<![CDATA[Muhi Masri RSS Feed]]>https://muhimasri.comGatsbyJSMon, 26 Jan 2026 13:24:04 GMT<![CDATA[Build a Customizable Next.js Blog with Material UI]]>https://muhimasri.comnextjs-mui-blog-starterhttps://muhimasri.comnextjs-mui-blog-starter<p>Developers always want to showcase or share their work, whether that’s through GitHub projects, technical blogs, or personal portfolios. Personally, I’ve found that writing blogs not only helps others, but also deepens my own knowledge and makes me more confident when working with teams and contributing to the community.</p> <p>I’ve rebuilt my blog and portfolio site three times already, and finally decided it was time to make it modular, scalable, and easy to maintain. So I built a Next.js starter that’s not only developer-friendly, but actually fun to work with.</p> <p>It comes with a bunch of useful features out of the box:</p> <ul> <li>Dark mode with token-based theming</li> <li>Dynamic Table of Contents (TOC) for each article</li> <li>MDX support with code highlighting built-in</li> <li>Optimized performance (90–100% Lighthouse scores)</li> <li>Clean component-based architecture for easy customization</li> <li>SEO-friendly with metadata and semantic URLs</li> <li>Simplistic and beautiful design</li> </ul> <p>In this tutorial, I’ll walk you through, step by step, how to build a blog and portfolio site using Next.js and Material UI (MUI). It will cover a well structured nextjs template to start from and customize it to your liking.</p> <p>Before we dive in, here’s a quick demo of the starter, a live version, and a link to the repo:</p> <video width="720" height="400" autoplay loop muted playsinline preload="none"> <source src="/bfe9aa5637c6524ae6c84eaa0df4edf0/blog-demo.mp4" type="video/mp4"> </video> <p><strong>GitHub Repo:</strong> <a href="https://github.com/muhimasri/nextjs-mui-blog-starter">nextjs starter repository</a></p> <p><strong>Live Demo:</strong> <a href="https://nextjs-mui-blog.muhimasri.com">nextjs blog demo</a></p> <h2 id="nextjs-setup" style="position:relative;"><a href="#nextjs-setup" aria-label="nextjs setup permalink" class="anchor before"><svg aria-hidden="true" focusable="false" height="16" version="1.1" viewBox="0 0 16 16" width="16"><path fill-rule="evenodd" d="M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z"></path></svg></a>Next.js Setup</h2> <p>Alright, let’s get the foundation in place with a fresh Next.js project. If you’ve done this before, feel free to skim.</p> <h3 id="create-the-project" style="position:relative;"><a href="#create-the-project" aria-label="create the project permalink" class="anchor before"><svg aria-hidden="true" focusable="false" height="16" version="1.1" viewBox="0 0 16 16" width="16"><path fill-rule="evenodd" d="M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z"></path></svg></a>Create the project</h3> <p>In your terminal, run:</p> <pre class="grvsc-container default-dark" data-language="bash" data-index="0"><code class="grvsc-code"><span class="grvsc-line"><span class="grvsc-source"><span class="mtk1">npx create-next-app@latest nextjs-mui-blog-starter</span></span></span></code></pre> <p>You’ll get a few prompts, things like TypeScript, App Router, Tailwind, etc. You can go with the defaults or tweak settings based on your preferences. The only must-do? Include the App Router, and skip Tailwind—we’re going with Material UI for this one (no hate on Tailwind; it’s just not what we’re using here).</p> <p>This setup uses the <code>app/</code> directory structure introduced in Next.js 13, which supports layouts and routing optimized for both performance and clarity.</p> <h3 id="run-the-dev-server" style="position:relative;"><a href="#run-the-dev-server" aria-label="run the dev server permalink" class="anchor before"><svg aria-hidden="true" focusable="false" height="16" version="1.1" viewBox="0 0 16 16" width="16"><path fill-rule="evenodd" d="M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z"></path></svg></a>Run the dev server</h3> <p>Once the setup finishes, go ahead and jump into the new directory:</p> <pre class="grvsc-container default-dark" data-language="bash" data-index="1"><code class="grvsc-code"><span class="grvsc-line"><span class="grvsc-source"><span class="mtk11">cd</span><span class="mtk1"> nextjs-mui-blog-starter</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1">npm run dev</span></span></span></code></pre> <p>You should see the usual Next.js welcome screen at <code>http://localhost:3000</code>. Nice!</p> <p><em>Pro tip: In <code>package.json</code>, you can modify the port to run your app on a different one, like 9000. Modify <code>"dev": "next dev -p 9000"</code> in the scripts section.</em></p> <h2 id="material-ui-setup" style="position:relative;"><a href="#material-ui-setup" aria-label="material ui setup permalink" class="anchor before"><svg aria-hidden="true" focusable="false" height="16" version="1.1" viewBox="0 0 16 16" width="16"><path fill-rule="evenodd" d="M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z"></path></svg></a>Material UI Setup</h2> <p>Now that Next.js is ready, let’s bring in Material UI (MUI) to style our application with a powerful and responsive component library. We’ll set up MUI into the project and shape a cohesive nextjs theme that’s consistent and accessible.</p> <h3 id="install-material-ui" style="position:relative;"><a href="#install-material-ui" aria-label="install material ui permalink" class="anchor before"><svg aria-hidden="true" focusable="false" height="16" version="1.1" viewBox="0 0 16 16" width="16"><path fill-rule="evenodd" d="M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z"></path></svg></a>Install Material UI</h3> <p>To get started, install MUI along with its required dependencies:</p> <pre class="grvsc-container default-dark" data-language="bash" data-index="2"><code class="grvsc-code"><span class="grvsc-line"><span class="grvsc-source"><span class="mtk1">npm install @mui/material @emotion/react @emotion/styled @mui/material-nextjs @emotion/cache</span></span></span></code></pre> <p><em>MUI uses <a href="https://emotion.sh/docs/introduction">Emotion</a> as its default styling engine. No need for global stylesheets or external CSS frameworks.</em></p> <p>The <code>@mui/material-nextjs</code> package simplifies server-side rendering with MUI in the Next.js App Router. Without it, you’d need to manually handle Emotion cache, inject styles into HTML streams, and manage SSR hydration mismatches.</p> <h3 id="clean-up-and-configure-mui" style="position:relative;"><a href="#clean-up-and-configure-mui" aria-label="clean up and configure mui permalink" class="anchor before"><svg aria-hidden="true" focusable="false" height="16" version="1.1" viewBox="0 0 16 16" width="16"><path fill-rule="evenodd" d="M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z"></path></svg></a>Clean Up and Configure MUI</h3> <p>Before adding custom components, let’s do a quick cleanup and MUI setup:</p> <ol> <li>Delete global CSS files like <code>globals.css</code> and <code>page.module.css</code>; we’ll use MUI’s <code>CssBaseline</code> instead.</li> <li>Remove the content in <code>page.tsx</code> so it starts clean.</li> </ol> <pre class="grvsc-container default-dark" data-language="tsx" data-index="3"><code class="grvsc-code"><span class="grvsc-line"><span class="grvsc-source"><span class="mtk15">export</span><span class="mtk1"> </span><span class="mtk15">default</span><span class="mtk1"> </span><span class="mtk4">function</span><span class="mtk1"> </span><span class="mtk11">Home</span><span class="mtk1">() {</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk15">return</span><span class="mtk1"> </span><span class="mtk17">&lt;</span><span class="mtk4">div</span><span class="mtk17">&gt;&lt;/</span><span class="mtk4">div</span><span class="mtk17">&gt;</span><span class="mtk1">;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1">}</span></span></span></code></pre> <ol start="3"> <li>Update <code>layout.tsx</code> to configure MUI’s SSR support and add a global style baseline:</li> </ol> <pre class="grvsc-container default-dark" data-language="tsx" data-index="4"><code class="grvsc-code"><span class="grvsc-line"><span class="grvsc-source"><span class="mtk15">import</span><span class="mtk1"> { </span><span class="mtk12">CssBaseline</span><span class="mtk1"> } </span><span class="mtk15">from</span><span class="mtk1"> </span><span class="mtk8">&quot;@mui/material&quot;</span><span class="mtk1">;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk15">import</span><span class="mtk1"> { </span><span class="mtk12">AppRouterCacheProvider</span><span class="mtk1"> } </span><span class="mtk15">from</span><span class="mtk1"> </span><span class="mtk8">&quot;@mui/material-nextjs/v15-appRouter&quot;</span><span class="mtk1">;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk15">export</span><span class="mtk1"> </span><span class="mtk15">default</span><span class="mtk1"> </span><span class="mtk4">function</span><span class="mtk1"> </span><span class="mtk11">RootLayout</span><span class="mtk1">({</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">children</span><span class="mtk1">,</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1">}: </span><span class="mtk10">Readonly</span><span class="mtk1">&lt;{</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">children</span><span class="mtk1">: </span><span class="mtk10">React</span><span class="mtk1">.</span><span class="mtk10">ReactNode</span><span class="mtk1">;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1">}&gt;) {</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk15">return</span><span class="mtk1"> (</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk17">&lt;</span><span class="mtk4">html</span><span class="mtk1"> </span><span class="mtk12">lang</span><span class="mtk1">=</span><span class="mtk8">&quot;en&quot;</span><span class="mtk17">&gt;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk17">&lt;</span><span class="mtk4">body</span><span class="mtk17">&gt;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk17">&lt;</span><span class="mtk10">AppRouterCacheProvider</span><span class="mtk17">&gt;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk17">&lt;</span><span class="mtk10">CssBaseline</span><span class="mtk1"> </span><span class="mtk17">/&gt;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk4">{</span><span class="mtk12">children</span><span class="mtk4">}</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk17">&lt;/</span><span class="mtk10">AppRouterCacheProvider</span><span class="mtk17">&gt;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk17">&lt;/</span><span class="mtk4">body</span><span class="mtk17">&gt;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk17">&lt;/</span><span class="mtk4">html</span><span class="mtk17">&gt;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> );</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1">}</span></span></span></code></pre> <ul> <li> <p><code>AppRouterCacheProvider</code>: Handles MUI’s server-generated styles as Next.js streams the page to the browser (<a href="https://mui.com/material-ui/integrations/nextjs/">learn more</a>)</p> </li> <li> <p><code>CssBaseline</code>: Applies consistent base styles (typography, color, layout) across browsers (<a href="https://mui.com/material-ui/react-css-baseline/">learn more</a>)</p> </li> </ul> <p>At this point, your app should render a clean, white page with no default Next.js styles.</p> <h3 id="test-mui-with-a-header-component" style="position:relative;"><a href="#test-mui-with-a-header-component" aria-label="test mui with a header component permalink" class="anchor before"><svg aria-hidden="true" focusable="false" height="16" version="1.1" viewBox="0 0 16 16" width="16"><path fill-rule="evenodd" d="M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z"></path></svg></a>Test MUI with a Header Component</h3> <p>Let’s test that MUI is working by building a quick header with navigation:</p> <p><code>components/Header.tsx</code></p> <pre class="grvsc-container default-dark" data-language="tsx" data-index="5"><code class="grvsc-code"><span class="grvsc-line"><span class="grvsc-source"><span class="mtk3">// Simple MUI AppBar component to validate Material UI setup</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk15">import</span><span class="mtk1"> </span><span class="mtk12">AppBar</span><span class="mtk1"> </span><span class="mtk15">from</span><span class="mtk1"> </span><span class="mtk8">&quot;@mui/material/AppBar&quot;</span><span class="mtk1">;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk15">import</span><span class="mtk1"> </span><span class="mtk12">Toolbar</span><span class="mtk1"> </span><span class="mtk15">from</span><span class="mtk1"> </span><span class="mtk8">&quot;@mui/material/Toolbar&quot;</span><span class="mtk1">;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk15">import</span><span class="mtk1"> </span><span class="mtk12">Typography</span><span class="mtk1"> </span><span class="mtk15">from</span><span class="mtk1"> </span><span class="mtk8">&quot;@mui/material/Typography&quot;</span><span class="mtk1">;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk15">import</span><span class="mtk1"> </span><span class="mtk12">Button</span><span class="mtk1"> </span><span class="mtk15">from</span><span class="mtk1"> </span><span class="mtk8">&quot;@mui/material/Button&quot;</span><span class="mtk1">;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk15">export</span><span class="mtk1"> </span><span class="mtk15">default</span><span class="mtk1"> </span><span class="mtk4">function</span><span class="mtk1"> </span><span class="mtk11">Header</span><span class="mtk1">() {</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk15">return</span><span class="mtk1"> (</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk17">&lt;</span><span class="mtk10">AppBar</span><span class="mtk1"> </span><span class="mtk12">position</span><span class="mtk1">=</span><span class="mtk8">&quot;static&quot;</span><span class="mtk17">&gt;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk17">&lt;</span><span class="mtk10">Toolbar</span><span class="mtk17">&gt;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk17">&lt;</span><span class="mtk10">Typography</span><span class="mtk1"> </span><span class="mtk12">variant</span><span class="mtk1">=</span><span class="mtk8">&quot;h6&quot;</span><span class="mtk1"> </span><span class="mtk12">mr</span><span class="mtk1">=</span><span class="mtk4">{</span><span class="mtk7">5</span><span class="mtk4">}</span><span class="mtk17">&gt;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> My Blog</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk17">&lt;/</span><span class="mtk10">Typography</span><span class="mtk17">&gt;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk17">&lt;</span><span class="mtk10">Button</span><span class="mtk1"> </span><span class="mtk12">color</span><span class="mtk1">=</span><span class="mtk8">&quot;inherit&quot;</span><span class="mtk17">&gt;</span><span class="mtk1">Home</span><span class="mtk17">&lt;/</span><span class="mtk10">Button</span><span class="mtk17">&gt;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk17">&lt;</span><span class="mtk10">Button</span><span class="mtk1"> </span><span class="mtk12">color</span><span class="mtk1">=</span><span class="mtk8">&quot;inherit&quot;</span><span class="mtk17">&gt;</span><span class="mtk1">Blog</span><span class="mtk17">&lt;/</span><span class="mtk10">Button</span><span class="mtk17">&gt;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk17">&lt;</span><span class="mtk10">Button</span><span class="mtk1"> </span><span class="mtk12">color</span><span class="mtk1">=</span><span class="mtk8">&quot;inherit&quot;</span><span class="mtk17">&gt;</span><span class="mtk1">About</span><span class="mtk17">&lt;/</span><span class="mtk10">Button</span><span class="mtk17">&gt;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk17">&lt;/</span><span class="mtk10">Toolbar</span><span class="mtk17">&gt;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk17">&lt;/</span><span class="mtk10">AppBar</span><span class="mtk17">&gt;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> );</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1">}</span></span></span></code></pre> <p>Then update <code>layout.tsx</code> to include the Header:</p> <pre class="grvsc-container default-dark" data-language="tsx" data-index="6"><code class="grvsc-code"><span class="grvsc-line"><span class="grvsc-source"><span class="mtk15">import</span><span class="mtk1"> { </span><span class="mtk12">CssBaseline</span><span class="mtk1"> } </span><span class="mtk15">from</span><span class="mtk1"> </span><span class="mtk8">&quot;@mui/material&quot;</span><span class="mtk1">;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk15">import</span><span class="mtk1"> { </span><span class="mtk12">AppRouterCacheProvider</span><span class="mtk1"> } </span><span class="mtk15">from</span><span class="mtk1"> </span><span class="mtk8">&quot;@mui/material-nextjs/v15-appRouter&quot;</span><span class="mtk1">;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk15">import</span><span class="mtk1"> </span><span class="mtk12">Header</span><span class="mtk1"> </span><span class="mtk15">from</span><span class="mtk1"> </span><span class="mtk8">&quot;./components/Header&quot;</span><span class="mtk1">;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk15">export</span><span class="mtk1"> </span><span class="mtk15">default</span><span class="mtk1"> </span><span class="mtk4">function</span><span class="mtk1"> </span><span class="mtk11">RootLayout</span><span class="mtk1">({</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">children</span><span class="mtk1">,</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1">}: </span><span class="mtk10">Readonly</span><span class="mtk1">&lt;{</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">children</span><span class="mtk1">: </span><span class="mtk10">React</span><span class="mtk1">.</span><span class="mtk10">ReactNode</span><span class="mtk1">;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1">}&gt;) {</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk15">return</span><span class="mtk1"> (</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk17">&lt;</span><span class="mtk4">html</span><span class="mtk1"> </span><span class="mtk12">lang</span><span class="mtk1">=</span><span class="mtk8">&quot;en&quot;</span><span class="mtk17">&gt;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk17">&lt;</span><span class="mtk4">body</span><span class="mtk17">&gt;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk17">&lt;</span><span class="mtk10">AppRouterCacheProvider</span><span class="mtk17">&gt;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk17">&lt;</span><span class="mtk10">CssBaseline</span><span class="mtk1"> </span><span class="mtk17">/&gt;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk17">&lt;</span><span class="mtk10">Header</span><span class="mtk1"> </span><span class="mtk17">/&gt;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk4">{</span><span class="mtk12">children</span><span class="mtk4">}</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk17">&lt;/</span><span class="mtk10">AppRouterCacheProvider</span><span class="mtk17">&gt;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk17">&lt;/</span><span class="mtk4">body</span><span class="mtk17">&gt;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk17">&lt;/</span><span class="mtk4">html</span><span class="mtk17">&gt;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> );</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1">}</span></span></span></code></pre> <p>If you see a blue top bar with “My Blog” and three navigation buttons, MUI is now integrated and rendering correctly!</p> <p><span class="gatsby-resp-image-wrapper" style="position: relative; display: block; margin-left: auto; margin-right: auto; max-width: 720px; " > <a class="gatsby-resp-image-link" href="/static/07dccd13bab8de81fb8d5828e39ba38d/3fca6/blog-header.png" style="display: block" target="_blank" rel="noopener" > <span class="gatsby-resp-image-background-image" style="padding-bottom: 60%; position: relative; bottom: 0; left: 0; background-image: url('data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABQAAAAMCAYAAABiDJ37AAAACXBIWXMAACToAAAk6AGCYwUcAAAAd0lEQVR42mPQbrrxX6/5xn+V2uv/NRqu/1eru/ZfqerSf6nyi/+lycAMB87d/b//7O3/e87c/r8XiI9effL/6tPP/y8/Jg8zfPrw7v+nj+//v3/7+v+bl8//f/vy6T8lgAGb4L9/5GOGf0ASHVPdhaMGjhqIHwAACu6UITDPrVcAAAAASUVORK5CYII='); background-size: cover; display: block;" ></span> <img class="gatsby-resp-image-image" alt="Header styled by the nextjs theme" title="" src="/static/07dccd13bab8de81fb8d5828e39ba38d/37523/blog-header.png" srcset="/static/07dccd13bab8de81fb8d5828e39ba38d/e9ff0/blog-header.png 180w, /static/07dccd13bab8de81fb8d5828e39ba38d/f21e7/blog-header.png 360w, /static/07dccd13bab8de81fb8d5828e39ba38d/37523/blog-header.png 720w, /static/07dccd13bab8de81fb8d5828e39ba38d/302a4/blog-header.png 1080w, /static/07dccd13bab8de81fb8d5828e39ba38d/3fca6/blog-header.png 1112w" sizes="(max-width: 720px) 100vw, 720px" style="width:100%;height:100%;margin:0;vertical-align:middle;position:absolute;top:0;left:0;" loading="lazy" decoding="async" /> </a> </span></p> <h2 id="mdx-setup" style="position:relative;"><a href="#mdx-setup" aria-label="mdx setup permalink" class="anchor before"><svg aria-hidden="true" focusable="false" height="16" version="1.1" viewBox="0 0 16 16" width="16"><path fill-rule="evenodd" d="M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z"></path></svg></a>MDX Setup</h2> <p>Now that we have Next.js and Material UI wired up, let’s add the ability to write blog posts using MDX, Markdown with embedded JSX.</p> <h3 id="install-mdx-dependencies" style="position:relative;"><a href="#install-mdx-dependencies" aria-label="install mdx dependencies permalink" class="anchor before"><svg aria-hidden="true" focusable="false" height="16" version="1.1" viewBox="0 0 16 16" width="16"><path fill-rule="evenodd" d="M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z"></path></svg></a>Install MDX Dependencies</h3> <p>MDX is one of the most flexible ways to author content in a React-based site, allowing your nextjs blog to support markdown with interactive components.</p> <p>To get started, install the required packages:</p> <pre class="grvsc-container default-dark" data-language="bash" data-index="7"><code class="grvsc-code"><span class="grvsc-line"><span class="grvsc-source"><span class="mtk1">npm install @next/mdx @mdx-js/loader @mdx-js/react @types/mdx</span></span></span></code></pre> <h3 id="configure-next" style="position:relative;"><a href="#configure-next" aria-label="configure next permalink" class="anchor before"><svg aria-hidden="true" focusable="false" height="16" version="1.1" viewBox="0 0 16 16" width="16"><path fill-rule="evenodd" d="M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z"></path></svg></a>Configure Next</h3> <p>Next, we’ll update the <code>next.config.ts</code> file to enable <code>.mdx</code> pages to be routed like normal React components:</p> <pre class="grvsc-container default-dark" data-language="ts" data-index="8"><code class="grvsc-code"><span class="grvsc-line"><span class="grvsc-source"><span class="mtk15">import</span><span class="mtk1"> </span><span class="mtk12">withMdx</span><span class="mtk1"> </span><span class="mtk15">from</span><span class="mtk1"> </span><span class="mtk8">&quot;@next/mdx&quot;</span><span class="mtk1">;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk4">const</span><span class="mtk1"> </span><span class="mtk12">nextConfig</span><span class="mtk1"> = {</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">pageExtensions:</span><span class="mtk1"> [</span><span class="mtk8">&quot;ts&quot;</span><span class="mtk1">, </span><span class="mtk8">&quot;tsx&quot;</span><span class="mtk1">, </span><span class="mtk8">&quot;js&quot;</span><span class="mtk1">, </span><span class="mtk8">&quot;jsx&quot;</span><span class="mtk1">, </span><span class="mtk8">&quot;mdx&quot;</span><span class="mtk1">],</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1">};</span></span></span> <span class="grvsc-line"><span class="grvsc-source"></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk4">const</span><span class="mtk1"> </span><span class="mtk12">mdxConfig</span><span class="mtk1"> = {</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk3">// You can add remark/rehype plugins here</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1">};</span></span></span> <span class="grvsc-line"><span class="grvsc-source"></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk15">export</span><span class="mtk1"> </span><span class="mtk15">default</span><span class="mtk1"> </span><span class="mtk11">withMdx</span><span class="mtk1">(</span><span class="mtk12">mdxConfig</span><span class="mtk1">)(</span><span class="mtk12">nextConfig</span><span class="mtk1">);</span></span></span></code></pre> <p>This configuration tells Next.js to treat <code>.mdx</code> files as valid page routes. The <code>@next/mdx</code> plugin automatically compiles them into React components that render just like <code>.tsx</code> files.</p> <h3 id="add-components-mapping" style="position:relative;"><a href="#add-components-mapping" aria-label="add components mapping permalink" class="anchor before"><svg aria-hidden="true" focusable="false" height="16" version="1.1" viewBox="0 0 16 16" width="16"><path fill-rule="evenodd" d="M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z"></path></svg></a>Add Components Mapping</h3> <p>With the App Router, we also need to define custom component mappings for MDX rendering.</p> <p>We can achieve this by creating a new file called <code>mdx-components.tsx</code> at the root of the <code>src/</code> directory:</p> <pre class="grvsc-container default-dark" data-language="tsx" data-index="9"><code class="grvsc-code"><span class="grvsc-line"><span class="grvsc-source"><span class="mtk15">import</span><span class="mtk1"> </span><span class="mtk12">type</span><span class="mtk1"> { </span><span class="mtk12">MDXComponents</span><span class="mtk1"> } </span><span class="mtk15">from</span><span class="mtk1"> </span><span class="mtk8">&quot;mdx/types&quot;</span><span class="mtk1">;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk15">export</span><span class="mtk1"> </span><span class="mtk4">function</span><span class="mtk1"> </span><span class="mtk11">useMDXComponents</span><span class="mtk1">(</span><span class="mtk12">components</span><span class="mtk1">: </span><span class="mtk10">MDXComponents</span><span class="mtk1">): </span><span class="mtk10">MDXComponents</span><span class="mtk1"> {</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk15">return</span><span class="mtk1"> {</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> ...</span><span class="mtk12">components</span><span class="mtk1">,</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> };</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1">}</span></span></span></code></pre> <p>The <code>useMDXComponents</code> hook allows us to customize how MDX elements are rendered throughout the application.</p> <h3 id="create-a-test-blog-post" style="position:relative;"><a href="#create-a-test-blog-post" aria-label="create a test blog post permalink" class="anchor before"><svg aria-hidden="true" focusable="false" height="16" version="1.1" viewBox="0 0 16 16" width="16"><path fill-rule="evenodd" d="M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z"></path></svg></a>Create a Test Blog Post</h3> <p>Let’s create a simple blog post to verify everything is working.</p> <ol> <li> <p>Inside the <code>app/</code> directory, create a folder called <code>blogs/</code></p> </li> <li> <p>Inside <code>blogs/</code>, create a new folder: <code>my-first-blog-post/</code></p> </li> <li> <p>Inside that folder, create a file named <code>page.mdx</code></p> </li> </ol> <pre class="grvsc-container default-dark" data-language="mdx" data-index="10"><code class="grvsc-code"><span class="grvsc-line"><span class="grvsc-source"># Introduction</span></span> <span class="grvsc-line"><span class="grvsc-source"></span></span> <span class="grvsc-line"><span class="grvsc-source">Welcome to my first blog post! In this post, I’ll share my journey of learning Next.js and Material UI. Stay tuned for more!</span></span> <span class="grvsc-line"><span class="grvsc-source"></span></span> <span class="grvsc-line"><span class="grvsc-source">## Setup</span></span> <span class="grvsc-line"><span class="grvsc-source"></span></span> <span class="grvsc-line"><span class="grvsc-source">To get started, we’ll install the latest Next.js version and create a new project:</span></span> <span class="grvsc-line"><span class="grvsc-source"></span></span> <span class="grvsc-line"><span class="grvsc-source">```bash</span></span> <span class="grvsc-line"><span class="grvsc-source">npx create-next-app@latest nextjs-mui-blog-starter</span></span> <span class="grvsc-line"><span class="grvsc-source">```</span></span></code></pre> <p>Now navigate to <a href="http://localhost:3000/blogs/my-first-blog-post">http://localhost:3000/blogs/my-first-blog-post</a> and boom, your MDX content should render just like any other page!</p> <p><strong>How It Works</strong></p> <p>The <strong>App Router</strong> in Next.js makes this possible by treating folders as route segments. Since <code>page.mdx</code> is a valid route file, it gets compiled and rendered automatically, just like <code>page.tsx</code>.</p> <p>We can nest routes, use dynamic segments (like <code>[slug]</code>), or structure our blog by date, tag, or category. All with native file-system routing.</p> <h3 id="final-structure-overview" style="position:relative;"><a href="#final-structure-overview" aria-label="final structure overview permalink" class="anchor before"><svg aria-hidden="true" focusable="false" height="16" version="1.1" viewBox="0 0 16 16" width="16"><path fill-rule="evenodd" d="M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z"></path></svg></a>Final Structure Overview</h3> <p>Here’s what your project should now look like:</p> <pre class="grvsc-container default-dark" data-language="plaintext" data-index="11"><code class="grvsc-code"><span class="grvsc-line"><span class="grvsc-source">nextjs-mui-blog-starter</span></span> <span class="grvsc-line"><span class="grvsc-source">├── app</span></span> <span class="grvsc-line"><span class="grvsc-source">│ ├── blogs</span></span> <span class="grvsc-line"><span class="grvsc-source">│ │ └── my-first-blog-post</span></span> <span class="grvsc-line"><span class="grvsc-source">│ │ └── page.mdx</span></span> <span class="grvsc-line"><span class="grvsc-source">│ ├── components</span></span> <span class="grvsc-line"><span class="grvsc-source">│ │ └── Header.tsx</span></span> <span class="grvsc-line"><span class="grvsc-source">│ ├── layouts</span></span> <span class="grvsc-line"><span class="grvsc-source">│ │ └── layout.tsx</span></span> <span class="grvsc-line"><span class="grvsc-source">├── mdx-components.tsx</span></span> <span class="grvsc-line"><span class="grvsc-source">├── next.config.ts</span></span> <span class="grvsc-line"><span class="grvsc-source">├── package.json</span></span> <span class="grvsc-line"><span class="grvsc-source">└── tsconfig.json</span></span></code></pre> <h2 id="building-a-blog" style="position:relative;"><a href="#building-a-blog" aria-label="building a blog permalink" class="anchor before"><svg aria-hidden="true" focusable="false" height="16" version="1.1" viewBox="0 0 16 16" width="16"><path fill-rule="evenodd" d="M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z"></path></svg></a>Building a Blog</h2> <p>Now that the foundation is in place, let’s start building the actual blog experience. This is where things get fun and a bit more dynamic.</p> <h3 id="understanding-dynamic-routing" style="position:relative;"><a href="#understanding-dynamic-routing" aria-label="understanding dynamic routing permalink" class="anchor before"><svg aria-hidden="true" focusable="false" height="16" version="1.1" viewBox="0 0 16 16" width="16"><path fill-rule="evenodd" d="M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z"></path></svg></a>Understanding Dynamic Routing</h3> <p>Next.js App Router supports dynamic segments using square brackets like <code>[slug]</code>. That is perfect for content-driven pages such as blogs, docs, or portfolios because the URL becomes the source of truth for which content to render.</p> <p><em>SEO Tip: Using slug-based folders and filenames keeps URLs semantic and helps both search engines and generative engines map each route to a specific content source.</em></p> <p><strong>Let’s break it down:</strong></p> <p>A folder named <code>[slug]</code> inside <code>app/blogs/</code> tells Next.js that anything matching <code>/blogs/\*</code> should be routed to this segment.</p> <p>When a request comes in (e.g., <code>/blogs/my-first-post</code>), the part after <code>/blogs/</code> (my-first-post) is passed as a parameter to your route.</p> <p>You can then use that slug to fetch content, metadata, and render it dynamically.</p> <h3 id="loading-dynamic-content" style="position:relative;"><a href="#loading-dynamic-content" aria-label="loading dynamic content permalink" class="anchor before"><svg aria-hidden="true" focusable="false" height="16" version="1.1" viewBox="0 0 16 16" width="16"><path fill-rule="evenodd" d="M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z"></path></svg></a>Loading Dynamic Content</h3> <p>Inside <code>app/blogs/</code>, we’ll create <code>[slug]/page.tsx</code>. Start with a minimal page so routing is set up cleanly:</p> <pre class="grvsc-container default-dark" data-language="tsx" data-index="12"><code class="grvsc-code"><span class="grvsc-line"><span class="grvsc-source"><span class="mtk15">import</span><span class="mtk1"> { </span><span class="mtk12">readdirSync</span><span class="mtk1"> } </span><span class="mtk15">from</span><span class="mtk1"> </span><span class="mtk8">&quot;fs&quot;</span><span class="mtk1">;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk15">import</span><span class="mtk1"> </span><span class="mtk12">path</span><span class="mtk1"> </span><span class="mtk15">from</span><span class="mtk1"> </span><span class="mtk8">&quot;path&quot;</span><span class="mtk1">;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk4">interface</span><span class="mtk1"> </span><span class="mtk10">BlogPostPageProps</span><span class="mtk1"> {</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">params</span><span class="mtk1">: { </span><span class="mtk12">slug</span><span class="mtk1">: </span><span class="mtk10">string</span><span class="mtk1"> };</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1">}</span></span></span> <span class="grvsc-line"><span class="grvsc-source"></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk15">export</span><span class="mtk1"> </span><span class="mtk15">default</span><span class="mtk1"> </span><span class="mtk4">async</span><span class="mtk1"> </span><span class="mtk4">function</span><span class="mtk1"> </span><span class="mtk11">BlogPostPage</span><span class="mtk1">({ </span><span class="mtk12">params</span><span class="mtk1"> }: </span><span class="mtk10">BlogPostPageProps</span><span class="mtk1">) {</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk4">const</span><span class="mtk1"> { </span><span class="mtk12">slug</span><span class="mtk1"> } = </span><span class="mtk15">await</span><span class="mtk1"> </span><span class="mtk12">params</span><span class="mtk1">;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk15">return</span><span class="mtk1"> (</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk17">&lt;</span><span class="mtk4">div</span><span class="mtk17">&gt;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk17">&lt;</span><span class="mtk4">h1</span><span class="mtk17">&gt;</span><span class="mtk4">{</span><span class="mtk12">slug</span><span class="mtk4">}</span><span class="mtk17">&lt;/</span><span class="mtk4">h1</span><span class="mtk17">&gt;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk17">&lt;/</span><span class="mtk4">div</span><span class="mtk17">&gt;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> );</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1">}</span></span></span> <span class="grvsc-line"><span class="grvsc-source"></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk3">// Return all slugs for SSG</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk15">export</span><span class="mtk1"> </span><span class="mtk4">async</span><span class="mtk1"> </span><span class="mtk4">function</span><span class="mtk1"> </span><span class="mtk11">generateStaticParams</span><span class="mtk1">() {</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk4">const</span><span class="mtk1"> </span><span class="mtk12">blogDir</span><span class="mtk1"> = </span><span class="mtk12">path</span><span class="mtk1">.</span><span class="mtk11">join</span><span class="mtk1">(</span><span class="mtk12">process</span><span class="mtk1">.</span><span class="mtk11">cwd</span><span class="mtk1">(), </span><span class="mtk8">&quot;content/blogs&quot;</span><span class="mtk1">);</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk4">const</span><span class="mtk1"> </span><span class="mtk12">slugs</span><span class="mtk1"> = </span><span class="mtk11">readdirSync</span><span class="mtk1">(</span><span class="mtk12">blogDir</span><span class="mtk1">);</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk15">return</span><span class="mtk1"> </span><span class="mtk12">slugs</span><span class="mtk1">.</span><span class="mtk11">map</span><span class="mtk1">(</span><span class="mtk12">slug</span><span class="mtk1"> </span><span class="mtk4">=&gt;</span><span class="mtk1"> ({ </span><span class="mtk12">slug</span><span class="mtk1"> }));</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1">}</span></span></span></code></pre> <p><strong>What’s happening here?</strong></p> <ul> <li><code>generateStaticParams</code> tells Next.js which paths to statically pre-render at build time.</li> <li>We’re scanning the blog directory and generating a list of slugs based on folder names.</li> <li>The <code>[slug]</code> parameter becomes available inside the <code>BlogPostPage</code> component, giving us dynamic access to the requested post.</li> </ul> <p><strong>Important routing note</strong></p> <p>When visiting <a href="http://localhost:3000/blogs/my-first-blog-post">http://localhost:3000/blogs/my-first-blog-post</a>, you may still see the original static page we created inside <code>app/</code> instead of the dynamic one with the slug value. Next.js gives static routes precedence over dynamic ones inside the project. To avoid unexpected behavior and keep the content separate from the project’s main routing, store all blog posts in a top-level <code>content/blogs</code> folder outside <code>app/</code>. Think of <code>content/</code> as your CMS or database. It prevents accidental route collisions and keeps the App Router focused on UI, not raw content files.</p> <p>A clean layout looks like this:</p> <pre class="grvsc-container default-dark" data-language="plaintext" data-index="13"><code class="grvsc-code"><span class="grvsc-line"><span class="grvsc-source">nextjs-mui-blog-starter</span></span> <span class="grvsc-line"><span class="grvsc-source">├── src</span></span> <span class="grvsc-line"><span class="grvsc-source">│ ├── app</span></span> <span class="grvsc-line"><span class="grvsc-source">│ │ └── blogs</span></span> <span class="grvsc-line"><span class="grvsc-source">│ │ └── [slug]</span></span> <span class="grvsc-line"><span class="grvsc-source">│ │ └── page.tsx</span></span> <span class="grvsc-line"><span class="grvsc-source">├── content</span></span> <span class="grvsc-line"><span class="grvsc-source">│ ├── blogs</span></span> <span class="grvsc-line"><span class="grvsc-source">│ │ ├── my-first-blog-post</span></span> <span class="grvsc-line"><span class="grvsc-source">│ │ │ └── page.mdx</span></span> <span class="grvsc-line"><span class="grvsc-source">│ │ └── my-second-blog-post</span></span> <span class="grvsc-line"><span class="grvsc-source">│ │ └── page.mdx</span></span></code></pre> <p>At this point, visiting <a href="http://localhost:3000/blogs/my-first-blog-post">http://localhost:3000/blogs/my-first-blog-post</a> should display the slug, but no content yet.</p> <p><span class="gatsby-resp-image-wrapper" style="position: relative; display: block; margin-left: auto; margin-right: auto; max-width: 720px; " > <a class="gatsby-resp-image-link" href="/static/07dccd13bab8de81fb8d5828e39ba38d/3fca6/blog-header.png" style="display: block" target="_blank" rel="noopener" > <span class="gatsby-resp-image-background-image" style="padding-bottom: 60%; position: relative; bottom: 0; left: 0; background-image: url('data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABQAAAAMCAYAAABiDJ37AAAACXBIWXMAACToAAAk6AGCYwUcAAAAd0lEQVR42mPQbrrxX6/5xn+V2uv/NRqu/1eru/ZfqerSf6nyi/+lycAMB87d/b//7O3/e87c/r8XiI9effL/6tPP/y8/Jg8zfPrw7v+nj+//v3/7+v+bl8//f/vy6T8lgAGb4L9/5GOGf0ASHVPdhaMGjhqIHwAACu6UITDPrVcAAAAASUVORK5CYII='); background-size: cover; display: block;" ></span> <img class="gatsby-resp-image-image" alt="Default Theme" title="" src="/static/07dccd13bab8de81fb8d5828e39ba38d/37523/blog-header.png" srcset="/static/07dccd13bab8de81fb8d5828e39ba38d/e9ff0/blog-header.png 180w, /static/07dccd13bab8de81fb8d5828e39ba38d/f21e7/blog-header.png 360w, /static/07dccd13bab8de81fb8d5828e39ba38d/37523/blog-header.png 720w, /static/07dccd13bab8de81fb8d5828e39ba38d/302a4/blog-header.png 1080w, /static/07dccd13bab8de81fb8d5828e39ba38d/3fca6/blog-header.png 1112w" sizes="(max-width: 720px) 100vw, 720px" style="width:100%;height:100%;margin:0;vertical-align:middle;position:absolute;top:0;left:0;" loading="lazy" decoding="async" /> </a> </span></p> <h3 id="loading-mdx-content" style="position:relative;"><a href="#loading-mdx-content" aria-label="loading mdx content permalink" class="anchor before"><svg aria-hidden="true" focusable="false" height="16" version="1.1" viewBox="0 0 16 16" width="16"><path fill-rule="evenodd" d="M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z"></path></svg></a>Loading MDX Content</h3> <p>With React 19, <code>next-mdx-remote</code> has not been updated and has known issues. We will use <code>next-mdx-remote-client</code> instead. It works well with the App Router and keeps MDX rendering on the server in an RSC-friendly fashion.</p> <pre class="grvsc-container default-dark" data-language="bash" data-index="14"><code class="grvsc-code"><span class="grvsc-line"><span class="grvsc-source"><span class="mtk1">npm install next-mdx-remote-client</span></span></span></code></pre> <p>In <code>app/blogs/[slug]/page.tsx</code>, we will update the code to load and render each post:</p> <pre class="grvsc-container default-dark" data-language="tsx" data-index="15"><code class="grvsc-code"><span class="grvsc-line"><span class="grvsc-source"><span class="mtk15">import</span><span class="mtk1"> { </span><span class="mtk12">readdirSync</span><span class="mtk1">, </span><span class="mtk12">readFileSync</span><span class="mtk1"> } </span><span class="mtk15">from</span><span class="mtk1"> </span><span class="mtk8">&quot;fs&quot;</span><span class="mtk1">;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk15">import</span><span class="mtk1"> { </span><span class="mtk12">MDXRemote</span><span class="mtk1"> } </span><span class="mtk15">from</span><span class="mtk1"> </span><span class="mtk8">&quot;next-mdx-remote-client/rsc&quot;</span><span class="mtk1">;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk15">import</span><span class="mtk1"> </span><span class="mtk12">path</span><span class="mtk1"> </span><span class="mtk15">from</span><span class="mtk1"> </span><span class="mtk8">&quot;path&quot;</span><span class="mtk1">;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk4">interface</span><span class="mtk1"> </span><span class="mtk10">BlogPostPageProps</span><span class="mtk1"> {</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">params</span><span class="mtk1">: { </span><span class="mtk12">slug</span><span class="mtk1">: </span><span class="mtk10">string</span><span class="mtk1"> };</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1">}</span></span></span> <span class="grvsc-line"><span class="grvsc-source"></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk15">export</span><span class="mtk1"> </span><span class="mtk15">default</span><span class="mtk1"> </span><span class="mtk4">async</span><span class="mtk1"> </span><span class="mtk4">function</span><span class="mtk1"> </span><span class="mtk11">BlogPostPage</span><span class="mtk1">({ </span><span class="mtk12">params</span><span class="mtk1"> }: </span><span class="mtk10">BlogPostPageProps</span><span class="mtk1">) {</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk4">const</span><span class="mtk1"> { </span><span class="mtk12">slug</span><span class="mtk1"> } = </span><span class="mtk15">await</span><span class="mtk1"> </span><span class="mtk12">params</span><span class="mtk1">;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk4">const</span><span class="mtk1"> </span><span class="mtk12">filePath</span><span class="mtk1"> = </span><span class="mtk12">path</span><span class="mtk1">.</span><span class="mtk11">join</span><span class="mtk1">(</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">process</span><span class="mtk1">.</span><span class="mtk11">cwd</span><span class="mtk1">(),</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk8">&quot;content&quot;</span><span class="mtk1">,</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk8">&quot;blogs&quot;</span><span class="mtk1">,</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">slug</span><span class="mtk1">,</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk8">&quot;page.mdx&quot;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> );</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk4">const</span><span class="mtk1"> </span><span class="mtk12">fileContents</span><span class="mtk1"> = </span><span class="mtk11">readFileSync</span><span class="mtk1">(</span><span class="mtk12">filePath</span><span class="mtk1">, </span><span class="mtk8">&quot;utf8&quot;</span><span class="mtk1">);</span></span></span> <span class="grvsc-line"><span class="grvsc-source"></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk15">return</span><span class="mtk1"> (</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk17">&lt;</span><span class="mtk4">div</span><span class="mtk17">&gt;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk17">&lt;</span><span class="mtk4">h1</span><span class="mtk17">&gt;</span><span class="mtk4">{</span><span class="mtk12">slug</span><span class="mtk4">}</span><span class="mtk17">&lt;/</span><span class="mtk4">h1</span><span class="mtk17">&gt;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk17">&lt;</span><span class="mtk10">MDXRemote</span><span class="mtk1"> </span><span class="mtk12">source</span><span class="mtk1">=</span><span class="mtk4">{</span><span class="mtk12">fileContents</span><span class="mtk4">}</span><span class="mtk1"> </span><span class="mtk17">/&gt;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk17">&lt;/</span><span class="mtk4">div</span><span class="mtk17">&gt;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> );</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1">}</span></span></span> <span class="grvsc-line"><span class="grvsc-source"></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk3">// Return all slugs for SSG</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk15">export</span><span class="mtk1"> </span><span class="mtk4">async</span><span class="mtk1"> </span><span class="mtk4">function</span><span class="mtk1"> </span><span class="mtk11">generateStaticParams</span><span class="mtk1">() {</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk4">const</span><span class="mtk1"> </span><span class="mtk12">blogDir</span><span class="mtk1"> = </span><span class="mtk12">path</span><span class="mtk1">.</span><span class="mtk11">join</span><span class="mtk1">(</span><span class="mtk12">process</span><span class="mtk1">.</span><span class="mtk11">cwd</span><span class="mtk1">(), </span><span class="mtk8">&quot;content/blogs&quot;</span><span class="mtk1">);</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk4">const</span><span class="mtk1"> </span><span class="mtk12">slugs</span><span class="mtk1"> = </span><span class="mtk11">readdirSync</span><span class="mtk1">(</span><span class="mtk12">blogDir</span><span class="mtk1">);</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk15">return</span><span class="mtk1"> </span><span class="mtk12">slugs</span><span class="mtk1">.</span><span class="mtk11">map</span><span class="mtk1">(</span><span class="mtk12">slug</span><span class="mtk1"> </span><span class="mtk4">=&gt;</span><span class="mtk1"> ({ </span><span class="mtk12">slug</span><span class="mtk1"> }));</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1">}</span></span></span></code></pre> <p><strong>What this does</strong></p> <ul> <li>Reads the <code>.mdx</code> file for the requested slug from <code>content/blogs/&#x3C;slug>/page.mdx</code>.</li> <li>Renders it with <code>&#x3C;MDXRemote source={fileContents} /></code>.</li> </ul> <p>To test this out on multiple blogs, we can create another folder and MDX file for a new blog post.</p> <p><code>content/blogs/my-second-blog-post/page.mdx</code></p> <pre class="grvsc-container default-dark" data-language="mdx" data-index="16"><code class="grvsc-code"><span class="grvsc-line"><span class="grvsc-source"># Introduction</span></span> <span class="grvsc-line"><span class="grvsc-source"></span></span> <span class="grvsc-line"><span class="grvsc-source">Welcome to my second blog post! In this post, I’ll share my journey of learning MDX and how it integrates with Next.js.</span></span> <span class="grvsc-line"><span class="grvsc-source"></span></span> <span class="grvsc-line"><span class="grvsc-source">## Setup</span></span> <span class="grvsc-line"><span class="grvsc-source"></span></span> <span class="grvsc-line"><span class="grvsc-source">To get started, we’ll install the latest MDX packages:</span></span> <span class="grvsc-line"><span class="grvsc-source"></span></span> <span class="grvsc-line"><span class="grvsc-source">```bash</span></span> <span class="grvsc-line"><span class="grvsc-source">npm install @mdx-js/react</span></span> <span class="grvsc-line"><span class="grvsc-source">```</span></span></code></pre> <p>If everything is set up correctly, visiting the following URLs should render the respective blog posts:</p> <ul> <li><a href="http://localhost:3000/blogs/my-first-blog-post">http://localhost:3000/blogs/my-first-blog-post</a></li> <li><a href="http://localhost:3000/blogs/my-second-blog-post">http://localhost:3000/blogs/my-second-blog-post</a></li> </ul> <p><span class="gatsby-resp-image-wrapper" style="position: relative; display: block; margin-left: auto; margin-right: auto; max-width: 720px; " > <a class="gatsby-resp-image-link" href="/static/be77e24b46ad6c188d3b9376c0ebd198/1ed3b/dynamic-routing.png" style="display: block" target="_blank" rel="noopener" > <span class="gatsby-resp-image-background-image" style="padding-bottom: 42.22222222222223%; position: relative; bottom: 0; left: 0; background-image: url('data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABQAAAAICAYAAAD5nd/tAAAACXBIWXMAACToAAAk6AGCYwUcAAABIUlEQVR42rVQTUvDQBDNn68HW8TUo5eC1K/aH+JFJC0pWqXbgm4Mcc0mm02zSfPc3dAQUcSLA48ZmDdv3ozTHy9weObjYDTD4PwBJ1MC93oFd9JgOF2jP/bRO73F4OIRvZGnuR6OLpcY3pCW504Ijq98OMHrBgYsolAqRzfqurZZCIGFP8d7+KJ5AXgcoSwVfgpnRdYgZIM45thuC6Qig8ikztLWmczxFka4u/csj7EPFIVCpjlCNEj1QjNTlhUcSqkuSux2O1RV1eY9TPAkgTebW1dKqbZnuN0565AxBs65dhgj0YNpmlrkeW4XNSdnWD49a1eZ5ZgspWxf8uVkM2S2FkVhN+0ddH9ozqM0sC5Mv9v7Jog/hBEM9R9/E/o3wU/+xF/qfHQ8wwAAAABJRU5ErkJggg=='); background-size: cover; display: block;" ></span> <img class="gatsby-resp-image-image" alt="Dynamic Routing" title="" src="/static/be77e24b46ad6c188d3b9376c0ebd198/37523/dynamic-routing.png" srcset="/static/be77e24b46ad6c188d3b9376c0ebd198/e9ff0/dynamic-routing.png 180w, /static/be77e24b46ad6c188d3b9376c0ebd198/f21e7/dynamic-routing.png 360w, /static/be77e24b46ad6c188d3b9376c0ebd198/37523/dynamic-routing.png 720w, /static/be77e24b46ad6c188d3b9376c0ebd198/302a4/dynamic-routing.png 1080w, /static/be77e24b46ad6c188d3b9376c0ebd198/07a9c/dynamic-routing.png 1440w, /static/be77e24b46ad6c188d3b9376c0ebd198/1ed3b/dynamic-routing.png 3790w" sizes="(max-width: 720px) 100vw, 720px" style="width:100%;height:100%;margin:0;vertical-align:middle;position:absolute;top:0;left:0;" loading="lazy" decoding="async" /> </a> </span></p> <h2 id="frontmatter-and-metadata" style="position:relative;"><a href="#frontmatter-and-metadata" aria-label="frontmatter and metadata permalink" class="anchor before"><svg aria-hidden="true" focusable="false" height="16" version="1.1" viewBox="0 0 16 16" width="16"><path fill-rule="evenodd" d="M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z"></path></svg></a>Frontmatter and Metadata</h2> <p>Frontmatter is a block of structured data (usually in YAML or JSON) placed at the top of Markdown or MDX files. It’s commonly used to store metadata like:</p> <ul> <li>Title</li> <li>Description</li> <li>Date</li> <li>Author</li> <li>Tags</li> </ul> <p>This metadata helps you build SEO-friendly pages, dynamic lists of posts, and consistent layouts. All without hardcoding details into the component.</p> <h3 id="add-frontmatter-to-blog-posts" style="position:relative;"><a href="#add-frontmatter-to-blog-posts" aria-label="add frontmatter to blog posts permalink" class="anchor before"><svg aria-hidden="true" focusable="false" height="16" version="1.1" viewBox="0 0 16 16" width="16"><path fill-rule="evenodd" d="M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z"></path></svg></a>Add Frontmatter to Blog Posts</h3> <p>Let’s update each post with a frontmatter block as follows:</p> <p><code>my-first-blog-post/page.mdx</code></p> <pre class="grvsc-container default-dark" data-language="mdx" data-index="17"><code class="grvsc-code"><span class="grvsc-line"><span class="grvsc-source">---</span></span> <span class="grvsc-line"><span class="grvsc-source">title: My First Blog Post</span></span> <span class="grvsc-line"><span class="grvsc-source">description: Welcome to my first blog post! In this post, I will share my journey of learning Next.js and Material UI. Stay tuned for more exciting content!</span></span> <span class="grvsc-line"><span class="grvsc-source">date: &quot;2022-01-01&quot;</span></span> <span class="grvsc-line"><span class="grvsc-source">author: Mareli Ramos</span></span> <span class="grvsc-line"><span class="grvsc-source">tags: nextjs, material-ui</span></span> <span class="grvsc-line"><span class="grvsc-source">---</span></span> <span class="grvsc-line"><span class="grvsc-source"></span></span> <span class="grvsc-line"><span class="grvsc-source"># Introduction</span></span> <span class="grvsc-line"><span class="grvsc-source"></span></span> <span class="grvsc-line"><span class="grvsc-source">Your content goes here...</span></span></code></pre> <p><code>my-second-blog-post/page.mdx</code></p> <pre class="grvsc-container default-dark" data-language="mdx" data-index="18"><code class="grvsc-code"><span class="grvsc-line"><span class="grvsc-source">---</span></span> <span class="grvsc-line"><span class="grvsc-source">title: My Second Blog Post</span></span> <span class="grvsc-line"><span class="grvsc-source">description: Welcome to my second blog post! This is a page created using MDX.</span></span> <span class="grvsc-line"><span class="grvsc-source">date: &quot;2022-01-02&quot;</span></span> <span class="grvsc-line"><span class="grvsc-source">author: Mareli Ramos</span></span> <span class="grvsc-line"><span class="grvsc-source">tags: mdx, react</span></span> <span class="grvsc-line"><span class="grvsc-source">---</span></span> <span class="grvsc-line"><span class="grvsc-source"></span></span> <span class="grvsc-line"><span class="grvsc-source"># Introduction</span></span> <span class="grvsc-line"><span class="grvsc-source"></span></span> <span class="grvsc-line"><span class="grvsc-source">Your content goes here...</span></span></code></pre> <h3 id="parsing-frontmatter" style="position:relative;"><a href="#parsing-frontmatter" aria-label="parsing frontmatter permalink" class="anchor before"><svg aria-hidden="true" focusable="false" height="16" version="1.1" viewBox="0 0 16 16" width="16"><path fill-rule="evenodd" d="M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z"></path></svg></a>Parsing Frontmatter</h3> <p>To extract frontmatter from each post, we’ll use the <code>gray-matter</code> package. It’s fast, lightweight, and handles both YAML and JSON.</p> <pre class="grvsc-container default-dark" data-language="bash" data-index="19"><code class="grvsc-code"><span class="grvsc-line"><span class="grvsc-source"><span class="mtk1">npm install gray-matter</span></span></span></code></pre> <p>In <code>app/blogs/[slug]/page.tsx</code>, extract frontmatter and render it alongside the MDX content:</p> <pre class="grvsc-container grvsc-has-line-highlighting default-dark" data-language="tsx" data-index="20"><code class="grvsc-code"><span class="grvsc-line"><span class="grvsc-source"><span class="mtk15">import</span><span class="mtk1"> { </span><span class="mtk12">readdirSync</span><span class="mtk1">, </span><span class="mtk12">readFileSync</span><span class="mtk1"> } </span><span class="mtk15">from</span><span class="mtk1"> </span><span class="mtk8">&quot;fs&quot;</span><span class="mtk1">;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk15">import</span><span class="mtk1"> </span><span class="mtk12">matter</span><span class="mtk1"> </span><span class="mtk15">from</span><span class="mtk1"> </span><span class="mtk8">&quot;gray-matter&quot;</span><span class="mtk1">;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk15">import</span><span class="mtk1"> { </span><span class="mtk12">MDXRemote</span><span class="mtk1"> } </span><span class="mtk15">from</span><span class="mtk1"> </span><span class="mtk8">&quot;next-mdx-remote-client/rsc&quot;</span><span class="mtk1">;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk15">import</span><span class="mtk1"> </span><span class="mtk12">path</span><span class="mtk1"> </span><span class="mtk15">from</span><span class="mtk1"> </span><span class="mtk8">&quot;path&quot;</span><span class="mtk1">;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk4">interface</span><span class="mtk1"> </span><span class="mtk10">BlogPostPageProps</span><span class="mtk1"> {</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">params</span><span class="mtk1">: { </span><span class="mtk12">slug</span><span class="mtk1">: </span><span class="mtk10">string</span><span class="mtk1"> };</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1">}</span></span></span> <span class="grvsc-line"><span class="grvsc-source"></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk15">export</span><span class="mtk1"> </span><span class="mtk15">default</span><span class="mtk1"> </span><span class="mtk4">async</span><span class="mtk1"> </span><span class="mtk4">function</span><span class="mtk1"> </span><span class="mtk11">BlogPostPage</span><span class="mtk1">({ </span><span class="mtk12">params</span><span class="mtk1"> }: </span><span class="mtk10">BlogPostPageProps</span><span class="mtk1">) {</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk4">const</span><span class="mtk1"> { </span><span class="mtk12">slug</span><span class="mtk1"> } = </span><span class="mtk15">await</span><span class="mtk1"> </span><span class="mtk12">params</span><span class="mtk1">;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk4">const</span><span class="mtk1"> </span><span class="mtk12">filePath</span><span class="mtk1"> = </span><span class="mtk12">path</span><span class="mtk1">.</span><span class="mtk11">join</span><span class="mtk1">(</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">process</span><span class="mtk1">.</span><span class="mtk11">cwd</span><span class="mtk1">(),</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk8">&quot;content&quot;</span><span class="mtk1">,</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk8">&quot;blogs&quot;</span><span class="mtk1">,</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">slug</span><span class="mtk1">,</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk8">&quot;page.mdx&quot;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> );</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk4">const</span><span class="mtk1"> </span><span class="mtk12">fileContents</span><span class="mtk1"> = </span><span class="mtk11">readFileSync</span><span class="mtk1">(</span><span class="mtk12">filePath</span><span class="mtk1">, </span><span class="mtk8">&quot;utf8&quot;</span><span class="mtk1">);</span></span></span> <span class="grvsc-line"><span class="grvsc-source"></span></span> <span class="grvsc-line grvsc-line-highlighted"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk4">const</span><span class="mtk1"> { </span><span class="mtk12">content</span><span class="mtk1">, </span><span class="mtk12">data</span><span class="mtk1">: </span><span class="mtk12">frontmatter</span><span class="mtk1"> } = </span><span class="mtk11">matter</span><span class="mtk1">(</span><span class="mtk12">fileContents</span><span class="mtk1">);</span></span></span> <span class="grvsc-line"><span class="grvsc-source"></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk15">return</span><span class="mtk1"> (</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk17">&lt;</span><span class="mtk4">div</span><span class="mtk17">&gt;</span></span></span> <span class="grvsc-line grvsc-line-highlighted"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk17">&lt;</span><span class="mtk4">h1</span><span class="mtk17">&gt;</span><span class="mtk4">{</span><span class="mtk12">frontmatter</span><span class="mtk1">.</span><span class="mtk12">title</span><span class="mtk4">}</span><span class="mtk17">&lt;/</span><span class="mtk4">h1</span><span class="mtk17">&gt;</span></span></span> <span class="grvsc-line grvsc-line-highlighted"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk17">&lt;</span><span class="mtk4">p</span><span class="mtk17">&gt;</span><span class="mtk4">{</span><span class="mtk12">frontmatter</span><span class="mtk1">.</span><span class="mtk12">date</span><span class="mtk4">}</span><span class="mtk17">&lt;/</span><span class="mtk4">p</span><span class="mtk17">&gt;</span></span></span> <span class="grvsc-line grvsc-line-highlighted"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk17">&lt;</span><span class="mtk4">p</span><span class="mtk17">&gt;</span><span class="mtk4">{</span><span class="mtk12">frontmatter</span><span class="mtk1">.</span><span class="mtk12">author</span><span class="mtk4">}</span><span class="mtk17">&lt;/</span><span class="mtk4">p</span><span class="mtk17">&gt;</span></span></span> <span class="grvsc-line grvsc-line-highlighted"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk17">&lt;</span><span class="mtk4">p</span><span class="mtk17">&gt;</span><span class="mtk4">{</span><span class="mtk12">frontmatter</span><span class="mtk1">.</span><span class="mtk12">description</span><span class="mtk4">}</span><span class="mtk17">&lt;/</span><span class="mtk4">p</span><span class="mtk17">&gt;</span></span></span> <span class="grvsc-line grvsc-line-highlighted"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk17">&lt;</span><span class="mtk4">p</span><span class="mtk17">&gt;</span><span class="mtk4">{</span><span class="mtk12">frontmatter</span><span class="mtk1">.</span><span class="mtk12">tags</span><span class="mtk4">}</span><span class="mtk17">&lt;/</span><span class="mtk4">p</span><span class="mtk17">&gt;</span></span></span> <span class="grvsc-line grvsc-line-highlighted"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk17">&lt;</span><span class="mtk10">MDXRemote</span><span class="mtk1"> </span><span class="mtk12">source</span><span class="mtk1">=</span><span class="mtk4">{</span><span class="mtk12">content</span><span class="mtk4">}</span><span class="mtk1"> </span><span class="mtk17">/&gt;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk17">&lt;/</span><span class="mtk4">div</span><span class="mtk17">&gt;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> );</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1">}</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk3">// Scans the content/blogs folder to return all slugs for SSG</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk15">export</span><span class="mtk1"> </span><span class="mtk4">async</span><span class="mtk1"> </span><span class="mtk4">function</span><span class="mtk1"> </span><span class="mtk11">generateStaticParams</span><span class="mtk1">() {</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk4">const</span><span class="mtk1"> </span><span class="mtk12">blogDir</span><span class="mtk1"> = </span><span class="mtk12">path</span><span class="mtk1">.</span><span class="mtk11">join</span><span class="mtk1">(</span><span class="mtk12">process</span><span class="mtk1">.</span><span class="mtk11">cwd</span><span class="mtk1">(), </span><span class="mtk8">&quot;content/blogs&quot;</span><span class="mtk1">);</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk4">const</span><span class="mtk1"> </span><span class="mtk12">slugs</span><span class="mtk1"> = </span><span class="mtk11">readdirSync</span><span class="mtk1">(</span><span class="mtk12">blogDir</span><span class="mtk1">);</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk15">return</span><span class="mtk1"> </span><span class="mtk12">slugs</span><span class="mtk1">.</span><span class="mtk11">map</span><span class="mtk1">(</span><span class="mtk12">slug</span><span class="mtk1"> </span><span class="mtk4">=&gt;</span><span class="mtk1"> ({ </span><span class="mtk12">slug</span><span class="mtk1"> }));</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1">}</span></span></span></code></pre> <p>At this point, when you visit the URLs:</p> <p><a href="http://localhost:3000/blogs/my-first-blog-post">http://localhost:3000/blogs/my-first-blog-post</a></p> <p><a href="http://localhost:3000/blogs/my-second-blog-post">http://localhost:3000/blogs/my-second-blog-post</a></p> <p>You’ll see not only the blog content, but also all the metadata rendered above it.</p> <p><span class="gatsby-resp-image-wrapper" style="position: relative; display: block; margin-left: auto; margin-right: auto; max-width: 720px; " > <a class="gatsby-resp-image-link" href="/static/a27c33cb4faa28616c314537d91802ad/e3848/frontmatter.png" style="display: block" target="_blank" rel="noopener" > <span class="gatsby-resp-image-background-image" style="padding-bottom: 43.333333333333336%; position: relative; bottom: 0; left: 0; background-image: url('data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABQAAAAJCAYAAAAywQxIAAAACXBIWXMAACToAAAk6AGCYwUcAAABTklEQVR42nVR7W6CQBDkRfvDNGqfon9rWl+qb9DUj1qDgiBSTZSoIAJ3THeugYCxmwzL7c7N7t5a/bcxuq9j9IcT4zsvowY+0RlM8PD8jqfhB3rDKbrC7wn3cTC64f7BWnlr2AsX6yBElisUSqMotPF5oUCb2w6mX3N4fiBcB+7KR5ykULoUjm7BSi8XaKWgVIGyLCEf4wmttRFcrTyBi+x6lWK5QVnqmtc063A4gIiiCBcRbyJJEmRZBs/zhROZooynaVrn+d8S3O/3JnhbiVbFXNfDbPaNIAhqgXt8I2jbNrbbrYxR4CojVeBFgvGlI2+8DrDb7XA6nVr5qlOCXItBvhUPhJL3pM/z3IzLThaLJRwR5bkJcnlXmR0ow7WOxyPO57NBHMd1taoQzZftbsLQdEc+8+zs3tgWExRqLoPdUay6sAl/JJ62Nv+f/QJJeKQ0aiNHWQAAAABJRU5ErkJggg=='); background-size: cover; display: block;" ></span> <img class="gatsby-resp-image-image" alt="Blog Post with Frontmatter" title="" src="/static/a27c33cb4faa28616c314537d91802ad/37523/frontmatter.png" srcset="/static/a27c33cb4faa28616c314537d91802ad/e9ff0/frontmatter.png 180w, /static/a27c33cb4faa28616c314537d91802ad/f21e7/frontmatter.png 360w, /static/a27c33cb4faa28616c314537d91802ad/37523/frontmatter.png 720w, /static/a27c33cb4faa28616c314537d91802ad/302a4/frontmatter.png 1080w, /static/a27c33cb4faa28616c314537d91802ad/07a9c/frontmatter.png 1440w, /static/a27c33cb4faa28616c314537d91802ad/e3848/frontmatter.png 3697w" sizes="(max-width: 720px) 100vw, 720px" style="width:100%;height:100%;margin:0;vertical-align:middle;position:absolute;top:0;left:0;" loading="lazy" decoding="async" /> </a> </span></p> <h2 id="table-of-contents-toc" style="position:relative;"><a href="#table-of-contents-toc" aria-label="table of contents toc permalink" class="anchor before"><svg aria-hidden="true" focusable="false" height="16" version="1.1" viewBox="0 0 16 16" width="16"><path fill-rule="evenodd" d="M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z"></path></svg></a>Table of Contents (TOC)</h2> <p>A Table of Contents (TOC) is more than just a list—it’s a navigation boost for both your readers and search engines. It helps readers quickly jump to the content they need and gives search engines a clearer understanding of your page structure, which can even improve your chances of getting rich results in search.</p> <p>Instead of maintaining one manually, we’ll generate a dynamic TOC based on the headings inside each blog post. This way, your TOC stays accurate and updated, no extra work required.</p> <h3 id="install-required-packages" style="position:relative;"><a href="#install-required-packages" aria-label="install required packages permalink" class="anchor before"><svg aria-hidden="true" focusable="false" height="16" version="1.1" viewBox="0 0 16 16" width="16"><path fill-rule="evenodd" d="M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z"></path></svg></a>Install Required Packages</h3> <p>We’ll use a few handy libraries to parse and walk through the content tree:</p> <pre class="grvsc-container default-dark" data-language="bash" data-index="21"><code class="grvsc-code"><span class="grvsc-line"><span class="grvsc-source"><span class="mtk1">npm install unified remark-parse remark-mdx unist-util-visit rehype-slug</span></span></span></code></pre> <p>I know that might seem like a lot, but they’re lightweight, efficient, and save us from manually parsing all the edge cases.</p> <p>Here’s what we’re using:</p> <ul> <li>unified – the core processor for parsing and transforming content</li> <li>remark-parse – parses raw Markdown into an AST (abstract syntax tree)</li> <li>remark-mdx – enables MDX parsing</li> <li>unist-util-visit – allows us to traverse the AST efficiently</li> <li>rehype-slug – generates slug IDs for heading elements</li> </ul> <h3 id="extracting-headings" style="position:relative;"><a href="#extracting-headings" aria-label="extracting headings permalink" class="anchor before"><svg aria-hidden="true" focusable="false" height="16" version="1.1" viewBox="0 0 16 16" width="16"><path fill-rule="evenodd" d="M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z"></path></svg></a>Extracting Headings</h3> <p>Let’s create a new function in <code>app/blogs/[slug]/page.tsx</code> that extracts all heading nodes from the MDX content:</p> <pre class="grvsc-container default-dark" data-language="ts" data-index="22"><code class="grvsc-code"><span class="grvsc-line"><span class="grvsc-source"><span class="mtk1">...</span></span></span> <span class="grvsc-line"><span class="grvsc-source"></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk15">import</span><span class="mtk1"> { </span><span class="mtk12">unified</span><span class="mtk1"> } </span><span class="mtk15">from</span><span class="mtk1"> </span><span class="mtk8">&quot;unified&quot;</span><span class="mtk1">;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk15">import</span><span class="mtk1"> </span><span class="mtk12">remarkParse</span><span class="mtk1"> </span><span class="mtk15">from</span><span class="mtk1"> </span><span class="mtk8">&quot;remark-parse&quot;</span><span class="mtk1">;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk15">import</span><span class="mtk1"> </span><span class="mtk12">remarkMdx</span><span class="mtk1"> </span><span class="mtk15">from</span><span class="mtk1"> </span><span class="mtk8">&quot;remark-mdx&quot;</span><span class="mtk1">;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk15">import</span><span class="mtk1"> { </span><span class="mtk12">visit</span><span class="mtk1"> } </span><span class="mtk15">from</span><span class="mtk1"> </span><span class="mtk8">&quot;unist-util-visit&quot;</span><span class="mtk1">;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1">...</span></span></span> <span class="grvsc-line"><span class="grvsc-source"></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk4">interface</span><span class="mtk1"> </span><span class="mtk10">Heading</span><span class="mtk1"> {</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">depth</span><span class="mtk1">: </span><span class="mtk10">number</span><span class="mtk1">;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">text</span><span class="mtk1">: </span><span class="mtk10">string</span><span class="mtk1">;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">slug</span><span class="mtk1">: </span><span class="mtk10">string</span><span class="mtk1">;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1">}</span></span></span> <span class="grvsc-line"><span class="grvsc-source"></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1">...</span></span></span> <span class="grvsc-line"><span class="grvsc-source"></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk15">export</span><span class="mtk1"> </span><span class="mtk4">async</span><span class="mtk1"> </span><span class="mtk4">function</span><span class="mtk1"> </span><span class="mtk11">extractHeadings</span><span class="mtk1">(</span><span class="mtk12">content</span><span class="mtk1">: </span><span class="mtk10">string</span><span class="mtk1">): </span><span class="mtk10">Promise</span><span class="mtk1">&lt;</span><span class="mtk10">Heading</span><span class="mtk1">[]&gt; {</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk4">const</span><span class="mtk1"> </span><span class="mtk12">headings</span><span class="mtk1">: </span><span class="mtk10">Heading</span><span class="mtk1">[] = [];</span></span></span> <span class="grvsc-line"><span class="grvsc-source"></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk4">const</span><span class="mtk1"> </span><span class="mtk12">processor</span><span class="mtk1"> = </span><span class="mtk11">unified</span><span class="mtk1">().</span><span class="mtk11">use</span><span class="mtk1">(</span><span class="mtk12">remarkParse</span><span class="mtk1">).</span><span class="mtk11">use</span><span class="mtk1">(</span><span class="mtk12">remarkMdx</span><span class="mtk1">);</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk4">const</span><span class="mtk1"> </span><span class="mtk12">ast</span><span class="mtk1"> = </span><span class="mtk12">processor</span><span class="mtk1">.</span><span class="mtk11">parse</span><span class="mtk1">(</span><span class="mtk12">content</span><span class="mtk1">);</span></span></span> <span class="grvsc-line"><span class="grvsc-source"></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk11">visit</span><span class="mtk1">(</span><span class="mtk12">ast</span><span class="mtk1">, </span><span class="mtk8">&quot;heading&quot;</span><span class="mtk1">, (</span><span class="mtk12">node</span><span class="mtk1">: </span><span class="mtk10">any</span><span class="mtk1">) </span><span class="mtk4">=&gt;</span><span class="mtk1"> {</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk4">const</span><span class="mtk1"> </span><span class="mtk12">text</span><span class="mtk1"> = </span><span class="mtk12">node</span><span class="mtk1">.</span><span class="mtk12">children</span><span class="mtk1">.</span><span class="mtk11">map</span><span class="mtk1">((</span><span class="mtk12">child</span><span class="mtk1">: </span><span class="mtk10">any</span><span class="mtk1">) </span><span class="mtk4">=&gt;</span><span class="mtk1"> </span><span class="mtk12">child</span><span class="mtk1">.</span><span class="mtk12">value</span><span class="mtk1">).</span><span class="mtk11">join</span><span class="mtk1">(</span><span class="mtk8">&quot;&quot;</span><span class="mtk1">);</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">headings</span><span class="mtk1">.</span><span class="mtk11">push</span><span class="mtk1">({</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">depth:</span><span class="mtk1"> </span><span class="mtk12">node</span><span class="mtk1">.</span><span class="mtk12">depth</span><span class="mtk1">,</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">text</span><span class="mtk1">,</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">slug:</span><span class="mtk1"> </span><span class="mtk12">text</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> .</span><span class="mtk11">toLowerCase</span><span class="mtk1">()</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> .</span><span class="mtk11">replace</span><span class="mtk1">(</span><span class="mtk5">/\s</span><span class="mtk6">+</span><span class="mtk5">/</span><span class="mtk4">g</span><span class="mtk1">, </span><span class="mtk8">&quot;-&quot;</span><span class="mtk1">)</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> .</span><span class="mtk11">replace</span><span class="mtk1">(</span><span class="mtk5">/</span><span class="mtk8">[^</span><span class="mtk5">\w-</span><span class="mtk8">]</span><span class="mtk5">/</span><span class="mtk4">g</span><span class="mtk1">, </span><span class="mtk8">&quot;&quot;</span><span class="mtk1">), </span><span class="mtk3">// Convert to slug-friendly format. E.g. &quot;My Heading&quot; -&gt; &quot;my-heading&quot;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> });</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> });</span></span></span> <span class="grvsc-line"><span class="grvsc-source"></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk15">return</span><span class="mtk1"> </span><span class="mtk12">headings</span><span class="mtk1">;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1">}</span></span></span></code></pre> <p>This function walks through the Markdown AST and returns all headings with their text, level (e.g., h2, h3), and a slug for anchor links.</p> <p>Now, we should update the <code>BlogPostPage</code> component to use this function and render the TOC.</p> <pre class="grvsc-container grvsc-has-line-highlighting default-dark" data-language="tsx" data-index="23"><code class="grvsc-code"><span class="grvsc-line"><span class="grvsc-source"><span class="mtk1">...</span></span></span> <span class="grvsc-line"><span class="grvsc-source"></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk15">import</span><span class="mtk1"> </span><span class="mtk12">rehypeSlug</span><span class="mtk1"> </span><span class="mtk15">from</span><span class="mtk1"> </span><span class="mtk8">&quot;rehype-slug&quot;</span><span class="mtk1">;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk15">export</span><span class="mtk1"> </span><span class="mtk15">default</span><span class="mtk1"> </span><span class="mtk4">async</span><span class="mtk1"> </span><span class="mtk4">function</span><span class="mtk1"> </span><span class="mtk11">BlogPostPage</span><span class="mtk1">({ </span><span class="mtk12">params</span><span class="mtk1"> }: </span><span class="mtk10">BlogPostPageProps</span><span class="mtk1">) {</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk4">const</span><span class="mtk1"> { </span><span class="mtk12">slug</span><span class="mtk1"> } = </span><span class="mtk15">await</span><span class="mtk1"> </span><span class="mtk12">params</span><span class="mtk1">;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk4">const</span><span class="mtk1"> </span><span class="mtk12">filePath</span><span class="mtk1"> = </span><span class="mtk12">path</span><span class="mtk1">.</span><span class="mtk11">join</span><span class="mtk1">(</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">process</span><span class="mtk1">.</span><span class="mtk11">cwd</span><span class="mtk1">(),</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk8">&quot;content&quot;</span><span class="mtk1">,</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk8">&quot;blogs&quot;</span><span class="mtk1">,</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">slug</span><span class="mtk1">,</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk8">&quot;page.mdx&quot;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> );</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk4">const</span><span class="mtk1"> </span><span class="mtk12">fileContents</span><span class="mtk1"> = </span><span class="mtk11">readFileSync</span><span class="mtk1">(</span><span class="mtk12">filePath</span><span class="mtk1">, </span><span class="mtk8">&quot;utf8&quot;</span><span class="mtk1">);</span></span></span> <span class="grvsc-line"><span class="grvsc-source"></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk4">const</span><span class="mtk1"> { </span><span class="mtk12">content</span><span class="mtk1">, </span><span class="mtk12">data</span><span class="mtk1">: </span><span class="mtk12">frontmatter</span><span class="mtk1"> } = </span><span class="mtk11">matter</span><span class="mtk1">(</span><span class="mtk12">fileContents</span><span class="mtk1">);</span></span></span> <span class="grvsc-line grvsc-line-highlighted"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk4">const</span><span class="mtk1"> </span><span class="mtk12">headings</span><span class="mtk1"> = </span><span class="mtk15">await</span><span class="mtk1"> </span><span class="mtk11">extractHeadings</span><span class="mtk1">(</span><span class="mtk12">content</span><span class="mtk1">);</span></span></span> <span class="grvsc-line"><span class="grvsc-source"></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk15">return</span><span class="mtk1"> (</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk17">&lt;</span><span class="mtk4">div</span><span class="mtk17">&gt;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk17">&lt;</span><span class="mtk4">h1</span><span class="mtk17">&gt;</span><span class="mtk4">{</span><span class="mtk12">frontmatter</span><span class="mtk1">.</span><span class="mtk12">title</span><span class="mtk4">}</span><span class="mtk17">&lt;/</span><span class="mtk4">h1</span><span class="mtk17">&gt;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk17">&lt;</span><span class="mtk4">p</span><span class="mtk17">&gt;</span><span class="mtk4">{</span><span class="mtk12">frontmatter</span><span class="mtk1">.</span><span class="mtk12">date</span><span class="mtk4">}</span><span class="mtk17">&lt;/</span><span class="mtk4">p</span><span class="mtk17">&gt;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk17">&lt;</span><span class="mtk4">p</span><span class="mtk17">&gt;</span><span class="mtk4">{</span><span class="mtk12">frontmatter</span><span class="mtk1">.</span><span class="mtk12">author</span><span class="mtk4">}</span><span class="mtk17">&lt;/</span><span class="mtk4">p</span><span class="mtk17">&gt;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk17">&lt;</span><span class="mtk4">p</span><span class="mtk17">&gt;</span><span class="mtk4">{</span><span class="mtk12">frontmatter</span><span class="mtk1">.</span><span class="mtk12">description</span><span class="mtk4">}</span><span class="mtk17">&lt;/</span><span class="mtk4">p</span><span class="mtk17">&gt;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk17">&lt;</span><span class="mtk4">p</span><span class="mtk17">&gt;</span><span class="mtk4">{</span><span class="mtk12">frontmatter</span><span class="mtk1">.</span><span class="mtk12">tags</span><span class="mtk4">}</span><span class="mtk17">&lt;/</span><span class="mtk4">p</span><span class="mtk17">&gt;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk4">{</span><span class="mtk3">/* Render TOC */</span><span class="mtk4">}</span></span></span> <span class="grvsc-line grvsc-line-highlighted"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk17">&lt;</span><span class="mtk4">ul</span><span class="mtk17">&gt;</span></span></span> <span class="grvsc-line grvsc-line-highlighted"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk4">{</span><span class="mtk12">headings</span><span class="mtk1">?.</span><span class="mtk11">map</span><span class="mtk1">(({ </span><span class="mtk12">text</span><span class="mtk1">, </span><span class="mtk12">slug</span><span class="mtk1">, </span><span class="mtk12">depth</span><span class="mtk1"> }) </span><span class="mtk4">=&gt;</span><span class="mtk1"> (</span></span></span> <span class="grvsc-line grvsc-line-highlighted"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk17">&lt;</span><span class="mtk4">li</span><span class="mtk1"> </span><span class="mtk12">key</span><span class="mtk1">=</span><span class="mtk4">{</span><span class="mtk12">slug</span><span class="mtk4">}</span><span class="mtk1"> </span><span class="mtk12">style</span><span class="mtk1">=</span><span class="mtk4">{</span><span class="mtk1">{ </span><span class="mtk12">marginLeft:</span><span class="mtk1"> </span><span class="mtk8">`</span><span class="mtk4">${</span><span class="mtk12">depth</span><span class="mtk1"> - </span><span class="mtk7">1</span><span class="mtk4">}</span><span class="mtk8">rem`</span><span class="mtk1"> }</span><span class="mtk4">}</span><span class="mtk17">&gt;</span></span></span> <span class="grvsc-line grvsc-line-highlighted"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk17">&lt;</span><span class="mtk4">a</span><span class="mtk1"> </span><span class="mtk12">href</span><span class="mtk1">=</span><span class="mtk4">{</span><span class="mtk8">`#</span><span class="mtk4">${</span><span class="mtk12">slug</span><span class="mtk4">}</span><span class="mtk8">`</span><span class="mtk4">}</span><span class="mtk17">&gt;</span><span class="mtk4">{</span><span class="mtk12">text</span><span class="mtk4">}</span><span class="mtk17">&lt;/</span><span class="mtk4">a</span><span class="mtk17">&gt;</span></span></span> <span class="grvsc-line grvsc-line-highlighted"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk17">&lt;/</span><span class="mtk4">li</span><span class="mtk17">&gt;</span></span></span> <span class="grvsc-line grvsc-line-highlighted"><span class="grvsc-source"><span class="mtk1"> ))</span><span class="mtk4">}</span></span></span> <span class="grvsc-line grvsc-line-highlighted"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk17">&lt;/</span><span class="mtk4">ul</span><span class="mtk17">&gt;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk17">&lt;</span><span class="mtk10">MDXRemote</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">source</span><span class="mtk1">=</span><span class="mtk4">{</span><span class="mtk12">content</span><span class="mtk4">}</span></span></span> <span class="grvsc-line grvsc-line-highlighted"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">options</span><span class="mtk1">=</span><span class="mtk4">{</span><span class="mtk1">{</span></span></span> <span class="grvsc-line grvsc-line-highlighted"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">mdxOptions:</span><span class="mtk1"> { </span><span class="mtk12">rehypePlugins:</span><span class="mtk1"> [</span><span class="mtk12">rehypeSlug</span><span class="mtk1">] },</span></span></span> <span class="grvsc-line grvsc-line-highlighted"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">parseFrontmatter:</span><span class="mtk1"> </span><span class="mtk4">true</span><span class="mtk1">,</span></span></span> <span class="grvsc-line grvsc-line-highlighted"><span class="grvsc-source"><span class="mtk1"> }</span><span class="mtk4">}</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk17">/&gt;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk17">&lt;/</span><span class="mtk4">div</span><span class="mtk17">&gt;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> );</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1">}</span></span></span> <span class="grvsc-line"><span class="grvsc-source"></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1">...</span></span></span></code></pre> <p><code>rehypeSlug</code> is added to the <code>rehypePlugins</code> array prop in <code>MDXRemote</code> to automatically generate id attributes for heading elements. These ids are derived from the heading text and make it possible to create anchor links.</p> <p>In case you’re not familiar with <code>rehype</code>, it’s part of the Unified ecosystem, a powerful plugin system that transforms HTML content into an abstract syntax tree (AST). This makes it easy to manipulate, enhance, or even sanitize content during compilation.</p> <p>With <code>rehypeSlug</code> in place and our <code>extractHeadings</code> function doing its job, we now render a clean Table of Contents where each item links to its respective section. We also use the depth value in HTML to adjust indentation and reflect the heading hierarchy visually.</p> <p>Let’s test it out and update <code>my-first-blog-post</code> with additional heading levels like this:</p> <pre class="grvsc-container default-dark" data-language="mdx" data-index="24"><code class="grvsc-code"><span class="grvsc-line"><span class="grvsc-source">## Learning Next.js</span></span> <span class="grvsc-line"><span class="grvsc-source"></span></span> <span class="grvsc-line"><span class="grvsc-source">### Why Next.js?</span></span> <span class="grvsc-line"><span class="grvsc-source"></span></span> <span class="grvsc-line"><span class="grvsc-source"># Learning Material UI</span></span> <span class="grvsc-line"><span class="grvsc-source"></span></span> <span class="grvsc-line"><span class="grvsc-source">## Why Material UI?</span></span> <span class="grvsc-line"><span class="grvsc-source"></span></span> <span class="grvsc-line"><span class="grvsc-source">## Conclusion</span></span></code></pre> <p>Navigate to <code>http://localhost:3000/blogs/my-first-blog-post</code> and you’ll now see a clickable TOC that anchors to each section of the article.</p> <p><span class="gatsby-resp-image-wrapper" style="position: relative; display: block; margin-left: auto; margin-right: auto; max-width: 720px; " > <a class="gatsby-resp-image-link" href="/static/ed794642208e2d5529d7a17b40314c1c/bdedb/table-of-contents.png" style="display: block" target="_blank" rel="noopener" > <span class="gatsby-resp-image-background-image" style="padding-bottom: 67.22222222222223%; position: relative; bottom: 0; left: 0; background-image: url('data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABQAAAANCAYAAACpUE5eAAAACXBIWXMAACToAAAk6AGCYwUcAAABQUlEQVR42q1Sy07DMBD0p3IChBC/wQUQ8DU9c+LApaoKbkvboBwgzYPmbec1eG05qgpCKGWlkccbZzLxDju/m+HifoaTa46z2xlOb15wfDXF0eVkENh48gw+X4LWyZTjdfWGrJDIy2oQ2MbzkGUZkiRBmqYoyxJd12FoMc/bII4T1HWtUVWVhhASUlYK0nBhekKIvk+r6Un1bgPywaIoVO4+e4d5nmuQ611uYc8QL4qi79EHtMMoyOAsEoiyMZ6H/60RlKLBmjfw31tl+0A1EizyGuNHiaeHGnlqBA+YiRJUEVlxgQ+3QtP8g0POOeYLjuVyri+Zqm1bHR0Ccbu3fLf3TTAIAhWbGNtt3E/aTs5y6hPo3O5zmva+KHMcR+fO3F33I/bd/BZ8NhqN4LouoiiC7/sgx2EY6j2t1hmF/i/1BdLH4LSWWyDIAAAAAElFTkSuQmCC'); background-size: cover; display: block;" ></span> <img class="gatsby-resp-image-image" alt="Table of contents in the nextjs starter" title="" src="/static/ed794642208e2d5529d7a17b40314c1c/37523/table-of-contents.png" srcset="/static/ed794642208e2d5529d7a17b40314c1c/e9ff0/table-of-contents.png 180w, /static/ed794642208e2d5529d7a17b40314c1c/f21e7/table-of-contents.png 360w, /static/ed794642208e2d5529d7a17b40314c1c/37523/table-of-contents.png 720w, /static/ed794642208e2d5529d7a17b40314c1c/302a4/table-of-contents.png 1080w, /static/ed794642208e2d5529d7a17b40314c1c/07a9c/table-of-contents.png 1440w, /static/ed794642208e2d5529d7a17b40314c1c/bdedb/table-of-contents.png 2715w" sizes="(max-width: 720px) 100vw, 720px" style="width:100%;height:100%;margin:0;vertical-align:middle;position:absolute;top:0;left:0;" loading="lazy" decoding="async" /> </a> </span></p> <h2 id="code-highlighting" style="position:relative;"><a href="#code-highlighting" aria-label="code highlighting permalink" class="anchor before"><svg aria-hidden="true" focusable="false" height="16" version="1.1" viewBox="0 0 16 16" width="16"><path fill-rule="evenodd" d="M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z"></path></svg></a>Code Highlighting</h2> <p>Code highlighting is one of those small touches that makes a huge difference, both for your readers and your own readability when revisiting code-heavy posts.</p> <p>After trying out several options over the years, I found Shiki to offer the perfect balance between performance, theming flexibility, and developer experience. It’s lightweight, fast, and customizable enough to fit nicely into your blog design.</p> <h3 id="install-shiki-and-rehype-plugin" style="position:relative;"><a href="#install-shiki-and-rehype-plugin" aria-label="install shiki and rehype plugin permalink" class="anchor before"><svg aria-hidden="true" focusable="false" height="16" version="1.1" viewBox="0 0 16 16" width="16"><path fill-rule="evenodd" d="M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z"></path></svg></a>Install Shiki and Rehype Plugin</h3> <p>We’ll use Shiki in combination with <code>rehype-pretty-code</code>, a rehype plugin that integrates Shiki for syntax highlighting.</p> <pre class="grvsc-container default-dark" data-language="bash" data-index="25"><code class="grvsc-code"><span class="grvsc-line"><span class="grvsc-source"><span class="mtk1">npm install shiki rehype-pretty-code</span></span></span></code></pre> <h3 id="configure-code-highlighting-in-mdx-compiler" style="position:relative;"><a href="#configure-code-highlighting-in-mdx-compiler" aria-label="configure code highlighting in mdx compiler permalink" class="anchor before"><svg aria-hidden="true" focusable="false" height="16" version="1.1" viewBox="0 0 16 16" width="16"><path fill-rule="evenodd" d="M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z"></path></svg></a>Configure Code Highlighting in MDX Compiler</h3> <p>Let’s update <code>app/blogs/[slug]/page.tsx</code> file to apply syntax highlighting via <code>rehypePrettyCode</code>:</p> <pre class="grvsc-container default-dark" data-language="tsx" data-index="26"><code class="grvsc-code"><span class="grvsc-line"><span class="grvsc-source"><span class="mtk1">...</span></span></span> <span class="grvsc-line"><span class="grvsc-source"></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk15">import</span><span class="mtk1"> </span><span class="mtk12">rehypePrettyCode</span><span class="mtk1"> </span><span class="mtk15">from</span><span class="mtk1"> </span><span class="mtk8">&quot;rehype-pretty-code&quot;</span><span class="mtk1">;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1">...</span></span></span> <span class="grvsc-line"><span class="grvsc-source"></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk3">// Inside MDXRemote component</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk17">&lt;</span><span class="mtk10">MDXRemote</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">source</span><span class="mtk1">=</span><span class="mtk4">{</span><span class="mtk12">content</span><span class="mtk4">}</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">options</span><span class="mtk1">=</span><span class="mtk4">{</span><span class="mtk1">{</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">mdxOptions:</span><span class="mtk1"> {</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">rehypePlugins:</span><span class="mtk1"> [</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">rehypeSlug</span><span class="mtk1">,</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> [</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">rehypePrettyCode</span><span class="mtk1">,</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> {</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">theme:</span><span class="mtk1"> </span><span class="mtk8">&quot;github-dark&quot;</span><span class="mtk1">, </span><span class="mtk3">// or &#39;nord&#39;, &#39;dracula&#39;, etc.</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">keepBackground:</span><span class="mtk1"> </span><span class="mtk4">true</span><span class="mtk1">,</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> },</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> ],</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> ],</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> },</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">parseFrontmatter:</span><span class="mtk1"> </span><span class="mtk4">true</span><span class="mtk1">,</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> }</span><span class="mtk4">}</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk17">/&gt;</span><span class="mtk1">;</span></span></span></code></pre> <p>This tells the compiler to:</p> <ul> <li>Style code blocks using the <code>github-dark</code> theme (you can customize it)</li> <li>Preserve any background color defined by the theme with <code>keepBackground: true</code></li> </ul> <p>Let’s add a code snippet to the MDX blog post and see it in action:</p> <pre class="grvsc-container default-dark" data-language="mdx" data-index="27"><code class="grvsc-code"><span class="grvsc-line"><span class="grvsc-source"># Code Highlighting</span></span> <span class="grvsc-line"><span class="grvsc-source"></span></span> <span class="grvsc-line"><span class="grvsc-source">Here’s an example of a simple MUI-powered header component:</span></span> <span class="grvsc-line"><span class="grvsc-source"></span></span> <span class="grvsc-line"><span class="grvsc-source">```jsx</span></span> <span class="grvsc-line"><span class="grvsc-source">import React from &quot;react&quot;;</span></span> <span class="grvsc-line"><span class="grvsc-source">import { AppBar, Toolbar, Typography, Button } from &quot;@mui/material&quot;;</span></span> <span class="grvsc-line"><span class="grvsc-source"></span></span> <span class="grvsc-line"><span class="grvsc-source">export default function Header() {</span></span> <span class="grvsc-line"><span class="grvsc-source"> return (</span></span> <span class="grvsc-line"><span class="grvsc-source"> &lt;AppBar position=&quot;static&quot;&gt;</span></span> <span class="grvsc-line"><span class="grvsc-source"> &lt;Toolbar&gt;</span></span> <span class="grvsc-line"><span class="grvsc-source"> &lt;Typography variant=&quot;h6&quot; mr={5}&gt;</span></span> <span class="grvsc-line"><span class="grvsc-source"> My Blog</span></span> <span class="grvsc-line"><span class="grvsc-source"> &lt;/Typography&gt;</span></span> <span class="grvsc-line"><span class="grvsc-source"> &lt;Button color=&quot;inherit&quot;&gt;Home&lt;/Button&gt;</span></span> <span class="grvsc-line"><span class="grvsc-source"> &lt;Button color=&quot;inherit&quot;&gt;Blog&lt;/Button&gt;</span></span> <span class="grvsc-line"><span class="grvsc-source"> &lt;Button color=&quot;inherit&quot;&gt;About&lt;/Button&gt;</span></span> <span class="grvsc-line"><span class="grvsc-source"> &lt;/Toolbar&gt;</span></span> <span class="grvsc-line"><span class="grvsc-source"> &lt;/AppBar&gt;</span></span> <span class="grvsc-line"><span class="grvsc-source"> );</span></span> <span class="grvsc-line"><span class="grvsc-source">}</span></span> <span class="grvsc-line"><span class="grvsc-source">```</span></span></code></pre> <p>Now when visiting <code>http://localhost:3000/blogs/my-first-blog-post</code>, you should see the syntax-highlighted block rendered with smooth, github-theme like styling, no manual styling needed. Hooray!</p> <p><span class="gatsby-resp-image-wrapper" style="position: relative; display: block; margin-left: auto; margin-right: auto; max-width: 720px; " > <a class="gatsby-resp-image-link" href="/static/9d1f7581bd5d2c7bc706c36b72343c43/6794a/code-highlighting.png" style="display: block" target="_blank" rel="noopener" > <span class="gatsby-resp-image-background-image" style="padding-bottom: 36.66666666666667%; position: relative; bottom: 0; left: 0; background-image: url('data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABQAAAAHCAYAAAAIy204AAAACXBIWXMAABnWAAAZ1gEY0crtAAABCElEQVR42p3OT0rDQBQG8DmD2xht2iZxGpsZsCYg2l03lWqr9c+ZRIpWewYRt4rVSdIGT6EeIDYXyCr5HINgNiJx4Me8j/d4PBJFEeI4xmLxgSRJkGUZ0jTN/9+kWaFfmP165P31DeJZYB6+YCo83D884knmYBbCl4QfQHjf/OAnF2vJC2YI5iHI5PIaqqKBsU1YzIVhcVQNCzXThkYZVmpUWvuTWjVzZHw1wWqdgbd20LAd6A2OOm1KDDq1ZWalkNHFGKrB4LZ30dzYAnfaoMyRl7L82rLI2fkIS8umXLINfb0Fyl1UTA6lokPRjNLIze0dOt0+Bken6A2G6PWH2Ds4xv7hyb98As51MW9QWGx7AAAAAElFTkSuQmCC'); background-size: cover; display: block;" ></span> <img class="gatsby-resp-image-image" alt="Code highlighting in a nextjs blog template" title="" src="/static/9d1f7581bd5d2c7bc706c36b72343c43/37523/code-highlighting.png" srcset="/static/9d1f7581bd5d2c7bc706c36b72343c43/e9ff0/code-highlighting.png 180w, /static/9d1f7581bd5d2c7bc706c36b72343c43/f21e7/code-highlighting.png 360w, /static/9d1f7581bd5d2c7bc706c36b72343c43/37523/code-highlighting.png 720w, /static/9d1f7581bd5d2c7bc706c36b72343c43/302a4/code-highlighting.png 1080w, /static/9d1f7581bd5d2c7bc706c36b72343c43/07a9c/code-highlighting.png 1440w, /static/9d1f7581bd5d2c7bc706c36b72343c43/6794a/code-highlighting.png 2773w" sizes="(max-width: 720px) 100vw, 720px" style="width:100%;height:100%;margin:0;vertical-align:middle;position:absolute;top:0;left:0;" loading="lazy" decoding="async" /> </a> </span></p> <h2 id="using-react-components-in-mdx" style="position:relative;"><a href="#using-react-components-in-mdx" aria-label="using react components in mdx permalink" class="anchor before"><svg aria-hidden="true" focusable="false" height="16" version="1.1" viewBox="0 0 16 16" width="16"><path fill-rule="evenodd" d="M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z"></path></svg></a>Using React Components in MDX</h2> <p>One of MDX’s best features is the ability to embed React components directly inside Markdown content.</p> <p>This means we’re no longer limited to static code examples. We can actually render live components within posts, perfect for interactive demos, UI previews, or teaching by example.</p> <p>Imagine writing a React tutorial and showing a simple counter. Instead of only pasting the code, your readers can see it in action and interact with it.</p> <h3 id="create-a-react-component" style="position:relative;"><a href="#create-a-react-component" aria-label="create a react component permalink" class="anchor before"><svg aria-hidden="true" focusable="false" height="16" version="1.1" viewBox="0 0 16 16" width="16"><path fill-rule="evenodd" d="M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z"></path></svg></a>Create a React Component</h3> <p>Let’s create a basic Counter component inside the components folder:</p> <pre class="grvsc-container default-dark" data-language="tsx" data-index="28"><code class="grvsc-code"><span class="grvsc-line"><span class="grvsc-source"><span class="mtk3">// components/Counter.tsx</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk8">&quot;use client&quot;</span><span class="mtk1">;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk15">import</span><span class="mtk1"> { </span><span class="mtk12">useState</span><span class="mtk1"> } </span><span class="mtk15">from</span><span class="mtk1"> </span><span class="mtk8">&quot;react&quot;</span><span class="mtk1">;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk15">export</span><span class="mtk1"> </span><span class="mtk15">default</span><span class="mtk1"> </span><span class="mtk4">function</span><span class="mtk1"> </span><span class="mtk11">Counter</span><span class="mtk1">() {</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk4">const</span><span class="mtk1"> [</span><span class="mtk12">count</span><span class="mtk1">, </span><span class="mtk12">setCount</span><span class="mtk1">] = </span><span class="mtk11">useState</span><span class="mtk1">(</span><span class="mtk7">0</span><span class="mtk1">);</span></span></span> <span class="grvsc-line"><span class="grvsc-source"></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk15">return</span><span class="mtk1"> (</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk17">&lt;</span><span class="mtk4">div</span><span class="mtk17">&gt;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk17">&lt;</span><span class="mtk4">button</span><span class="mtk1"> </span><span class="mtk12">onClick</span><span class="mtk1">=</span><span class="mtk4">{</span><span class="mtk1">() </span><span class="mtk4">=&gt;</span><span class="mtk1"> </span><span class="mtk11">setCount</span><span class="mtk1">(</span><span class="mtk12">c</span><span class="mtk1"> </span><span class="mtk4">=&gt;</span><span class="mtk1"> </span><span class="mtk12">c</span><span class="mtk1"> - </span><span class="mtk7">1</span><span class="mtk1">)</span><span class="mtk4">}</span><span class="mtk17">&gt;</span><span class="mtk1">-</span><span class="mtk17">&lt;/</span><span class="mtk4">button</span><span class="mtk17">&gt;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk17">&lt;</span><span class="mtk4">span</span><span class="mtk17">&gt;</span><span class="mtk4">{</span><span class="mtk12">count</span><span class="mtk4">}</span><span class="mtk17">&lt;/</span><span class="mtk4">span</span><span class="mtk17">&gt;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk17">&lt;</span><span class="mtk4">button</span><span class="mtk1"> </span><span class="mtk12">onClick</span><span class="mtk1">=</span><span class="mtk4">{</span><span class="mtk1">() </span><span class="mtk4">=&gt;</span><span class="mtk1"> </span><span class="mtk11">setCount</span><span class="mtk1">(</span><span class="mtk12">c</span><span class="mtk1"> </span><span class="mtk4">=&gt;</span><span class="mtk1"> </span><span class="mtk12">c</span><span class="mtk1"> + </span><span class="mtk7">1</span><span class="mtk1">)</span><span class="mtk4">}</span><span class="mtk17">&gt;</span><span class="mtk1">+</span><span class="mtk17">&lt;/</span><span class="mtk4">button</span><span class="mtk17">&gt;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk17">&lt;/</span><span class="mtk4">div</span><span class="mtk17">&gt;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> );</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1">}</span></span></span></code></pre> <p><em><code>"use client"</code> in the first line is required to make this a client component, since it uses state and interactivity. The default behavior in Next.js is to render components on the server.</em></p> <p>This is a simple component, but we can get creative and build more advanced widgets like tabbed examples, theme toggles, or custom UI cards.</p> <h3 id="use-component-in-mdx" style="position:relative;"><a href="#use-component-in-mdx" aria-label="use component in mdx permalink" class="anchor before"><svg aria-hidden="true" focusable="false" height="16" version="1.1" viewBox="0 0 16 16" width="16"><path fill-rule="evenodd" d="M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z"></path></svg></a>Use Component in MDX</h3> <p>To use a component inside any <code>.mdx</code> blog post, we need to expose it to the MDX compiler by passing it via the components prop in <code>MDXRemote</code>.</p> <pre class="grvsc-container default-dark" data-language="tsx" data-index="29"><code class="grvsc-code"><span class="grvsc-line"><span class="grvsc-source"><span class="mtk15">import</span><span class="mtk1"> </span><span class="mtk12">Counter</span><span class="mtk1"> </span><span class="mtk15">from</span><span class="mtk1"> </span><span class="mtk8">&quot;@/components/Counter&quot;</span><span class="mtk1">;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1">...</span></span></span> <span class="grvsc-line"><span class="grvsc-source"></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk17">&lt;</span><span class="mtk10">MDXRemote</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">source</span><span class="mtk1">=</span><span class="mtk4">{</span><span class="mtk12">content</span><span class="mtk4">}</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">components</span><span class="mtk1">=</span><span class="mtk4">{</span><span class="mtk1">{ </span><span class="mtk12">Counter</span><span class="mtk1"> }</span><span class="mtk4">}</span><span class="mtk1"> </span><span class="mtk3">// or add more components here. E.g. { Counter, Alert, Tabs }</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">options</span><span class="mtk1">=</span><span class="mtk4">{</span><span class="mtk1">{</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">mdxOptions:</span><span class="mtk1"> {</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">rehypePlugins:</span><span class="mtk1"> [</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">rehypeSlug</span><span class="mtk1">,</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> [</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">rehypePrettyCode</span><span class="mtk1">,</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> {</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">theme:</span><span class="mtk1"> </span><span class="mtk8">&quot;github-dark&quot;</span><span class="mtk1">, </span><span class="mtk3">// or &#39;nord&#39;, &#39;dracula&#39;, etc.</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">keepBackground:</span><span class="mtk1"> </span><span class="mtk4">true</span><span class="mtk1">,</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> },</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> ],</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> ],</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> },</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">parseFrontmatter:</span><span class="mtk1"> </span><span class="mtk4">true</span><span class="mtk1">,</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> }</span><span class="mtk4">}</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk17">/&gt;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1">...</span></span></span></code></pre> <p>Now in any blog post, we can just write:</p> <pre class="grvsc-container default-dark" data-language="mdx" data-index="30"><code class="grvsc-code"><span class="grvsc-line"><span class="grvsc-source"># Interactive Counter Example</span></span> <span class="grvsc-line"><span class="grvsc-source"></span></span> <span class="grvsc-line"><span class="grvsc-source">Here’s a simple counter component you can interact with:</span></span> <span class="grvsc-line"><span class="grvsc-source"></span></span> <span class="grvsc-line"><span class="grvsc-source">```tsx</span></span> <span class="grvsc-line"><span class="grvsc-source">import { useState } from &quot;react&quot;;</span></span> <span class="grvsc-line"><span class="grvsc-source">export default function Counter() {</span></span> <span class="grvsc-line"><span class="grvsc-source"> const [count, setCount] = useState(0);</span></span> <span class="grvsc-line"><span class="grvsc-source"> return (</span></span> <span class="grvsc-line"><span class="grvsc-source"> &lt;div&gt;</span></span> <span class="grvsc-line"><span class="grvsc-source"> &lt;button onClick={() =&gt; setCount(c =&gt; c - 1)}&gt;-&lt;/button&gt;</span></span> <span class="grvsc-line"><span class="grvsc-source"> &lt;span&gt;{count}&lt;/span&gt;</span></span> <span class="grvsc-line"><span class="grvsc-source"> &lt;button onClick={() =&gt; setCount(c =&gt; c + 1)}&gt;+&lt;/button&gt;</span></span> <span class="grvsc-line"><span class="grvsc-source"> &lt;/div&gt;</span></span> <span class="grvsc-line"><span class="grvsc-source"> );</span></span> <span class="grvsc-line"><span class="grvsc-source">}</span></span> <span class="grvsc-line"><span class="grvsc-source">```</span></span> <span class="grvsc-line"><span class="grvsc-source"></span></span> <span class="grvsc-line"><span class="grvsc-source">&lt;Counter /&gt;</span></span></code></pre> <p>In the demo video below, you can see how the counter component renders live inside the MDX content, allowing readers to interact with it directly.</p> <video width="720" height="400" autoplay loop muted playsinline preload="none"> <source src="/d41345416de2468ef964a27c271497af/react-components-in-mdx.mp4" type="video/mp4"> </video> <h2 id="creating-a-list-of-blog-posts" style="position:relative;"><a href="#creating-a-list-of-blog-posts" aria-label="creating a list of blog posts permalink" class="anchor before"><svg aria-hidden="true" focusable="false" height="16" version="1.1" viewBox="0 0 16 16" width="16"><path fill-rule="evenodd" d="M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z"></path></svg></a>Creating a List of Blog Posts</h2> <p>Now that we’ve got multiple posts up and running, let’s build a clean <code>/blogs</code> listing page to show them off, complete with tag-based filtering for a better browsing experience.</p> <h3 id="create-the-blogs-page" style="position:relative;"><a href="#create-the-blogs-page" aria-label="create the blogs page permalink" class="anchor before"><svg aria-hidden="true" focusable="false" height="16" version="1.1" viewBox="0 0 16 16" width="16"><path fill-rule="evenodd" d="M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z"></path></svg></a>Create the blogs Page</h3> <p>Thanks to the power of the Next.js App Router, we can simply create a <code>page.tsx</code> file inside the blogs folder and it’ll automatically be available at <code>/blogs</code>.</p> <p>Your project structure should look like this:</p> <pre class="grvsc-container default-dark" data-language="plaintext" data-index="31"><code class="grvsc-code"><span class="grvsc-line"><span class="grvsc-source">nextjs-mui-blog-starter</span></span> <span class="grvsc-line"><span class="grvsc-source">├── src</span></span> <span class="grvsc-line"><span class="grvsc-source">│ ├── app</span></span> <span class="grvsc-line"><span class="grvsc-source">│ │ ├── blogs</span></span> <span class="grvsc-line"><span class="grvsc-source">│ │ │ ├── [slug]</span></span> <span class="grvsc-line"><span class="grvsc-source">│ │ │ │ └── page.tsx</span></span> <span class="grvsc-line"><span class="grvsc-source">│ │ │ └── page.tsx ← our new blogs listing page</span></span> <span class="grvsc-line"><span class="grvsc-source">├── content</span></span> <span class="grvsc-line"><span class="grvsc-source">│ └── blogs</span></span> <span class="grvsc-line"><span class="grvsc-source">│ └── my-first-blog-post</span></span> <span class="grvsc-line"><span class="grvsc-source">│ └── my-second-blog-post</span></span></code></pre> <ul> <li>The <code>app/blogs/[slug]/page.tsx</code> file defines a dynamic route in the App Router. It acts as a template that loads and renders each blog post based on its unique slug (e.g., <code>/blogs/my-first-post</code>).</li> <li><code>content/blogs/</code> holds the blog post MDX files with frontmatter</li> <li><code>app/blogs/page.tsx</code> is the blog listing page</li> </ul> <p>Let’s add the following code in <code>app/blogs/page.tsx</code> to display a list of all blog posts by extracting their frontmatter:</p> <pre class="grvsc-container default-dark" data-language="tsx" data-index="32"><code class="grvsc-code"><span class="grvsc-line"><span class="grvsc-source"><span class="mtk15">import</span><span class="mtk1"> </span><span class="mtk12">fs</span><span class="mtk1"> </span><span class="mtk15">from</span><span class="mtk1"> </span><span class="mtk8">&quot;fs&quot;</span><span class="mtk1">;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk15">import</span><span class="mtk1"> </span><span class="mtk12">path</span><span class="mtk1"> </span><span class="mtk15">from</span><span class="mtk1"> </span><span class="mtk8">&quot;path&quot;</span><span class="mtk1">;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk15">import</span><span class="mtk1"> </span><span class="mtk12">matter</span><span class="mtk1"> </span><span class="mtk15">from</span><span class="mtk1"> </span><span class="mtk8">&quot;gray-matter&quot;</span><span class="mtk1">;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk15">import</span><span class="mtk1"> </span><span class="mtk12">Link</span><span class="mtk1"> </span><span class="mtk15">from</span><span class="mtk1"> </span><span class="mtk8">&quot;next/link&quot;</span><span class="mtk1">;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk4">const</span><span class="mtk1"> </span><span class="mtk12">blogsDirectory</span><span class="mtk1"> = </span><span class="mtk12">path</span><span class="mtk1">.</span><span class="mtk11">join</span><span class="mtk1">(</span><span class="mtk12">process</span><span class="mtk1">.</span><span class="mtk11">cwd</span><span class="mtk1">(), </span><span class="mtk8">&quot;content&quot;</span><span class="mtk1">, </span><span class="mtk8">&quot;blogs&quot;</span><span class="mtk1">);</span></span></span> <span class="grvsc-line"><span class="grvsc-source"></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk15">export</span><span class="mtk1"> </span><span class="mtk15">default</span><span class="mtk1"> </span><span class="mtk4">function</span><span class="mtk1"> </span><span class="mtk11">BlogsPage</span><span class="mtk1">() {</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk4">const</span><span class="mtk1"> </span><span class="mtk12">blogFolders</span><span class="mtk1"> = </span><span class="mtk12">fs</span><span class="mtk1">.</span><span class="mtk11">readdirSync</span><span class="mtk1">(</span><span class="mtk12">blogsDirectory</span><span class="mtk1">);</span></span></span> <span class="grvsc-line"><span class="grvsc-source"></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk4">const</span><span class="mtk1"> </span><span class="mtk12">allBlogs</span><span class="mtk1"> = </span><span class="mtk12">blogFolders</span><span class="mtk1">.</span><span class="mtk11">map</span><span class="mtk1">(</span><span class="mtk12">folder</span><span class="mtk1"> </span><span class="mtk4">=&gt;</span><span class="mtk1"> {</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk4">const</span><span class="mtk1"> </span><span class="mtk12">filePath</span><span class="mtk1"> = </span><span class="mtk12">path</span><span class="mtk1">.</span><span class="mtk11">join</span><span class="mtk1">(</span><span class="mtk12">blogsDirectory</span><span class="mtk1">, </span><span class="mtk12">folder</span><span class="mtk1">, </span><span class="mtk8">&quot;page.mdx&quot;</span><span class="mtk1">);</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk4">const</span><span class="mtk1"> </span><span class="mtk12">fileContent</span><span class="mtk1"> = </span><span class="mtk12">fs</span><span class="mtk1">.</span><span class="mtk11">readFileSync</span><span class="mtk1">(</span><span class="mtk12">filePath</span><span class="mtk1">, </span><span class="mtk8">&quot;utf-8&quot;</span><span class="mtk1">);</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk4">const</span><span class="mtk1"> { </span><span class="mtk12">data</span><span class="mtk1">: </span><span class="mtk12">frontmatter</span><span class="mtk1"> } = </span><span class="mtk11">matter</span><span class="mtk1">(</span><span class="mtk12">fileContent</span><span class="mtk1">);</span></span></span> <span class="grvsc-line"><span class="grvsc-source"></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk15">return</span><span class="mtk1"> {</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">slug:</span><span class="mtk1"> </span><span class="mtk12">folder</span><span class="mtk1">,</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> ...</span><span class="mtk12">frontmatter</span><span class="mtk1">,</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> };</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> });</span></span></span> <span class="grvsc-line"><span class="grvsc-source"></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk15">return</span><span class="mtk1"> (</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk17">&lt;</span><span class="mtk4">div</span><span class="mtk17">&gt;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk17">&lt;</span><span class="mtk4">h1</span><span class="mtk17">&gt;</span><span class="mtk1">All Blog Posts</span><span class="mtk17">&lt;/</span><span class="mtk4">h1</span><span class="mtk17">&gt;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk17">&lt;</span><span class="mtk4">ul</span><span class="mtk17">&gt;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk4">{</span><span class="mtk12">allBlogs</span><span class="mtk1">.</span><span class="mtk11">map</span><span class="mtk1">((</span><span class="mtk12">blog</span><span class="mtk1">: </span><span class="mtk10">any</span><span class="mtk1">) </span><span class="mtk4">=&gt;</span><span class="mtk1"> (</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk17">&lt;</span><span class="mtk4">li</span><span class="mtk1"> </span><span class="mtk12">key</span><span class="mtk1">=</span><span class="mtk4">{</span><span class="mtk12">blog</span><span class="mtk1">.</span><span class="mtk12">slug</span><span class="mtk4">}</span><span class="mtk17">&gt;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk17">&lt;</span><span class="mtk10">Link</span><span class="mtk1"> </span><span class="mtk12">href</span><span class="mtk1">=</span><span class="mtk4">{</span><span class="mtk8">`/blogs/</span><span class="mtk4">${</span><span class="mtk12">blog</span><span class="mtk1">.</span><span class="mtk12">slug</span><span class="mtk4">}</span><span class="mtk8">`</span><span class="mtk4">}</span><span class="mtk17">&gt;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk17">&lt;</span><span class="mtk4">h2</span><span class="mtk17">&gt;</span><span class="mtk4">{</span><span class="mtk12">blog</span><span class="mtk1">.</span><span class="mtk12">title</span><span class="mtk4">}</span><span class="mtk17">&lt;/</span><span class="mtk4">h2</span><span class="mtk17">&gt;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk17">&lt;</span><span class="mtk4">p</span><span class="mtk17">&gt;</span><span class="mtk4">{</span><span class="mtk12">blog</span><span class="mtk1">.</span><span class="mtk12">description</span><span class="mtk4">}</span><span class="mtk17">&lt;/</span><span class="mtk4">p</span><span class="mtk17">&gt;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk17">&lt;/</span><span class="mtk10">Link</span><span class="mtk17">&gt;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk17">&lt;/</span><span class="mtk4">li</span><span class="mtk17">&gt;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> ))</span><span class="mtk4">}</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk17">&lt;/</span><span class="mtk4">ul</span><span class="mtk17">&gt;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk17">&lt;/</span><span class="mtk4">div</span><span class="mtk17">&gt;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> );</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1">}</span></span></span></code></pre> <p>Similar to the <code>app/blogs/[slug]/page.tsx</code> file, which handles dynamic routing and displays a single blog post based on the URL slug, this page will iterate through the entire content directory, extract the metadata (frontmatter) from each post, and render them as a list.</p> <p>Now, when you navigate to <a href="http://localhost:3000/blogs">http://localhost:3000/blogs</a>, you should see a clean list of all the blog posts with titles and descriptions.</p> <p><span class="gatsby-resp-image-wrapper" style="position: relative; display: block; margin-left: auto; margin-right: auto; max-width: 720px; " > <a class="gatsby-resp-image-link" href="/static/2cd82efaa0c912e670ee445c35cff1c4/3162c/list-of-blog-posts.png" style="display: block" target="_blank" rel="noopener" > <span class="gatsby-resp-image-background-image" style="padding-bottom: 55.00000000000001%; position: relative; bottom: 0; left: 0; background-image: url('data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABQAAAALCAYAAAB/Ca1DAAAACXBIWXMAACToAAAk6AGCYwUcAAABAUlEQVR42uVQ204CMRDdD/HJBB9N/Doe1DfjV5n4ASYmijdWFARWQNmupd1eaOlhWtyY+GTQN09yctqZ6enMZPsnXRyc5tg9vMHecQetIyLpTvtqK2ZnF12cX+a4HjI8vincv0rcFQK34+2YlbMphr0BRMmx0h7Br/AbZJIbTAccRY/h5eEdfF5jaT2MWiZa7WA0nRulmK6/7k3eGocQyFAtDIqnkkwrTJ4ZJn0GyTWUsKjps5ryUUWlIT80FkxBkMYaUakUTzmqSR3GB6N8Th2WGJNGUyUMlLTJLBYa6ujHIwfq0zsPT7vzbsM4RhpFbdTRChLCJxuEb4yG+GP8Q8M1HEo926cRhY8AAAAASUVORK5CYII='); background-size: cover; display: block;" ></span> <img class="gatsby-resp-image-image" alt="nextjs blog listing page" title="" src="/static/2cd82efaa0c912e670ee445c35cff1c4/37523/list-of-blog-posts.png" srcset="/static/2cd82efaa0c912e670ee445c35cff1c4/e9ff0/list-of-blog-posts.png 180w, /static/2cd82efaa0c912e670ee445c35cff1c4/f21e7/list-of-blog-posts.png 360w, /static/2cd82efaa0c912e670ee445c35cff1c4/37523/list-of-blog-posts.png 720w, /static/2cd82efaa0c912e670ee445c35cff1c4/302a4/list-of-blog-posts.png 1080w, /static/2cd82efaa0c912e670ee445c35cff1c4/07a9c/list-of-blog-posts.png 1440w, /static/2cd82efaa0c912e670ee445c35cff1c4/3162c/list-of-blog-posts.png 2750w" sizes="(max-width: 720px) 100vw, 720px" style="width:100%;height:100%;margin:0;vertical-align:middle;position:absolute;top:0;left:0;" loading="lazy" decoding="async" /> </a> </span></p> <p><em>SEO Tip: Use meaningful <code>&#x3C;h1></code>, <code>&#x3C;h2></code> elements and meta descriptions per blog for better indexing.</em></p> <h3 id="filtering-blog-posts" style="position:relative;"><a href="#filtering-blog-posts" aria-label="filtering blog posts permalink" class="anchor before"><svg aria-hidden="true" focusable="false" height="16" version="1.1" viewBox="0 0 16 16" width="16"><path fill-rule="evenodd" d="M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z"></path></svg></a>Filtering Blog Posts</h3> <p>Given that you’re on your way to becoming a blogging superstar, it makes sense to give your readers a way to easily filter and explore your posts based on topics they care about.</p> <p>Since we already added tags to the frontmatter of each blog post, let’s build a simple but powerful filter system based on those tags.</p> <p>We’ll start by adding <code>searchParams</code> to the <code>BlogsPage</code> component. This allows us to capture the selected tag from the URL and use it to filter posts:</p> <pre class="grvsc-container default-dark" data-language="tsx" data-index="33"><code class="grvsc-code"><span class="grvsc-line"><span class="grvsc-source"><span class="mtk15">export</span><span class="mtk1"> </span><span class="mtk15">default</span><span class="mtk1"> </span><span class="mtk4">function</span><span class="mtk1"> </span><span class="mtk11">BlogsPage</span><span class="mtk1">({</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">searchParams</span><span class="mtk1">,</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1">}: {</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">searchParams</span><span class="mtk1">: { </span><span class="mtk12">tag</span><span class="mtk1">?: </span><span class="mtk10">string</span><span class="mtk1"> };</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1">}) {</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk4">const</span><span class="mtk1"> </span><span class="mtk12">selectedTag</span><span class="mtk1"> = </span><span class="mtk12">searchParams</span><span class="mtk1">?.</span><span class="mtk12">tag</span><span class="mtk1">;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> ...</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1">}</span></span></span></code></pre> <p>Thanks to the awesome App Router in Next.js 13+, <code>searchParams</code> is available directly in server components. No need for extra hooks or client-side tricks.</p> <p>Now let’s filter the blog posts using the selected tag:</p> <pre class="grvsc-container default-dark" data-language="tsx" data-index="34"><code class="grvsc-code"><span class="grvsc-line"><span class="grvsc-source"><span class="mtk4">const</span><span class="mtk1"> </span><span class="mtk12">filteredBlogs</span><span class="mtk1"> = </span><span class="mtk12">selectedTag</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> ? </span><span class="mtk12">allBlogs</span><span class="mtk1">.</span><span class="mtk11">filter</span><span class="mtk1">((</span><span class="mtk12">blog</span><span class="mtk1">: </span><span class="mtk10">any</span><span class="mtk1">) </span><span class="mtk4">=&gt;</span><span class="mtk1"> </span><span class="mtk12">blog</span><span class="mtk1">.</span><span class="mtk12">tags</span><span class="mtk1">?.</span><span class="mtk11">includes</span><span class="mtk1">(</span><span class="mtk12">selectedTag</span><span class="mtk1">))</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> : </span><span class="mtk12">allBlogs</span><span class="mtk1">;</span></span></span></code></pre> <p>This ensures that only posts matching the selected tag are shown. Pretty handy when your content library starts to overflow with posts.</p> <p>And here’s how it all comes together in <code>BlogsPage</code> component:</p> <pre class="grvsc-container default-dark" data-language="tsx" data-index="35"><code class="grvsc-code"><span class="grvsc-line"><span class="grvsc-source"><span class="mtk15">import</span><span class="mtk1"> </span><span class="mtk12">fs</span><span class="mtk1"> </span><span class="mtk15">from</span><span class="mtk1"> </span><span class="mtk8">&quot;fs&quot;</span><span class="mtk1">;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk15">import</span><span class="mtk1"> </span><span class="mtk12">path</span><span class="mtk1"> </span><span class="mtk15">from</span><span class="mtk1"> </span><span class="mtk8">&quot;path&quot;</span><span class="mtk1">;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk15">import</span><span class="mtk1"> </span><span class="mtk12">matter</span><span class="mtk1"> </span><span class="mtk15">from</span><span class="mtk1"> </span><span class="mtk8">&quot;gray-matter&quot;</span><span class="mtk1">;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk15">import</span><span class="mtk1"> </span><span class="mtk12">Link</span><span class="mtk1"> </span><span class="mtk15">from</span><span class="mtk1"> </span><span class="mtk8">&quot;next/link&quot;</span><span class="mtk1">;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk4">const</span><span class="mtk1"> </span><span class="mtk12">blogsDirectory</span><span class="mtk1"> = </span><span class="mtk12">path</span><span class="mtk1">.</span><span class="mtk11">join</span><span class="mtk1">(</span><span class="mtk12">process</span><span class="mtk1">.</span><span class="mtk11">cwd</span><span class="mtk1">(), </span><span class="mtk8">&quot;content&quot;</span><span class="mtk1">, </span><span class="mtk8">&quot;blogs&quot;</span><span class="mtk1">);</span></span></span> <span class="grvsc-line"><span class="grvsc-source"></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk15">export</span><span class="mtk1"> </span><span class="mtk15">default</span><span class="mtk1"> </span><span class="mtk4">function</span><span class="mtk1"> </span><span class="mtk11">BlogsPage</span><span class="mtk1">({</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">searchParams</span><span class="mtk1">,</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1">}: {</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">searchParams</span><span class="mtk1">: { </span><span class="mtk12">tag</span><span class="mtk1">?: </span><span class="mtk10">string</span><span class="mtk1"> };</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1">}) {</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk4">const</span><span class="mtk1"> </span><span class="mtk12">selectedTag</span><span class="mtk1"> = </span><span class="mtk12">searchParams</span><span class="mtk1">?.</span><span class="mtk12">tag</span><span class="mtk1">;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk4">const</span><span class="mtk1"> </span><span class="mtk12">blogFolders</span><span class="mtk1"> = </span><span class="mtk12">fs</span><span class="mtk1">.</span><span class="mtk11">readdirSync</span><span class="mtk1">(</span><span class="mtk12">blogsDirectory</span><span class="mtk1">);</span></span></span> <span class="grvsc-line"><span class="grvsc-source"></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk4">const</span><span class="mtk1"> </span><span class="mtk12">allBlogs</span><span class="mtk1"> = </span><span class="mtk12">blogFolders</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> .</span><span class="mtk11">filter</span><span class="mtk1">(</span><span class="mtk12">folder</span><span class="mtk1"> </span><span class="mtk4">=&gt;</span><span class="mtk1"> </span><span class="mtk12">folder</span><span class="mtk1"> !== </span><span class="mtk8">&quot;page.tsx&quot;</span><span class="mtk1">)</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> .</span><span class="mtk11">map</span><span class="mtk1">(</span><span class="mtk12">folder</span><span class="mtk1"> </span><span class="mtk4">=&gt;</span><span class="mtk1"> {</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk4">const</span><span class="mtk1"> </span><span class="mtk12">filePath</span><span class="mtk1"> = </span><span class="mtk12">path</span><span class="mtk1">.</span><span class="mtk11">join</span><span class="mtk1">(</span><span class="mtk12">blogsDirectory</span><span class="mtk1">, </span><span class="mtk12">folder</span><span class="mtk1">, </span><span class="mtk8">&quot;page.mdx&quot;</span><span class="mtk1">);</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk4">const</span><span class="mtk1"> </span><span class="mtk12">fileContent</span><span class="mtk1"> = </span><span class="mtk12">fs</span><span class="mtk1">.</span><span class="mtk11">readFileSync</span><span class="mtk1">(</span><span class="mtk12">filePath</span><span class="mtk1">, </span><span class="mtk8">&quot;utf-8&quot;</span><span class="mtk1">);</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk4">const</span><span class="mtk1"> { </span><span class="mtk12">data</span><span class="mtk1">: </span><span class="mtk12">frontmatter</span><span class="mtk1"> } = </span><span class="mtk11">matter</span><span class="mtk1">(</span><span class="mtk12">fileContent</span><span class="mtk1">);</span></span></span> <span class="grvsc-line"><span class="grvsc-source"></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk15">return</span><span class="mtk1"> {</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">slug:</span><span class="mtk1"> </span><span class="mtk12">folder</span><span class="mtk1">,</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> ...</span><span class="mtk12">frontmatter</span><span class="mtk1">,</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> };</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> });</span></span></span> <span class="grvsc-line"><span class="grvsc-source"></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk4">const</span><span class="mtk1"> </span><span class="mtk12">allTags</span><span class="mtk1"> = [</span><span class="mtk8">&quot;react&quot;</span><span class="mtk1">, </span><span class="mtk8">&quot;material-ui&quot;</span><span class="mtk1">, </span><span class="mtk8">&quot;mdx&quot;</span><span class="mtk1">, </span><span class="mtk8">&quot;nextjs&quot;</span><span class="mtk1">]; </span><span class="mtk3">// You can dynamically generate this too</span></span></span> <span class="grvsc-line"><span class="grvsc-source"></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk4">const</span><span class="mtk1"> </span><span class="mtk12">filteredBlogs</span><span class="mtk1"> = </span><span class="mtk12">selectedTag</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> ? </span><span class="mtk12">allBlogs</span><span class="mtk1">.</span><span class="mtk11">filter</span><span class="mtk1">((</span><span class="mtk12">blog</span><span class="mtk1">: </span><span class="mtk10">any</span><span class="mtk1">) </span><span class="mtk4">=&gt;</span><span class="mtk1"> </span><span class="mtk12">blog</span><span class="mtk1">.</span><span class="mtk12">tags</span><span class="mtk1">?.</span><span class="mtk11">includes</span><span class="mtk1">(</span><span class="mtk12">selectedTag</span><span class="mtk1">))</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> : </span><span class="mtk12">allBlogs</span><span class="mtk1">;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk15">return</span><span class="mtk1"> (</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk17">&lt;</span><span class="mtk4">div</span><span class="mtk17">&gt;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk17">&lt;</span><span class="mtk4">div</span><span class="mtk17">&gt;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk17">&lt;</span><span class="mtk4">h2</span><span class="mtk17">&gt;</span><span class="mtk1">Tags</span><span class="mtk17">&lt;/</span><span class="mtk4">h2</span><span class="mtk17">&gt;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk17">&lt;</span><span class="mtk4">ul</span><span class="mtk17">&gt;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk4">{</span><span class="mtk12">allTags</span><span class="mtk1">.</span><span class="mtk11">map</span><span class="mtk1">(</span><span class="mtk12">tag</span><span class="mtk1"> </span><span class="mtk4">=&gt;</span><span class="mtk1"> (</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk17">&lt;</span><span class="mtk4">li</span><span class="mtk1"> </span><span class="mtk12">key</span><span class="mtk1">=</span><span class="mtk4">{</span><span class="mtk12">tag</span><span class="mtk4">}</span><span class="mtk17">&gt;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk17">&lt;</span><span class="mtk10">Link</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">href</span><span class="mtk1">=</span><span class="mtk4">{</span><span class="mtk8">`/blogs?tag=</span><span class="mtk4">${</span><span class="mtk12">tag</span><span class="mtk4">}</span><span class="mtk8">`</span><span class="mtk4">}</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">style</span><span class="mtk1">=</span><span class="mtk4">{</span><span class="mtk1">{</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">fontWeight:</span><span class="mtk1"> </span><span class="mtk12">tag</span><span class="mtk1"> === </span><span class="mtk12">selectedTag</span><span class="mtk1"> ? </span><span class="mtk8">&quot;bold&quot;</span><span class="mtk1"> : </span><span class="mtk8">&quot;normal&quot;</span><span class="mtk1">,</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> }</span><span class="mtk4">}</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk17">&gt;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk4">{</span><span class="mtk12">tag</span><span class="mtk4">}</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk17">&lt;/</span><span class="mtk10">Link</span><span class="mtk17">&gt;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk17">&lt;/</span><span class="mtk4">li</span><span class="mtk17">&gt;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> ))</span><span class="mtk4">}</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk17">&lt;/</span><span class="mtk4">ul</span><span class="mtk17">&gt;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk17">&lt;/</span><span class="mtk4">div</span><span class="mtk17">&gt;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk17">&lt;</span><span class="mtk4">h1</span><span class="mtk17">&gt;</span><span class="mtk1">All Blogs</span><span class="mtk17">&lt;/</span><span class="mtk4">h1</span><span class="mtk17">&gt;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk17">&lt;</span><span class="mtk4">ul</span><span class="mtk17">&gt;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk4">{</span><span class="mtk12">filteredBlogs</span><span class="mtk1">.</span><span class="mtk11">map</span><span class="mtk1">((</span><span class="mtk12">blog</span><span class="mtk1">: </span><span class="mtk10">any</span><span class="mtk1">) </span><span class="mtk4">=&gt;</span><span class="mtk1"> (</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk17">&lt;</span><span class="mtk4">li</span><span class="mtk1"> </span><span class="mtk12">key</span><span class="mtk1">=</span><span class="mtk4">{</span><span class="mtk12">blog</span><span class="mtk1">.</span><span class="mtk12">slug</span><span class="mtk4">}</span><span class="mtk17">&gt;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk17">&lt;</span><span class="mtk10">Link</span><span class="mtk1"> </span><span class="mtk12">href</span><span class="mtk1">=</span><span class="mtk4">{</span><span class="mtk8">`/blogs/</span><span class="mtk4">${</span><span class="mtk12">blog</span><span class="mtk1">.</span><span class="mtk12">slug</span><span class="mtk4">}</span><span class="mtk8">`</span><span class="mtk4">}</span><span class="mtk17">&gt;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk17">&lt;</span><span class="mtk4">h2</span><span class="mtk17">&gt;</span><span class="mtk4">{</span><span class="mtk12">blog</span><span class="mtk1">.</span><span class="mtk12">title</span><span class="mtk4">}</span><span class="mtk17">&lt;/</span><span class="mtk4">h2</span><span class="mtk17">&gt;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk17">&lt;</span><span class="mtk4">p</span><span class="mtk17">&gt;</span><span class="mtk4">{</span><span class="mtk12">blog</span><span class="mtk1">.</span><span class="mtk12">description</span><span class="mtk4">}</span><span class="mtk17">&lt;/</span><span class="mtk4">p</span><span class="mtk17">&gt;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk17">&lt;/</span><span class="mtk10">Link</span><span class="mtk17">&gt;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk17">&lt;/</span><span class="mtk4">li</span><span class="mtk17">&gt;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> ))</span><span class="mtk4">}</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk17">&lt;/</span><span class="mtk4">ul</span><span class="mtk17">&gt;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk17">&lt;/</span><span class="mtk4">div</span><span class="mtk17">&gt;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> );</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1">}</span></span></span></code></pre> <p><em>We’re listing a static set of tags for now, just to keep things simple, but feel free to level up and dynamically extract tags from your blog content later.</em></p> <p>In the template, each tag is rendered as a link. When a reader clicks on one, it updates the tag query param in the URL, triggering a filter that only shows blog posts matching that tag.</p> <p>Now, if you head over to <a href="http://localhost:3000/blogs?tag=nextjs">http://localhost:3000/blogs?tag=nextjs</a>, you’ll see only the posts tagged with “nextjs”.</p> <video width="720" height="400" autoplay loop muted playsinline preload="none"> <source src="/851d22419b9bc2ce9bfd916b4f16b8e4/filtering-blog-posts.mp4" type="video/mp4"> </video> <h2 id="design-tokens--theme-configuration" style="position:relative;"><a href="#design-tokens--theme-configuration" aria-label="design tokens theme configuration permalink" class="anchor before"><svg aria-hidden="true" focusable="false" height="16" version="1.1" viewBox="0 0 16 16" width="16"><path fill-rule="evenodd" d="M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z"></path></svg></a>Design Tokens &#x26; Theme Configuration</h2> <p>From this section onward, we’ll shift focus to the design and theming side of things. We’ll explore how to create a consistent visual language using design tokens and custom theming. Code examples are all samples from the starter project. Anytime you need access to the full source, you can find it here on <a href="https://github.com/muhimasri/nextjs-mui-blog-starter">GitHub</a>.</p> <p>When it comes to styling large applications, or even moderately sized ones, consistency is key. And let’s be honest, guessing paddings and hex codes on the fly is a productivity killer. That’s where <strong>design tokens</strong> come in. Think of them as a visual grammar in your nextjs theme: reusable values for spacing, typography, colors, shadows, and more.</p> <p>In this starter, we’ve structured tokens in a single source of truth: <code>styles/tokens.ts</code>.</p> <h3 id="design-tokens-in-action" style="position:relative;"><a href="#design-tokens-in-action" aria-label="design tokens in action permalink" class="anchor before"><svg aria-hidden="true" focusable="false" height="16" version="1.1" viewBox="0 0 16 16" width="16"><path fill-rule="evenodd" d="M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z"></path></svg></a>Design Tokens in Action</h3> <p>Here’s a snippet from the <code>tokens.ts</code> file:</p> <pre class="grvsc-container default-dark" data-language="ts" data-index="36"><code class="grvsc-code"><span class="grvsc-line"><span class="grvsc-source"><span class="mtk15">export</span><span class="mtk1"> </span><span class="mtk4">const</span><span class="mtk1"> {</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">font</span><span class="mtk1">,</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">spacing</span><span class="mtk1">,</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">shadows</span><span class="mtk1">,</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">colors</span><span class="mtk1">,</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">borderRadius</span><span class="mtk1">,</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">letterSpacing</span><span class="mtk1">,</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">lineHeight</span><span class="mtk1">,</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1">} = {</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">colors:</span><span class="mtk1"> {</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">primary:</span><span class="mtk1"> {</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk7">100</span><span class="mtk12">:</span><span class="mtk1"> </span><span class="mtk8">&quot;#f6fffa&quot;</span><span class="mtk1">,</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk7">200</span><span class="mtk12">:</span><span class="mtk1"> </span><span class="mtk8">&quot;#e0fff4&quot;</span><span class="mtk1">,</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk7">300</span><span class="mtk12">:</span><span class="mtk1"> </span><span class="mtk8">&quot;#b3ffe1&quot;</span><span class="mtk1">,</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> ...</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> },</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">secondary:</span><span class="mtk1"> {</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk7">100</span><span class="mtk12">:</span><span class="mtk1"> </span><span class="mtk8">&quot;#dbdce8&quot;</span><span class="mtk1">,</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk7">200</span><span class="mtk12">:</span><span class="mtk1"> </span><span class="mtk8">&quot;#b7b9c8&quot;</span><span class="mtk1">,</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk7">300</span><span class="mtk12">:</span><span class="mtk1"> </span><span class="mtk8">&quot;#8f92a6&quot;</span><span class="mtk1">,</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> ...</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> },</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">grey:</span><span class="mtk1"> {</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk7">100</span><span class="mtk12">:</span><span class="mtk1"> </span><span class="mtk8">&quot;#f8f9fb&quot;</span><span class="mtk1">,</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk7">200</span><span class="mtk12">:</span><span class="mtk1"> </span><span class="mtk8">&quot;#f1f3f5&quot;</span><span class="mtk1">,</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk7">300</span><span class="mtk12">:</span><span class="mtk1"> </span><span class="mtk8">&quot;#e9ecef&quot;</span><span class="mtk1">,</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> ...</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> },</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> },</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">font:</span><span class="mtk1"> {</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">size:</span><span class="mtk1"> {</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk7">1</span><span class="mtk12">:</span><span class="mtk1"> </span><span class="mtk8">&quot;1rem&quot;</span><span class="mtk1">,</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk7">2</span><span class="mtk12">:</span><span class="mtk1"> </span><span class="mtk8">&quot;1.2rem&quot;</span><span class="mtk1">,</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk7">3</span><span class="mtk12">:</span><span class="mtk1"> </span><span class="mtk8">&quot;1.6rem&quot;</span><span class="mtk1">,</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> ...</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> },</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> },</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">spacing:</span><span class="mtk1"> {</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk7">1</span><span class="mtk12">:</span><span class="mtk1"> </span><span class="mtk8">&quot;0.4rem&quot;</span><span class="mtk1">,</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk7">2</span><span class="mtk12">:</span><span class="mtk1"> </span><span class="mtk8">&quot;0.8rem&quot;</span><span class="mtk1">,</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk7">3</span><span class="mtk12">:</span><span class="mtk1"> </span><span class="mtk8">&quot;1.2rem&quot;</span><span class="mtk1">,</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> ...</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> },</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">shadows:</span><span class="mtk1"> [</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk8">&quot;none&quot;</span><span class="mtk1">,</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk8">&quot;0px 1px 3px rgba(0, 0, 0, 0.12), 0px 1px 2px rgba(0, 0, 0, 0.24)&quot;</span><span class="mtk1">,</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk8">&quot;0px 3px 6px rgba(0, 0, 0, 0.16), 0px 3px 6px rgba(0, 0, 0, 0.23)&quot;</span><span class="mtk1">,</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> ...</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> ],</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">borderRadius:</span><span class="mtk1"> {</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">small:</span><span class="mtk1"> </span><span class="mtk8">&quot;4px&quot;</span><span class="mtk1">,</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">medium:</span><span class="mtk1"> </span><span class="mtk8">&quot;7px&quot;</span><span class="mtk1">,</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">pill:</span><span class="mtk1"> </span><span class="mtk8">&quot;50px&quot;</span><span class="mtk1">,</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> },</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">letterSpacing:</span><span class="mtk1"> {</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">small:</span><span class="mtk1"> </span><span class="mtk8">&quot;0.5px&quot;</span><span class="mtk1">,</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">large:</span><span class="mtk1"> </span><span class="mtk8">&quot;1px&quot;</span><span class="mtk1">,</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> },</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">lineHeight:</span><span class="mtk1"> {</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">small:</span><span class="mtk1"> </span><span class="mtk8">&quot;1.3em&quot;</span><span class="mtk1">,</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> ...</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> },</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1">};</span></span></span></code></pre> <p>These token values are simple, semantic, and most importantly, <strong>predictable</strong>. No need to wonder “Was that padding <code>1.2rem</code> or <code>1.6rem</code>?” You just reach for <code>spacing[3]</code> or <code>font.size[4]</code>, and you’re done.</p> <p>In my setup, tokens cover:</p> <ul> <li>Spacing (in steps of 4px)</li> <li>Font sizes</li> <li>Color palettes (primary, secondary, grey, etc.)</li> <li>Shadows (scalable elevation system)</li> <li>Border radius, line height, letter spacing</li> </ul> <p>This makes everything from <code>Button</code> to <code>Banner</code> look and feel like it came from the same brand playbook.</p> <h3 id="creating-the-theme" style="position:relative;"><a href="#creating-the-theme" aria-label="creating the theme permalink" class="anchor before"><svg aria-hidden="true" focusable="false" height="16" version="1.1" viewBox="0 0 16 16" width="16"><path fill-rule="evenodd" d="M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z"></path></svg></a>Creating the Theme</h3> <p>Now that we have our tokens, it’s time to wire them into the actual MUI theme using <code>createTheme</code>. Here’s a simplified look at how it comes together in <code>theme.ts</code>:</p> <pre class="grvsc-container default-dark" data-language="ts" data-index="37"><code class="grvsc-code"><span class="grvsc-line"><span class="grvsc-source"><span class="mtk8">&quot;use client&quot;</span><span class="mtk1">;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk15">import</span><span class="mtk1"> { </span><span class="mtk12">createTheme</span><span class="mtk1"> } </span><span class="mtk15">from</span><span class="mtk1"> </span><span class="mtk8">&quot;@mui/material&quot;</span><span class="mtk1">;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk15">import</span><span class="mtk1"> {</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">borderRadius</span><span class="mtk1">,</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">colors</span><span class="mtk1">,</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">font</span><span class="mtk1">,</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">letterSpacing</span><span class="mtk1">,</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">lineHeight</span><span class="mtk1">,</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1">} </span><span class="mtk15">from</span><span class="mtk1"> </span><span class="mtk8">&quot;./tokens&quot;</span><span class="mtk1">;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk4">const</span><span class="mtk1"> </span><span class="mtk12">theme</span><span class="mtk1"> = </span><span class="mtk11">createTheme</span><span class="mtk1">({</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">palette:</span><span class="mtk1"> {</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">primary:</span><span class="mtk1"> {</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">main:</span><span class="mtk1"> </span><span class="mtk12">colors</span><span class="mtk1">.</span><span class="mtk12">primary</span><span class="mtk1">[</span><span class="mtk7">500</span><span class="mtk1">],</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> },</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">secondary:</span><span class="mtk1"> {</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">main:</span><span class="mtk1"> </span><span class="mtk12">colors</span><span class="mtk1">.</span><span class="mtk12">secondary</span><span class="mtk1">[</span><span class="mtk7">500</span><span class="mtk1">],</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> },</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> },</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">typography:</span><span class="mtk1"> {</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">letterSpacing:</span><span class="mtk1"> </span><span class="mtk12">letterSpacing</span><span class="mtk1">,</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">lineHeight:</span><span class="mtk1"> </span><span class="mtk12">lineHeight</span><span class="mtk1">,</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> ...</span><span class="mtk12">font</span><span class="mtk1">.</span><span class="mtk12">size</span><span class="mtk1">,</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> },</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">shape:</span><span class="mtk1"> {</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">radius:</span><span class="mtk1"> </span><span class="mtk12">borderRadius</span><span class="mtk1">,</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> },</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1">});</span></span></span> <span class="grvsc-line"><span class="grvsc-source"></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk15">export</span><span class="mtk1"> </span><span class="mtk15">default</span><span class="mtk1"> </span><span class="mtk12">theme</span><span class="mtk1">;</span></span></span></code></pre> <p>As you can see, we’re not just dropping values randomly, we’re referencing our tokens throughout the theme. That means every <code>sx</code> prop or styled component across the app now has direct access to a design language that scales.</p> <p><strong>Why This Matters</strong></p> <p>You might be thinking: “Cool, but why not just use MUI’s defaults and tweak what I need?”</p> <p>Totally fair. But using your own tokens gives you a few massive wins:</p> <ul> <li>Consistency across components and pages</li> <li>Easy theme switching (light/dark or even brand variants)</li> <li>Reusability across projects (yep, this token setup is portable)</li> </ul> <p><strong>In short:</strong> when your design decisions are abstracted as tokens, you write less custom CSS and spend more time building features that matter.</p> <p>To get the theme showing up in the app, we need to wrap the root layout with MUI’s <code>ThemeProvider</code>:</p> <pre class="grvsc-container default-dark" data-language="tsx" data-index="38"><code class="grvsc-code"><span class="grvsc-line"><span class="grvsc-source"><span class="mtk15">import</span><span class="mtk1"> { </span><span class="mtk12">ThemeProvider</span><span class="mtk1"> } </span><span class="mtk15">from</span><span class="mtk1"> </span><span class="mtk8">&quot;@mui/material&quot;</span><span class="mtk1">;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk15">import</span><span class="mtk1"> </span><span class="mtk12">theme</span><span class="mtk1"> </span><span class="mtk15">from</span><span class="mtk1"> </span><span class="mtk8">&quot;./theme&quot;</span><span class="mtk1">;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk15">export</span><span class="mtk1"> </span><span class="mtk15">default</span><span class="mtk1"> </span><span class="mtk4">function</span><span class="mtk1"> </span><span class="mtk11">RootLayout</span><span class="mtk1">({ </span><span class="mtk12">children</span><span class="mtk1"> }) {</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk15">return</span><span class="mtk1"> </span><span class="mtk17">&lt;</span><span class="mtk10">ThemeProvider</span><span class="mtk1"> </span><span class="mtk12">theme</span><span class="mtk1">=</span><span class="mtk4">{</span><span class="mtk12">theme</span><span class="mtk4">}</span><span class="mtk17">&gt;</span><span class="mtk4">{</span><span class="mtk12">children</span><span class="mtk4">}</span><span class="mtk17">&lt;/</span><span class="mtk10">ThemeProvider</span><span class="mtk17">&gt;</span><span class="mtk1">;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1">}</span></span></span></code></pre> <p>For an in-depth look at custom theming with MUI, check out my guide: <a href="https://muhimasri.com/blogs/how-to-customize-theme-and-colors-in-material-ui/">Customizing Theme, Palette, and Colors with Material UI (MUI)</a></p> <h3 id="section-specific-palettes" style="position:relative;"><a href="#section-specific-palettes" aria-label="section specific palettes permalink" class="anchor before"><svg aria-hidden="true" focusable="false" height="16" version="1.1" viewBox="0 0 16 16" width="16"><path fill-rule="evenodd" d="M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z"></path></svg></a>Section-Specific Palettes</h3> <p>One thing I like about this theme setup is that it doesn’t just define generic MUI palette keys, it also <strong>creates palette areas for specific sections of the site</strong>:</p> <ul> <li><code>blog</code> → custom header background, h1 color, and code block styles.</li> <li><code>about</code> → custom section borders, title colors, and icon colors.</li> <li><code>postCard</code> → tag backgrounds.</li> <li><code>subscribe</code> → header text colors.</li> </ul> <p>This keeps the styling logic organized and makes it very easy to change the look of an entire section without touching multiple components.</p> <p>Example:</p> <pre class="grvsc-container default-dark" data-language="ts" data-index="39"><code class="grvsc-code"><span class="grvsc-line"><span class="grvsc-source"><span class="mtk4">const</span><span class="mtk1"> </span><span class="mtk12">theme</span><span class="mtk1"> = </span><span class="mtk11">createTheme</span><span class="mtk1">({</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">palette:</span><span class="mtk1"> {</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">primary:</span><span class="mtk1"> {</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">main:</span><span class="mtk1"> </span><span class="mtk12">colors</span><span class="mtk1">.</span><span class="mtk12">primary</span><span class="mtk1">[</span><span class="mtk7">500</span><span class="mtk1">],</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> },</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">secondary:</span><span class="mtk1"> {</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">main:</span><span class="mtk1"> </span><span class="mtk12">colors</span><span class="mtk1">.</span><span class="mtk12">secondary</span><span class="mtk1">[</span><span class="mtk7">500</span><span class="mtk1">],</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> },</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">blog:</span><span class="mtk1"> {</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">headerBgColor:</span><span class="mtk1"> </span><span class="mtk12">colors</span><span class="mtk1">.</span><span class="mtk12">secondary</span><span class="mtk1">[</span><span class="mtk7">100</span><span class="mtk1">],</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">h1Color:</span><span class="mtk1"> </span><span class="mtk12">colors</span><span class="mtk1">.</span><span class="mtk12">secondary</span><span class="mtk1">[</span><span class="mtk7">500</span><span class="mtk1">],</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">preBorderColor:</span><span class="mtk1"> </span><span class="mtk12">colors</span><span class="mtk1">.</span><span class="mtk12">secondary</span><span class="mtk1">[</span><span class="mtk7">300</span><span class="mtk1">],</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">codeBgColor:</span><span class="mtk1"> </span><span class="mtk12">colors</span><span class="mtk1">.</span><span class="mtk12">grey</span><span class="mtk1">[</span><span class="mtk7">100</span><span class="mtk1">],</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">codeTextColor:</span><span class="mtk1"> </span><span class="mtk12">colors</span><span class="mtk1">.</span><span class="mtk12">secondary</span><span class="mtk1">[</span><span class="mtk7">700</span><span class="mtk1">],</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> },</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">about:</span><span class="mtk1"> {</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">sectionBorderColor:</span><span class="mtk1"> </span><span class="mtk12">colors</span><span class="mtk1">.</span><span class="mtk12">grey</span><span class="mtk1">[</span><span class="mtk7">300</span><span class="mtk1">],</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">titleColor:</span><span class="mtk1"> </span><span class="mtk12">colors</span><span class="mtk1">.</span><span class="mtk12">primary</span><span class="mtk1">[</span><span class="mtk7">700</span><span class="mtk1">],</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">iconColor:</span><span class="mtk1"> </span><span class="mtk12">colors</span><span class="mtk1">.</span><span class="mtk12">primary</span><span class="mtk1">[</span><span class="mtk7">500</span><span class="mtk1">],</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> },</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">postCard:</span><span class="mtk1"> {</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">tagBgColor:</span><span class="mtk1"> </span><span class="mtk12">colors</span><span class="mtk1">.</span><span class="mtk12">grey</span><span class="mtk1">[</span><span class="mtk7">200</span><span class="mtk1">],</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> },</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">subscribe:</span><span class="mtk1"> {</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">headerTextColor:</span><span class="mtk1"> </span><span class="mtk12">colors</span><span class="mtk1">.</span><span class="mtk12">primary</span><span class="mtk1">[</span><span class="mtk7">700</span><span class="mtk1">],</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> },</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> },</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1">});</span></span></span></code></pre> <p>Now when we want to style the blog header component, we can simply do:</p> <pre class="grvsc-container default-dark" data-language="ts" data-index="40"><code class="grvsc-code"><span class="grvsc-line"><span class="grvsc-source"><span class="mtk4">const</span><span class="mtk1"> </span><span class="mtk11">BlogHeader</span><span class="mtk1"> = () </span><span class="mtk4">=&gt;</span><span class="mtk1"> {</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk4">const</span><span class="mtk1"> </span><span class="mtk12">theme</span><span class="mtk1"> = </span><span class="mtk11">useTheme</span><span class="mtk1">();</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk15">return</span><span class="mtk1"> (</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> &lt;</span><span class="mtk12">Box</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">sx</span><span class="mtk1">={{</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">backgroundColor:</span><span class="mtk1"> </span><span class="mtk8">&quot;blog.headerBgColor&quot;</span><span class="mtk1">,</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">color:</span><span class="mtk1"> </span><span class="mtk8">&quot;blog.h1Color&quot;</span><span class="mtk1">,</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> ...</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> }}</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> &gt;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> ...</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> &lt;/</span><span class="mtk12">Box</span><span class="mtk1">&gt;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> );</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1">};</span></span></span></code></pre> <h2 id="extending-the-mui-theme-with-custom-types" style="position:relative;"><a href="#extending-the-mui-theme-with-custom-types" aria-label="extending the mui theme with custom types permalink" class="anchor before"><svg aria-hidden="true" focusable="false" height="16" version="1.1" viewBox="0 0 16 16" width="16"><path fill-rule="evenodd" d="M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z"></path></svg></a>Extending the MUI Theme with Custom Types</h2> <p>Design tokens and theme configuration give us the structure. But if we’re serious about DX (Developer Experience), TypeScript is our best friend. Why guess what properties are available in the theme when we can get full IntelliSense and type safety?</p> <p>This is where the magic of <code>theme-types.d.ts</code> comes in.</p> <h3 id="extending-mui-theme-types" style="position:relative;"><a href="#extending-mui-theme-types" aria-label="extending mui theme types permalink" class="anchor before"><svg aria-hidden="true" focusable="false" height="16" version="1.1" viewBox="0 0 16 16" width="16"><path fill-rule="evenodd" d="M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z"></path></svg></a>Extending MUI Theme Types</h3> <p>Let’s assume we want to add a custom <code>blog</code> section to the theme palette for blog-specific properties like header background color, h1 color, and code block styles.</p> <pre class="grvsc-container default-dark" data-language="ts" data-index="41"><code class="grvsc-code"><span class="grvsc-line"><span class="grvsc-source"><span class="mtk3">// theme.ts</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk8">&quot;use client&quot;</span><span class="mtk1">;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk15">import</span><span class="mtk1"> { </span><span class="mtk12">createTheme</span><span class="mtk1"> } </span><span class="mtk15">from</span><span class="mtk1"> </span><span class="mtk8">&quot;@mui/material&quot;</span><span class="mtk1">;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk15">import</span><span class="mtk1"> { </span><span class="mtk12">colors</span><span class="mtk1"> } </span><span class="mtk15">from</span><span class="mtk1"> </span><span class="mtk8">&quot;./tokens&quot;</span><span class="mtk1">;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk4">const</span><span class="mtk1"> </span><span class="mtk12">theme</span><span class="mtk1"> = </span><span class="mtk11">createTheme</span><span class="mtk1">({</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">palette:</span><span class="mtk1"> {</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">primary:</span><span class="mtk1"> {</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">main:</span><span class="mtk1"> </span><span class="mtk12">colors</span><span class="mtk1">.</span><span class="mtk12">primary</span><span class="mtk1">[</span><span class="mtk7">500</span><span class="mtk1">],</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> },</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">secondary:</span><span class="mtk1"> {</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">main:</span><span class="mtk1"> </span><span class="mtk12">colors</span><span class="mtk1">.</span><span class="mtk12">secondary</span><span class="mtk1">[</span><span class="mtk7">500</span><span class="mtk1">],</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> },</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">blog:</span><span class="mtk1"> {</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">headerBgColor:</span><span class="mtk1"> </span><span class="mtk12">colors</span><span class="mtk1">.</span><span class="mtk12">secondary</span><span class="mtk1">[</span><span class="mtk7">100</span><span class="mtk1">],</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">h1Color:</span><span class="mtk1"> </span><span class="mtk12">colors</span><span class="mtk1">.</span><span class="mtk12">secondary</span><span class="mtk1">[</span><span class="mtk7">500</span><span class="mtk1">],</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">preBorderColor:</span><span class="mtk1"> </span><span class="mtk12">colors</span><span class="mtk1">.</span><span class="mtk12">secondary</span><span class="mtk1">[</span><span class="mtk7">300</span><span class="mtk1">],</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> },</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> },</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1">});</span></span></span> <span class="grvsc-line"><span class="grvsc-source"></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk15">export</span><span class="mtk1"> </span><span class="mtk15">default</span><span class="mtk1"> </span><span class="mtk12">theme</span><span class="mtk1">;</span></span></span></code></pre> <p>By default, MUI provides types for its palette, typography, and shape. But if we want to add custom theme sections like above, we need to tell TypeScript they exist. Otherwise, <code>theme.palette.blog?.h1Color</code> will just display red squiggles and sad vibes.</p> <p>Let’s create a new file: <code>theme-types.d.ts</code>:</p> <pre class="grvsc-container default-dark" data-language="ts" data-index="42"><code class="grvsc-code"><span class="grvsc-line"><span class="grvsc-source"><span class="mtk15">import</span><span class="mtk1"> </span><span class="mtk8">&quot;@mui/material/styles&quot;</span><span class="mtk1">;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk4">declare</span><span class="mtk1"> </span><span class="mtk4">module</span><span class="mtk1"> </span><span class="mtk8">&quot;@mui/material/styles&quot;</span><span class="mtk1"> {</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk4">interface</span><span class="mtk1"> </span><span class="mtk10">Palette</span><span class="mtk1"> {</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">blog</span><span class="mtk1">?: {</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">headerBgColor</span><span class="mtk1">: </span><span class="mtk10">string</span><span class="mtk1">;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">h1Color</span><span class="mtk1">: </span><span class="mtk10">string</span><span class="mtk1">;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">preBorderColor</span><span class="mtk1">: </span><span class="mtk10">string</span><span class="mtk1">;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> };</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> }</span></span></span> <span class="grvsc-line"><span class="grvsc-source"></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk4">interface</span><span class="mtk1"> </span><span class="mtk10">PaletteOptions</span><span class="mtk1"> {</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">blog</span><span class="mtk1">?: {</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">headerBgColor</span><span class="mtk1">: </span><span class="mtk10">string</span><span class="mtk1">;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">h1Color</span><span class="mtk1">: </span><span class="mtk10">string</span><span class="mtk1">;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">preBorderColor</span><span class="mtk1">: </span><span class="mtk10">string</span><span class="mtk1">;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> };</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> }</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1">}</span></span></span></code></pre> <p>We’re telling MUI:</p> <blockquote> <p>“Hey, we’ve got some extra sections in our theme. Don’t worry, we’ll define what keys they have and what values they expect.”</p> </blockquote> <p>We can also do the same for:</p> <ul> <li><code>shape.radius</code> (like <code>small</code>, <code>medium</code>, <code>pill</code>, <code>circle</code>)</li> <li><code>typography.letterSpacing</code></li> <li><code>typography.lineHeight</code></li> </ul> <pre class="grvsc-container default-dark" data-language="ts" data-index="43"><code class="grvsc-code"><span class="grvsc-line"><span class="grvsc-source"><span class="mtk4">declare</span><span class="mtk1"> </span><span class="mtk4">module</span><span class="mtk1"> </span><span class="mtk8">&quot;@mui/material/styles/createTypography&quot;</span><span class="mtk1"> {</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk4">interface</span><span class="mtk1"> </span><span class="mtk10">Typography</span><span class="mtk1"> {</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">letterSpacing</span><span class="mtk1">: </span><span class="mtk10">LetterSpacing</span><span class="mtk1">;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">lineHeight</span><span class="mtk1">: </span><span class="mtk10">LineHeight</span><span class="mtk1">;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> }</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk4">interface</span><span class="mtk1"> </span><span class="mtk10">TypographyOptions</span><span class="mtk1"> {</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">letterSpacing</span><span class="mtk1">?: </span><span class="mtk10">LetterSpacing</span><span class="mtk1">;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">lineHeight</span><span class="mtk1">?: </span><span class="mtk10">LineHeight</span><span class="mtk1">;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> }</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1">}</span></span></span> <span class="grvsc-line"><span class="grvsc-source"></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk4">declare</span><span class="mtk1"> </span><span class="mtk4">module</span><span class="mtk1"> </span><span class="mtk8">&quot;@mui/system/createTheme/shape&quot;</span><span class="mtk1"> {</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk4">interface</span><span class="mtk1"> </span><span class="mtk10">Shape</span><span class="mtk1"> {</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">radius</span><span class="mtk1">: </span><span class="mtk10">BorderRadius</span><span class="mtk1">;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> }</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk4">interface</span><span class="mtk1"> </span><span class="mtk10">ShapeOptions</span><span class="mtk1"> {</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">radius</span><span class="mtk1">: </span><span class="mtk10">BorderRadius</span><span class="mtk1">;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> }</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1">}</span></span></span></code></pre> <p>Now when you’re inside a component and want to do:</p> <pre class="grvsc-container default-dark" data-language="ts" data-index="44"><code class="grvsc-code"><span class="grvsc-line"><span class="grvsc-source"><span class="mtk4">const</span><span class="mtk1"> </span><span class="mtk12">theme</span><span class="mtk1"> = </span><span class="mtk11">useTheme</span><span class="mtk1">();</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk10">console</span><span class="mtk1">.</span><span class="mtk11">log</span><span class="mtk1">(</span><span class="mtk12">theme</span><span class="mtk1">.</span><span class="mtk12">palette</span><span class="mtk1">.</span><span class="mtk12">blog</span><span class="mtk1">?.</span><span class="mtk12">h1Color</span><span class="mtk1">); </span><span class="mtk3">// ✅ No more red squiggles</span></span></span></code></pre> <p>You’ll get <strong>autocompletion and type checking</strong>. It’s like having a mini design system IDE right inside your editor.</p> <h2 id="global-styles--typography-setup" style="position:relative;"><a href="#global-styles--typography-setup" aria-label="global styles typography setup permalink" class="anchor before"><svg aria-hidden="true" focusable="false" height="16" version="1.1" viewBox="0 0 16 16" width="16"><path fill-rule="evenodd" d="M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z"></path></svg></a>Global Styles &#x26; Typography Setup</h2> <p>Before a single component hits the screen, we want to make sure we have a strong <strong>basis</strong>: standard spacing, font sizing, scrollbars, and responsive scaling across different browsers.</p> <p>That’s exactly what we’ll do in <code>global.tsx</code>.</p> <h3 id="setting-global-styles-with-mui" style="position:relative;"><a href="#setting-global-styles-with-mui" aria-label="setting global styles with mui permalink" class="anchor before"><svg aria-hidden="true" focusable="false" height="16" version="1.1" viewBox="0 0 16 16" width="16"><path fill-rule="evenodd" d="M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z"></path></svg></a>Setting Global Styles with MUI</h3> <p>MUI offers a <code>GlobalStyles</code> component that lets us apply baseline styles to the <code>html</code>, <code>body</code>, or any tag. In my setup, I’m using it to enforce:</p> <ul> <li><code>fontSize</code> (root rem base)</li> <li><code>fontFamily</code> (from theme)</li> <li>Custom scrollbar styles</li> <li>Full height for the <code>html</code> element</li> </ul> <p>Here’s what it looks like:</p> <pre class="grvsc-container default-dark" data-language="tsx" data-index="45"><code class="grvsc-code"><span class="grvsc-line"><span class="grvsc-source"><span class="mtk15">import</span><span class="mtk1"> { </span><span class="mtk12">GlobalStyles</span><span class="mtk1"> } </span><span class="mtk15">from</span><span class="mtk1"> </span><span class="mtk8">&quot;@mui/material&quot;</span><span class="mtk1">;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk4">const</span><span class="mtk1"> </span><span class="mtk11">globalStyles</span><span class="mtk1"> = (</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk17">&lt;</span><span class="mtk10">GlobalStyles</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">styles</span><span class="mtk1">=</span><span class="mtk4">{</span><span class="mtk12">theme</span><span class="mtk1"> </span><span class="mtk4">=&gt;</span><span class="mtk1"> ({</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">html:</span><span class="mtk1"> {</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">height:</span><span class="mtk1"> </span><span class="mtk8">&quot;100%&quot;</span><span class="mtk1">,</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">fontSize:</span><span class="mtk1"> </span><span class="mtk8">&quot;62.5%&quot;</span><span class="mtk1">,</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">fontFamily:</span><span class="mtk1"> </span><span class="mtk12">theme</span><span class="mtk1">.</span><span class="mtk12">typography</span><span class="mtk1">.</span><span class="mtk12">fontFamily</span><span class="mtk1">,</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk8">&quot;&amp;::-webkit-scrollbar&quot;</span><span class="mtk12">:</span><span class="mtk1"> {</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">width:</span><span class="mtk1"> </span><span class="mtk7">10</span><span class="mtk1">,</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> },</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk8">&quot;&amp;::-webkit-scrollbar-track&quot;</span><span class="mtk12">:</span><span class="mtk1"> {</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">borderRadius:</span><span class="mtk1"> </span><span class="mtk12">theme</span><span class="mtk1">.</span><span class="mtk12">shape</span><span class="mtk1">.</span><span class="mtk12">radius</span><span class="mtk1">.</span><span class="mtk12">small</span><span class="mtk1">,</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> },</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk8">&quot;&amp;::-webkit-scrollbar-thumb&quot;</span><span class="mtk12">:</span><span class="mtk1"> {</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">background:</span><span class="mtk1"> </span><span class="mtk12">theme</span><span class="mtk1">.</span><span class="mtk12">palette</span><span class="mtk1">.</span><span class="mtk12">grey</span><span class="mtk1">[</span><span class="mtk7">500</span><span class="mtk1">],</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">borderRadius:</span><span class="mtk1"> </span><span class="mtk12">theme</span><span class="mtk1">.</span><span class="mtk12">shape</span><span class="mtk1">.</span><span class="mtk12">radius</span><span class="mtk1">.</span><span class="mtk12">medium</span><span class="mtk1">,</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> },</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> },</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> })</span><span class="mtk4">}</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk17">/&gt;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1">);</span></span></span> <span class="grvsc-line"><span class="grvsc-source"></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk15">export</span><span class="mtk1"> </span><span class="mtk15">default</span><span class="mtk1"> </span><span class="mtk12">globalStyles</span><span class="mtk1">;</span></span></span></code></pre> <h3 id="why-fontsize-625" style="position:relative;"><a href="#why-fontsize-625" aria-label="why fontsize 625 permalink" class="anchor before"><svg aria-hidden="true" focusable="false" height="16" version="1.1" viewBox="0 0 16 16" width="16"><path fill-rule="evenodd" d="M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z"></path></svg></a>Why fontSize: 62.5%?</h3> <p>This classic trick that sets the base <code>1rem = 10px</code>. It’s a small touch that makes spacing and sizing math-friendly:</p> <ul> <li><code>1.6rem → 16px</code></li> <li><code>2.4rem → 24px</code></li> </ul> <p>This lines up beautifully with the <code>font.size</code> and <code>spacing</code> tokens from our design system.</p> <p>To apply these styles globally, all we need to do is import and inject globalStyles inside <code>layout.tsx</code> or the root layout:</p> <pre class="grvsc-container default-dark" data-language="tsx" data-index="46"><code class="grvsc-code"><span class="grvsc-line"><span class="grvsc-source"><span class="mtk15">import</span><span class="mtk1"> </span><span class="mtk12">globalStyles</span><span class="mtk1"> </span><span class="mtk15">from</span><span class="mtk1"> </span><span class="mtk8">&quot;./styles/global&quot;</span><span class="mtk1">;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1">...</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk15">return</span><span class="mtk1"> (</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk17">&lt;</span><span class="mtk10">ThemeProvider</span><span class="mtk1"> </span><span class="mtk12">theme</span><span class="mtk1">=</span><span class="mtk4">{</span><span class="mtk12">theme</span><span class="mtk4">}</span><span class="mtk17">&gt;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk4">{</span><span class="mtk12">globalStyles</span><span class="mtk4">}</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk4">{</span><span class="mtk12">children</span><span class="mtk4">}</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk17">&lt;/</span><span class="mtk10">ThemeProvider</span><span class="mtk17">&gt;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> );</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1">};</span></span></span></code></pre> <p>And voilà! Your app now has consistent scrollbars, base font sizes, and typography that flows from the theme. For more details regarding MUI global styling, I suggest reading this small tutorial I wrote: <a href="https://muhimasri.com/blogs/mui-global-styles/">How to Create Global Styles in Material UI (MUI)</a></p> <h3 id="typography-setup-with-google-fonts" style="position:relative;"><a href="#typography-setup-with-google-fonts" aria-label="typography setup with google fonts permalink" class="anchor before"><svg aria-hidden="true" focusable="false" height="16" version="1.1" viewBox="0 0 16 16" width="16"><path fill-rule="evenodd" d="M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z"></path></svg></a>Typography Setup with Google Fonts</h3> <p>In <code>theme.ts</code> we’re importing <code>Poppins</code> from <code>next/font/google</code>, and setting it as the base theme font:</p> <pre class="grvsc-container default-dark" data-language="ts" data-index="47"><code class="grvsc-code"><span class="grvsc-line"><span class="grvsc-source"><span class="mtk15">import</span><span class="mtk1"> { </span><span class="mtk12">Poppins</span><span class="mtk1"> } </span><span class="mtk15">from</span><span class="mtk1"> </span><span class="mtk8">&quot;next/font/google&quot;</span><span class="mtk1">;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1">...</span></span></span> <span class="grvsc-line"><span class="grvsc-source"></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk4">const</span><span class="mtk1"> </span><span class="mtk12">poppins</span><span class="mtk1"> = </span><span class="mtk11">Poppins</span><span class="mtk1">({</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">weight:</span><span class="mtk1"> [</span><span class="mtk8">&quot;100&quot;</span><span class="mtk1">, </span><span class="mtk8">&quot;200&quot;</span><span class="mtk1">, </span><span class="mtk8">&quot;300&quot;</span><span class="mtk1">, </span><span class="mtk8">&quot;400&quot;</span><span class="mtk1">, </span><span class="mtk8">&quot;500&quot;</span><span class="mtk1">, </span><span class="mtk8">&quot;600&quot;</span><span class="mtk1">, </span><span class="mtk8">&quot;700&quot;</span><span class="mtk1">, </span><span class="mtk8">&quot;800&quot;</span><span class="mtk1">, </span><span class="mtk8">&quot;900&quot;</span><span class="mtk1">],</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">subsets:</span><span class="mtk1"> [</span><span class="mtk8">&quot;latin&quot;</span><span class="mtk1">],</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">display:</span><span class="mtk1"> </span><span class="mtk8">&quot;swap&quot;</span><span class="mtk1">,</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1">});</span></span></span> <span class="grvsc-line"><span class="grvsc-source"></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1">...</span></span></span> <span class="grvsc-line"><span class="grvsc-source"></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk4">const</span><span class="mtk1"> </span><span class="mtk12">theme</span><span class="mtk1"> = </span><span class="mtk11">createTheme</span><span class="mtk1">({</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> ...</span></span></span> <span class="grvsc-line"><span class="grvsc-source"></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">typography</span><span class="mtk1">: {</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">htmlFontSize:</span><span class="mtk1"> </span><span class="mtk7">10</span><span class="mtk1">,</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">fontFamily:</span><span class="mtk1"> </span><span class="mtk12">poppins</span><span class="mtk1">.</span><span class="mtk12">style</span><span class="mtk1">.</span><span class="mtk12">fontFamily</span><span class="mtk1">,</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> },</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1">});</span></span></span></code></pre> <p>This gives you:</p> <ul> <li>Smooth loading fonts (with <code>display: swap</code>)</li> <li>Strong visual identity from the get-go</li> <li><code>htmlFontSize</code> sets the base font to <code>10px</code> to match our <code>62.5%</code> global style</li> <li>And since this font setup is defined in the theme, every single component inherits it without needing to touch CSS.</li> </ul> <h2 id="component-level-styling-using-tokens" style="position:relative;"><a href="#component-level-styling-using-tokens" aria-label="component level styling using tokens permalink" class="anchor before"><svg aria-hidden="true" focusable="false" height="16" version="1.1" viewBox="0 0 16 16" width="16"><path fill-rule="evenodd" d="M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z"></path></svg></a>Component-Level Styling Using Tokens</h2> <p>With a solid theme and design tokens in place, styling individual components becomes a breeze. You can leverage MUI’s <code>sx</code> prop and direct style props to apply consistent, theme-aware styles without writing custom CSS.</p> <h3 id="sx-vs-direct-props" style="position:relative;"><a href="#sx-vs-direct-props" aria-label="sx vs direct props permalink" class="anchor before"><svg aria-hidden="true" focusable="false" height="16" version="1.1" viewBox="0 0 16 16" width="16"><path fill-rule="evenodd" d="M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z"></path></svg></a><code>sx</code> vs. Direct Props</h3> <p>The <code>sx</code> prop gives us access to the full range of CSS styles, plus theme-aware values. It’s the most flexible option:</p> <pre class="grvsc-container default-dark" data-language="tsx" data-index="48"><code class="grvsc-code"><span class="grvsc-line"><span class="grvsc-source"><span class="mtk17">&lt;</span><span class="mtk10">Toolbar</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">sx</span><span class="mtk1">=</span><span class="mtk4">{</span><span class="mtk1">{</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">py:</span><span class="mtk1"> </span><span class="mtk7">7</span><span class="mtk1">,</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">bgcolor:</span><span class="mtk1"> </span><span class="mtk8">&quot;primary.500&quot;</span><span class="mtk1">,</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">color:</span><span class="mtk1"> </span><span class="mtk8">&quot;white&quot;</span><span class="mtk1">,</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">borderBottom:</span><span class="mtk1"> </span><span class="mtk7">1</span><span class="mtk1">,</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">borderColor:</span><span class="mtk1"> </span><span class="mtk8">&quot;grey.200&quot;</span><span class="mtk1">,</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> }</span><span class="mtk4">}</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk17">&gt;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> Flexible styling with full theme access</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk17">&lt;/</span><span class="mtk10">Toolbar</span><span class="mtk17">&gt;</span></span></span></code></pre> <p>Direct props can be faster to write and in some cases apply multiple styles at once. For example, <code>color="primary"</code> in the <code>AppBar</code> component affects text, icons, and certain background states in one go:</p> <pre class="grvsc-container default-dark" data-language="tsx" data-index="49"><code class="grvsc-code"><span class="grvsc-line"><span class="grvsc-source"><span class="mtk17">&lt;</span><span class="mtk10">AppBar</span><span class="mtk1"> </span><span class="mtk12">position</span><span class="mtk1">=</span><span class="mtk8">&quot;static&quot;</span><span class="mtk1"> </span><span class="mtk12">color</span><span class="mtk1">=</span><span class="mtk8">&quot;primary&quot;</span><span class="mtk1"> </span><span class="mtk12">elevation</span><span class="mtk1">=</span><span class="mtk4">{</span><span class="mtk7">0</span><span class="mtk4">}</span><span class="mtk17">&gt;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk17">&lt;</span><span class="mtk10">Toolbar</span><span class="mtk17">&gt;</span><span class="mtk1">Direct props for quick styling</span><span class="mtk17">&lt;/</span><span class="mtk10">Toolbar</span><span class="mtk17">&gt;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk17">&lt;</span><span class="mtk10">Typography</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">fontSize</span><span class="mtk1">=</span><span class="mtk8">&quot;7&quot;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">fontWeight</span><span class="mtk1">=</span><span class="mtk8">&quot;600&quot;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">whiteSpace</span><span class="mtk1">=</span><span class="mtk8">&quot;nowrap&quot;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">color</span><span class="mtk1">=</span><span class="mtk8">&quot;primary.500&quot;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk17">&gt;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> Mareli Ramos</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk17">&lt;/</span><span class="mtk10">Typography</span><span class="mtk17">&gt;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk17">&lt;/</span><span class="mtk10">AppBar</span><span class="mtk17">&gt;</span></span></span></code></pre> <h3 id="theme-aware-shorthand" style="position:relative;"><a href="#theme-aware-shorthand" aria-label="theme aware shorthand permalink" class="anchor before"><svg aria-hidden="true" focusable="false" height="16" version="1.1" viewBox="0 0 16 16" width="16"><path fill-rule="evenodd" d="M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z"></path></svg></a>Theme-Aware Shorthand</h3> <p>MUI maps certain style props to theme keys automatically. For colors, we can use <code>primary.500</code>, <code>grey.100</code>, etc., without manually resolving them from <code>theme.palette</code>.</p> <pre class="grvsc-container default-dark" data-language="tsx" data-index="50"><code class="grvsc-code"><span class="grvsc-line"><span class="grvsc-source"><span class="mtk17">&lt;</span><span class="mtk10">Box</span><span class="mtk1"> </span><span class="mtk12">sx</span><span class="mtk1">=</span><span class="mtk4">{</span><span class="mtk1">{ </span><span class="mtk12">bgcolor:</span><span class="mtk1"> </span><span class="mtk8">&quot;grey.100&quot;</span><span class="mtk1">, </span><span class="mtk12">color:</span><span class="mtk1"> </span><span class="mtk8">&quot;primary.500&quot;</span><span class="mtk1"> }</span><span class="mtk4">}</span><span class="mtk17">&gt;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> This box uses theme palette shorthand</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk17">&lt;/</span><span class="mtk10">Box</span><span class="mtk17">&gt;</span></span></span></code></pre> <p>This corresponds to the tokens defined in <code>tokens.ts</code>:</p> <pre class="grvsc-container default-dark" data-language="ts" data-index="51"><code class="grvsc-code"><span class="grvsc-line"><span class="grvsc-source"><span class="mtk1">palette: {</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> primary: {</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk7">500</span><span class="mtk1">: </span><span class="mtk8">&#39;#0D47A1&#39;</span><span class="mtk1">,</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> ...</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> },</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> grey: {</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk7">100</span><span class="mtk1">: </span><span class="mtk8">&#39;#F5F5F5&#39;</span><span class="mtk1">,</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> ...</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> }</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1">}</span></span></span></code></pre> <p>Spacing works similarly. We can pass numbers to props like <code>gap</code>, <code>p</code>, or <code>m</code> and MUI will look up the value from the spacing scale.</p> <pre class="grvsc-container default-dark" data-language="tsx" data-index="52"><code class="grvsc-code"><span class="grvsc-line"><span class="grvsc-source"><span class="mtk17">&lt;</span><span class="mtk10">Stack</span><span class="mtk1"> </span><span class="mtk12">gap</span><span class="mtk1">=</span><span class="mtk4">{</span><span class="mtk7">4</span><span class="mtk4">}</span><span class="mtk1"> </span><span class="mtk12">p</span><span class="mtk1">=</span><span class="mtk4">{</span><span class="mtk7">2</span><span class="mtk4">}</span><span class="mtk17">&gt;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> Spaced using theme.spacing</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk17">&lt;/</span><span class="mtk10">Stack</span><span class="mtk17">&gt;</span></span></span></code></pre> <p>This corresponds to the <code>spacing</code> array in <code>tokens.ts</code>:</p> <pre class="grvsc-container default-dark" data-language="ts" data-index="53"><code class="grvsc-code"><span class="grvsc-line"><span class="grvsc-source"><span class="mtk1">spacing: [</span><span class="mtk7">0</span><span class="mtk1">, </span><span class="mtk7">4</span><span class="mtk1">, </span><span class="mtk7">8</span><span class="mtk1">, </span><span class="mtk7">12</span><span class="mtk1">, </span><span class="mtk7">16</span><span class="mtk1">, </span><span class="mtk7">20</span><span class="mtk1">, </span><span class="mtk7">24</span><span class="mtk1">, ...]</span></span></span></code></pre> <h3 id="custom-font-size-hack" style="position:relative;"><a href="#custom-font-size-hack" aria-label="custom font size hack permalink" class="anchor before"><svg aria-hidden="true" focusable="false" height="16" version="1.1" viewBox="0 0 16 16" width="16"><path fill-rule="evenodd" d="M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z"></path></svg></a>Custom Font Size Hack</h3> <p>By default, MUI’s <code>fontSize</code> expects numbers tied to a fixed scale. But since we have our own font size tokens, we can spread them directly into the <code>typography</code> section of the theme. This way, we can use our custom sizes as strings in the <code>fontSize</code> prop.</p> <p><strong>tokens.ts:</strong></p> <pre class="grvsc-container default-dark" data-language="ts" data-index="54"><code class="grvsc-code"><span class="grvsc-line"><span class="grvsc-source"><span class="mtk1">font: {</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> size: {</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk7">1</span><span class="mtk1">: </span><span class="mtk8">&#39;1rem&#39;</span><span class="mtk1">,</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk7">2</span><span class="mtk1">: </span><span class="mtk8">&#39;1.2rem&#39;</span><span class="mtk1">,</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk7">3</span><span class="mtk1">: </span><span class="mtk8">&#39;1.4rem&#39;</span><span class="mtk1">,</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk7">4</span><span class="mtk1">: </span><span class="mtk8">&#39;1.6rem&#39;</span><span class="mtk1">,</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk7">5</span><span class="mtk1">: </span><span class="mtk8">&#39;1.8rem&#39;</span><span class="mtk1">,</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk7">6</span><span class="mtk1">: </span><span class="mtk8">&#39;2rem&#39;</span><span class="mtk1">,</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk7">7</span><span class="mtk1">: </span><span class="mtk8">&#39;2.4rem&#39;</span><span class="mtk1">,</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> ...</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> }</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1">}</span></span></span></code></pre> <p><strong>theme.ts:</strong></p> <pre class="grvsc-container default-dark" data-language="ts" data-index="55"><code class="grvsc-code"><span class="grvsc-line"><span class="grvsc-source"><span class="mtk1">typography: {</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> htmlFontSize: </span><span class="mtk7">10</span><span class="mtk1">,</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> ...</span><span class="mtk12">fontFamily</span><span class="mtk1">,</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> ...</span><span class="mtk12">letterSpacing</span><span class="mtk1">,</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> ...</span><span class="mtk12">lineHeight</span><span class="mtk1">,</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> ...</span><span class="mtk12">font</span><span class="mtk1">.</span><span class="mtk12">size</span><span class="mtk1">, </span><span class="mtk3">// &lt;– Spread font sizes directly here</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1">}</span></span></span></code></pre> <p><strong>Usage:</strong></p> <pre class="grvsc-container default-dark" data-language="tsx" data-index="56"><code class="grvsc-code"><span class="grvsc-line"><span class="grvsc-source"><span class="mtk17">&lt;</span><span class="mtk10">Typography</span><span class="mtk1"> </span><span class="mtk12">fontSize</span><span class="mtk1">=</span><span class="mtk8">&quot;2&quot;</span><span class="mtk17">&gt;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> This is 1.2rem because fontSize comes from tokens</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk17">&lt;/</span><span class="mtk10">Typography</span><span class="mtk17">&gt;</span></span></span></code></pre> <p><em>Use <code>"2"</code> as a string. If you pass <code>{2}</code>, MUI will treat it as an index in its internal scale, bypassing our tokens.</em></p> <p>With these patterns, your component styles become predictable, theme-driven, and easy to refactor. No guesswork, no color-picking, just consistent design language baked into every element.</p> <h2 id="using-theme-variables-responsively" style="position:relative;"><a href="#using-theme-variables-responsively" aria-label="using theme variables responsively permalink" class="anchor before"><svg aria-hidden="true" focusable="false" height="16" version="1.1" viewBox="0 0 16 16" width="16"><path fill-rule="evenodd" d="M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z"></path></svg></a>Using Theme Variables Responsively</h2> <p>Our theme tokens aren’t just for static styles—they work beautifully with MUI’s responsive styling system. This allows us to adapt spacing, typography, and layout across different screen sizes while still staying consistent with our design language.</p> <h3 id="responsive-values-in-sx" style="position:relative;"><a href="#responsive-values-in-sx" aria-label="responsive values in sx permalink" class="anchor before"><svg aria-hidden="true" focusable="false" height="16" version="1.1" viewBox="0 0 16 16" width="16"><path fill-rule="evenodd" d="M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z"></path></svg></a>Responsive Values in <code>sx</code></h3> <p>MUI lets you pass an object keyed by breakpoints directly inside the <code>sx</code> prop. The keys correspond to breakpoints defined in the theme (<code>xs</code>, <code>sm</code>, <code>md</code>, <code>lg</code>, <code>xl</code>).</p> <pre class="grvsc-container default-dark" data-language="tsx" data-index="57"><code class="grvsc-code"><span class="grvsc-line"><span class="grvsc-source"><span class="mtk17">&lt;</span><span class="mtk10">Box</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">sx</span><span class="mtk1">=</span><span class="mtk4">{</span><span class="mtk1">{</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">p:</span><span class="mtk1"> { </span><span class="mtk12">xs:</span><span class="mtk1"> </span><span class="mtk7">2</span><span class="mtk1">, </span><span class="mtk12">md:</span><span class="mtk1"> </span><span class="mtk7">4</span><span class="mtk1"> },</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">fontSize:</span><span class="mtk1"> { </span><span class="mtk12">xs:</span><span class="mtk1"> </span><span class="mtk8">&quot;3&quot;</span><span class="mtk1">, </span><span class="mtk12">md:</span><span class="mtk1"> </span><span class="mtk8">&quot;5&quot;</span><span class="mtk1"> },</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">bgcolor:</span><span class="mtk1"> { </span><span class="mtk12">xs:</span><span class="mtk1"> </span><span class="mtk8">&quot;grey.100&quot;</span><span class="mtk1">, </span><span class="mtk12">md:</span><span class="mtk1"> </span><span class="mtk8">&quot;primary.500&quot;</span><span class="mtk1"> },</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">color:</span><span class="mtk1"> { </span><span class="mtk12">xs:</span><span class="mtk1"> </span><span class="mtk8">&quot;primary.500&quot;</span><span class="mtk1">, </span><span class="mtk12">md:</span><span class="mtk1"> </span><span class="mtk8">&quot;white&quot;</span><span class="mtk1"> },</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> }</span><span class="mtk4">}</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk17">&gt;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> Responsive box using theme values</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk17">&lt;/</span><span class="mtk10">Box</span><span class="mtk17">&gt;</span></span></span></code></pre> <p>Here, <code>p</code>, <code>fontSize</code>, <code>bgcolor</code>, and <code>color</code> all reference values from our tokens, they just change depending on the viewport size. For example, <code>p: 2</code> on small screens becomes <code>p: 4</code> on medium and up.</p> <h3 id="example-from-main-codebase" style="position:relative;"><a href="#example-from-main-codebase" aria-label="example from main codebase permalink" class="anchor before"><svg aria-hidden="true" focusable="false" height="16" version="1.1" viewBox="0 0 16 16" width="16"><path fill-rule="evenodd" d="M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z"></path></svg></a>Example from Main Codebase</h3> <p>Here’s a real example adapted from the <a href="https://github.com/muhimasri/nextjs-mui-blog-starter/blob/main/src/app/components/Banner/index.tsx">repo</a>, showing how the <code>Banner</code> component adapts typography and padding:</p> <pre class="grvsc-container default-dark" data-language="tsx" data-index="58"><code class="grvsc-code"><span class="grvsc-line"><span class="grvsc-source"><span class="mtk17">&lt;</span><span class="mtk10">Grid</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">container</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">mt</span><span class="mtk1">=</span><span class="mtk4">{</span><span class="mtk1">{ </span><span class="mtk12">xs:</span><span class="mtk1"> </span><span class="mtk7">2</span><span class="mtk1">, </span><span class="mtk12">lg:</span><span class="mtk1"> </span><span class="mtk7">6</span><span class="mtk1"> }</span><span class="mtk4">}</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">gap</span><span class="mtk1">=</span><span class="mtk4">{</span><span class="mtk7">7</span><span class="mtk4">}</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">direction</span><span class="mtk1">=</span><span class="mtk4">{</span><span class="mtk1">{ </span><span class="mtk12">xs:</span><span class="mtk1"> </span><span class="mtk8">&quot;column-reverse&quot;</span><span class="mtk1">, </span><span class="mtk12">lg:</span><span class="mtk1"> </span><span class="mtk8">&quot;row&quot;</span><span class="mtk1"> }</span><span class="mtk4">}</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">flexWrap</span><span class="mtk1">=</span><span class="mtk8">&quot;nowrap&quot;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">alignItems</span><span class="mtk1">=</span><span class="mtk8">&quot;center&quot;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">width</span><span class="mtk1">=</span><span class="mtk8">&quot;auto&quot;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk17">&gt;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> ...</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk17">&lt;/</span><span class="mtk10">Grid</span><span class="mtk17">&gt;</span></span></span></code></pre> <p>In this component:</p> <ul> <li><code>mt</code> (margin-top) uses spacing tokens, changing from <code>2</code> (8px) on small screens to <code>6</code> (24px) on large.</li> <li><code>direction</code> switches from column on small screens to row on large, adapting layout responsively.</li> </ul> <p>This tutorial has a more detailed walkthrough for creating responsive layouts: <a href="https://muhimasri.com/blogs/mui-breakpoint/">Breakpoints and Responsive Design with Material UI (MUI)</a></p> <h2 id="dark-mode-support--theme-switching" style="position:relative;"><a href="#dark-mode-support--theme-switching" aria-label="dark mode support theme switching permalink" class="anchor before"><svg aria-hidden="true" focusable="false" height="16" version="1.1" viewBox="0 0 16 16" width="16"><path fill-rule="evenodd" d="M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z"></path></svg></a>Dark Mode Support &#x26; Theme Switching</h2> <p>One of the best parts of our theming setup is how <strong>light and dark modes</strong> are handled in a completely token-driven way—with no manual color overrides scattered across components.</p> <h3 id="defining-light--dark-color-schemes" style="position:relative;"><a href="#defining-light--dark-color-schemes" aria-label="defining light dark color schemes permalink" class="anchor before"><svg aria-hidden="true" focusable="false" height="16" version="1.1" viewBox="0 0 16 16" width="16"><path fill-rule="evenodd" d="M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z"></path></svg></a>Defining Light &#x26; Dark Color Schemes</h3> <p>In <code>theme.ts</code>, we use MUI’s <code>colorSchemes</code> property to define two separate palettes: one for <code>light</code> and one for <code>dark</code>. Each using the same token names but with different values.</p> <pre class="grvsc-container default-dark" data-language="tsx" data-index="59"><code class="grvsc-code"><span class="grvsc-line"><span class="grvsc-source"><span class="mtk4">const</span><span class="mtk1"> </span><span class="mtk12">theme</span><span class="mtk1"> = </span><span class="mtk11">createTheme</span><span class="mtk1">({</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">cssVariables:</span><span class="mtk1"> { </span><span class="mtk12">colorSchemeSelector:</span><span class="mtk1"> </span><span class="mtk8">&quot;class&quot;</span><span class="mtk1"> },</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">colorSchemes:</span><span class="mtk1"> {</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">light:</span><span class="mtk1"> {</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">palette:</span><span class="mtk1"> {</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">primary:</span><span class="mtk1"> {</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">main:</span><span class="mtk1"> </span><span class="mtk12">colors</span><span class="mtk1">.</span><span class="mtk12">primary</span><span class="mtk1">[</span><span class="mtk7">500</span><span class="mtk1">],</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">contrastText:</span><span class="mtk1"> </span><span class="mtk12">colors</span><span class="mtk1">.</span><span class="mtk12">grey</span><span class="mtk1">[</span><span class="mtk7">50</span><span class="mtk1">],</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> ...</span><span class="mtk12">colors</span><span class="mtk1">.</span><span class="mtk12">primary</span><span class="mtk1">,</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> },</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">blog:</span><span class="mtk1"> {</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">headerBgColor:</span><span class="mtk1"> </span><span class="mtk11">lighten</span><span class="mtk1">(</span><span class="mtk12">colors</span><span class="mtk1">.</span><span class="mtk12">secondary</span><span class="mtk1">[</span><span class="mtk7">100</span><span class="mtk1">], </span><span class="mtk7">0.4</span><span class="mtk1">),</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">h1Color:</span><span class="mtk1"> </span><span class="mtk12">colors</span><span class="mtk1">.</span><span class="mtk12">secondary</span><span class="mtk1">[</span><span class="mtk7">500</span><span class="mtk1">],</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">preBorderColor:</span><span class="mtk1"> </span><span class="mtk12">colors</span><span class="mtk1">.</span><span class="mtk12">secondary</span><span class="mtk1">[</span><span class="mtk7">300</span><span class="mtk1">],</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> ...</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> },</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> },</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> },</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">dark:</span><span class="mtk1"> {</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">palette:</span><span class="mtk1"> {</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">primary:</span><span class="mtk1"> {</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">main:</span><span class="mtk1"> </span><span class="mtk12">colors</span><span class="mtk1">.</span><span class="mtk12">primary</span><span class="mtk1">[</span><span class="mtk7">600</span><span class="mtk1">],</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">contrastText:</span><span class="mtk1"> </span><span class="mtk12">colors</span><span class="mtk1">.</span><span class="mtk12">grey</span><span class="mtk1">[</span><span class="mtk7">50</span><span class="mtk1">],</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> ...</span><span class="mtk12">colors</span><span class="mtk1">.</span><span class="mtk12">primary</span><span class="mtk1">,</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> },</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">blog:</span><span class="mtk1"> {</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">headerBgColor:</span><span class="mtk1"> </span><span class="mtk8">&quot;black&quot;</span><span class="mtk1">,</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">h1Color:</span><span class="mtk1"> </span><span class="mtk12">colors</span><span class="mtk1">.</span><span class="mtk12">secondary</span><span class="mtk1">[</span><span class="mtk7">300</span><span class="mtk1">],</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">preBorderColor:</span><span class="mtk1"> </span><span class="mtk12">colors</span><span class="mtk1">.</span><span class="mtk12">secondary</span><span class="mtk1">[</span><span class="mtk7">700</span><span class="mtk1">],</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> ...</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> },</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> },</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> },</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1">});</span></span></span></code></pre> <p>Here’s the beauty: both modes share the <strong>same palette keys</strong> (<code>primary.main</code>, <code>blog.h1Color</code>, etc.). Which means when we switch modes, <strong>every component using theme-aware colors automatically updates</strong> without touching the component code.</p> <h3 id="switching-modes-with-usecolorscheme" style="position:relative;"><a href="#switching-modes-with-usecolorscheme" aria-label="switching modes with usecolorscheme permalink" class="anchor before"><svg aria-hidden="true" focusable="false" height="16" version="1.1" viewBox="0 0 16 16" width="16"><path fill-rule="evenodd" d="M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z"></path></svg></a>Switching Modes with <code>useColorScheme()</code></h3> <p>In <code>Header.tsx</code>, we’ll use MUI’s <code>useColorScheme()</code> hook to toggle between modes.</p> <pre class="grvsc-container grvsc-has-line-highlighting default-dark" data-language="tsx" data-index="60"><code class="grvsc-code"><span class="grvsc-line"><span class="grvsc-source"><span class="mtk8">&quot;use client&quot;</span><span class="mtk1">;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk15">import</span><span class="mtk1"> </span><span class="mtk12">AppBar</span><span class="mtk1"> </span><span class="mtk15">from</span><span class="mtk1"> </span><span class="mtk8">&quot;@mui/material/AppBar&quot;</span><span class="mtk1">;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk15">import</span><span class="mtk1"> </span><span class="mtk12">Toolbar</span><span class="mtk1"> </span><span class="mtk15">from</span><span class="mtk1"> </span><span class="mtk8">&quot;@mui/material/Toolbar&quot;</span><span class="mtk1">;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk15">import</span><span class="mtk1"> </span><span class="mtk12">Typography</span><span class="mtk1"> </span><span class="mtk15">from</span><span class="mtk1"> </span><span class="mtk8">&quot;@mui/material/Typography&quot;</span><span class="mtk1">;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk15">import</span><span class="mtk1"> </span><span class="mtk12">Button</span><span class="mtk1"> </span><span class="mtk15">from</span><span class="mtk1"> </span><span class="mtk8">&quot;@mui/material/Button&quot;</span><span class="mtk1">;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk15">import</span><span class="mtk1"> { </span><span class="mtk12">Box</span><span class="mtk1">, </span><span class="mtk12">IconButton</span><span class="mtk1">, </span><span class="mtk12">useColorScheme</span><span class="mtk1"> } </span><span class="mtk15">from</span><span class="mtk1"> </span><span class="mtk8">&quot;@mui/material&quot;</span><span class="mtk1">;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk15">export</span><span class="mtk1"> </span><span class="mtk15">default</span><span class="mtk1"> </span><span class="mtk4">function</span><span class="mtk1"> </span><span class="mtk11">Header</span><span class="mtk1">() {</span></span></span> <span class="grvsc-line grvsc-line-highlighted"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk4">const</span><span class="mtk1"> { </span><span class="mtk12">mode</span><span class="mtk1">, </span><span class="mtk12">setMode</span><span class="mtk1">, </span><span class="mtk12">systemMode</span><span class="mtk1"> } = </span><span class="mtk11">useColorScheme</span><span class="mtk1">();</span></span></span> <span class="grvsc-line grvsc-line-highlighted"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk4">const</span><span class="mtk1"> </span><span class="mtk12">isDark</span><span class="mtk1"> =</span></span></span> <span class="grvsc-line grvsc-line-highlighted"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">mode</span><span class="mtk1"> === </span><span class="mtk8">&quot;dark&quot;</span><span class="mtk1"> || (</span><span class="mtk12">mode</span><span class="mtk1"> === </span><span class="mtk8">&quot;system&quot;</span><span class="mtk1"> &amp;&amp; </span><span class="mtk12">systemMode</span><span class="mtk1"> === </span><span class="mtk8">&quot;dark&quot;</span><span class="mtk1">);</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk15">return</span><span class="mtk1"> (</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk17">&lt;&gt;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk17">&lt;</span><span class="mtk10">AppBar</span><span class="mtk1"> </span><span class="mtk12">position</span><span class="mtk1">=</span><span class="mtk8">&quot;static&quot;</span><span class="mtk17">&gt;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk17">&lt;</span><span class="mtk10">Toolbar</span><span class="mtk17">&gt;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk17">&lt;</span><span class="mtk10">Typography</span><span class="mtk1"> </span><span class="mtk12">variant</span><span class="mtk1">=</span><span class="mtk8">&quot;h6&quot;</span><span class="mtk1"> </span><span class="mtk12">mr</span><span class="mtk1">=</span><span class="mtk4">{</span><span class="mtk7">5</span><span class="mtk4">}</span><span class="mtk17">&gt;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> My Blog</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk17">&lt;/</span><span class="mtk10">Typography</span><span class="mtk17">&gt;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk17">&lt;</span><span class="mtk10">Button</span><span class="mtk1"> </span><span class="mtk12">color</span><span class="mtk1">=</span><span class="mtk8">&quot;inherit&quot;</span><span class="mtk17">&gt;</span><span class="mtk1">Home</span><span class="mtk17">&lt;/</span><span class="mtk10">Button</span><span class="mtk17">&gt;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk17">&lt;</span><span class="mtk10">Button</span><span class="mtk1"> </span><span class="mtk12">color</span><span class="mtk1">=</span><span class="mtk8">&quot;inherit&quot;</span><span class="mtk17">&gt;</span><span class="mtk1">Blog</span><span class="mtk17">&lt;/</span><span class="mtk10">Button</span><span class="mtk17">&gt;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk17">&lt;</span><span class="mtk10">Button</span><span class="mtk1"> </span><span class="mtk12">color</span><span class="mtk1">=</span><span class="mtk8">&quot;inherit&quot;</span><span class="mtk17">&gt;</span><span class="mtk1">About</span><span class="mtk17">&lt;/</span><span class="mtk10">Button</span><span class="mtk17">&gt;</span></span></span> <span class="grvsc-line grvsc-line-highlighted"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk17">&lt;</span><span class="mtk10">IconButton</span><span class="mtk1"> </span><span class="mtk12">onClick</span><span class="mtk1">=</span><span class="mtk4">{</span><span class="mtk1">() </span><span class="mtk4">=&gt;</span><span class="mtk1"> </span><span class="mtk11">setMode</span><span class="mtk1">(</span><span class="mtk12">isDark</span><span class="mtk1"> ? </span><span class="mtk8">&quot;light&quot;</span><span class="mtk1"> : </span><span class="mtk8">&quot;dark&quot;</span><span class="mtk1">)</span><span class="mtk4">}</span><span class="mtk17">&gt;</span></span></span> <span class="grvsc-line grvsc-line-highlighted"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk4">{</span><span class="mtk12">isDark</span><span class="mtk1"> ? </span><span class="mtk8">&quot;🌞&quot;</span><span class="mtk1"> : </span><span class="mtk8">&quot;🌜&quot;</span><span class="mtk4">}</span></span></span> <span class="grvsc-line grvsc-line-highlighted"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk17">&lt;/</span><span class="mtk10">IconButton</span><span class="mtk17">&gt;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk17">&lt;/</span><span class="mtk10">Toolbar</span><span class="mtk17">&gt;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk17">&lt;/</span><span class="mtk10">AppBar</span><span class="mtk17">&gt;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk17">&lt;</span><span class="mtk10">Box</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">sx</span><span class="mtk1">=</span><span class="mtk4">{</span><span class="mtk1">{</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">backgroundColor:</span><span class="mtk1"> </span><span class="mtk8">&quot;blog.headerBgColor&quot;</span><span class="mtk1">,</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">color:</span><span class="mtk1"> </span><span class="mtk8">&quot;blog.h1Color&quot;</span><span class="mtk1">,</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> }</span><span class="mtk4">}</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk17">&gt;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> Title</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk17">&lt;/</span><span class="mtk10">Box</span><span class="mtk17">&gt;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk17">&lt;/&gt;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> );</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1">}</span></span></span></code></pre> <p>The hook handles:</p> <ul> <li><code>mode</code>: current mode (<code>light</code>, <code>dark</code>, or <code>system</code>)</li> <li><code>setMode()</code>: instantly switches modes</li> <li><code>systemMode</code>: respects OS-level settings if <code>mode</code> is <code>"system"</code></li> </ul> <p><strong>Automatic Theme Updates</strong></p> <p>Since components pull styles from <code>theme.palette</code> and other tokens, toggling the mode instantly changes values like:</p> <ul> <li>Text colors (<code>text.primary</code>, <code>text.secondary</code>)</li> <li>Backgrounds (<code>background.default</code>, <code>banner.background</code>)</li> <li>Section-specific palettes (<code>blog.h1Color</code>, <code>about.headerTitle</code>)</li> </ul> <p><strong>Example:</strong> If your blog header uses <code>color="blog.h1Color"</code>, switching to dark mode swaps the color without touching the component:</p> <pre class="grvsc-container default-dark" data-language="tsx" data-index="61"><code class="grvsc-code"><span class="grvsc-line"><span class="grvsc-source"><span class="mtk17">&lt;</span><span class="mtk10">Typography</span><span class="mtk1"> </span><span class="mtk12">color</span><span class="mtk1">=</span><span class="mtk8">&quot;blog.h1Color&quot;</span><span class="mtk17">&gt;</span><span class="mtk1">Hello Dark Mode ✨</span><span class="mtk17">&lt;/</span><span class="mtk10">Typography</span><span class="mtk17">&gt;</span></span></span></code></pre> <p>Now, when going to any of the blog pages and toggling the theme, you’ll see the entire page update, including all elements.</p> <video width="720" height="400" autoplay loop muted playsinline preload="none"> <source src="/68c2b2a0562ab2933cbecdb3807c865d/dark-mode-support.mp4" type="video/mp4"> </video> <h2 id="summary" style="position:relative;"><a href="#summary" aria-label="summary permalink" class="anchor before"><svg aria-hidden="true" focusable="false" height="16" version="1.1" viewBox="0 0 16 16" width="16"><path fill-rule="evenodd" d="M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z"></path></svg></a>Summary</h2> <p>Whew, that was a lot to cover! I hope this deep dive into building a Next.js blog starter with MUI has given you a solid foundation to create your own content-rich, beautifully themed applications. You now have a reusable nextjs template to build on 🚀</p> <p>A quick recap of what we covered:</p> <ul> <li>Setting up a Next.js project with MUI and MDX (App Router SSR + MDX component mapping)</li> <li>Creating dynamic blog posts with frontmatter</li> <li>Implementing a dynamic Table of Contents (TOC)</li> <li>Adding syntax highlighting with Shiki and rehype plugins</li> <li>Embedding React components directly in MDX content</li> <li>Building a blog listing page with tag-based filtering</li> <li>Establishing a design system with tokens, custom theming, and section-specific palettes</li> <li>Extending MUI theme types for better DX</li> <li>Applying global styles and typography setup</li> <li>Styling components using theme-aware values</li> <li>Using theme variables responsively</li> <li>Implementing dark mode support with seamless theme switching</li> </ul> <p>Feel free to explore the complete source code on <a href="https://github.com/muhimasri/nextjs-mui-blog-starter">GitHub</a>, and if you found this guide helpful, please star the repo on GitHub <a href="https://github.com/muhimasri/nextjs-mui-blog-starter/stargazers">here</a>.</p> <style class="grvsc-styles"> .grvsc-container { overflow: auto; position: relative; -webkit-overflow-scrolling: touch; padding-top: 1rem; padding-top: var(--grvsc-padding-top, var(--grvsc-padding-v, 1rem)); padding-bottom: 1rem; padding-bottom: var(--grvsc-padding-bottom, var(--grvsc-padding-v, 1rem)); border-radius: 8px; border-radius: var(--grvsc-border-radius, 8px); font-feature-settings: normal; line-height: 1.4; } .grvsc-code { display: table; } .grvsc-line { display: table-row; box-sizing: border-box; width: 100%; position: relative; } .grvsc-line > * { position: relative; } .grvsc-gutter-pad { display: table-cell; padding-left: 0.75rem; padding-left: calc(var(--grvsc-padding-left, var(--grvsc-padding-h, 1.5rem)) / 2); } .grvsc-gutter { display: table-cell; -webkit-user-select: none; -moz-user-select: none; user-select: none; } .grvsc-gutter::before { content: attr(data-content); } .grvsc-source { display: table-cell; padding-left: 1.5rem; padding-left: var(--grvsc-padding-left, var(--grvsc-padding-h, 1.5rem)); padding-right: 1.5rem; padding-right: var(--grvsc-padding-right, var(--grvsc-padding-h, 1.5rem)); } .grvsc-source:empty::after { content: ' '; -webkit-user-select: none; -moz-user-select: none; user-select: none; } .grvsc-gutter + .grvsc-source { padding-left: 0.75rem; padding-left: calc(var(--grvsc-padding-left, var(--grvsc-padding-h, 1.5rem)) / 2); } /* Line transformer styles */ .grvsc-has-line-highlighting > .grvsc-code > .grvsc-line::before { content: ' '; position: absolute; width: 100%; } .grvsc-line-diff-add::before { background-color: var(--grvsc-line-diff-add-background-color, rgba(0, 255, 60, 0.2)); } .grvsc-line-diff-del::before { background-color: var(--grvsc-line-diff-del-background-color, rgba(255, 0, 20, 0.2)); } .grvsc-line-number { padding: 0 2px; text-align: right; opacity: 0.7; } .default-dark { background-color: #1E1E1E; color: #D4D4D4; } .default-dark .mtk1 { color: #D4D4D4; } .default-dark .mtk11 { color: #DCDCAA; } .default-dark .mtk15 { color: #C586C0; } .default-dark .mtk4 { color: #569CD6; } .default-dark .mtk17 { color: #808080; } .default-dark .mtk12 { color: #9CDCFE; } .default-dark .mtk8 { color: #CE9178; } .default-dark .mtk10 { color: #4EC9B0; } .default-dark .mtk3 { color: #6A9955; } .default-dark .mtk7 { color: #B5CEA8; } .default-dark .mtk5 { color: #D16969; } .default-dark .mtk6 { color: #D7BA7D; } .default-dark .grvsc-line-highlighted::before { background-color: var(--grvsc-line-highlighted-background-color, rgba(255, 255, 255, 0.1)); box-shadow: inset var(--grvsc-line-highlighted-border-width, 4px) 0 0 0 var(--grvsc-line-highlighted-border-color, rgba(255, 255, 255, 0.5)); } </style><![CDATA[Creating React Fieldset Component with MUI]]> element is a commonly used HTML element that serves a specific purpose in forms: grouping related information. For example…]]>https://muhimasri.comreact-mui-fieldsethttps://muhimasri.comreact-mui-fieldset<p>The <code>&#x3C;fieldset></code> element is a commonly used HTML element that serves a specific purpose in forms: grouping related information. For example, within a form, you might have sections like “Basic Info,” “Address,” or “Payment Info.”</p> <p>When working with frameworks like React and UI libraries like MUI, using standard HTML elements directly can sometimes feel limiting. That’s where creating a custom component comes in handy. In this tutorial, we’ll walk through how to create a custom and enhanced Fieldset component using React and MUI.</p> <p>Let’s dive in and start building this component step by step!</p> <h2 id="basic-react-fieldset" style="position:relative;"><a href="#basic-react-fieldset" aria-label="basic react fieldset permalink" class="anchor before"><svg aria-hidden="true" focusable="false" height="16" version="1.1" viewBox="0 0 16 16" width="16"><path fill-rule="evenodd" d="M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z"></path></svg></a>Basic React Fieldset</h2> <p>Let’s start by creating a basic React component named <code>Fieldset</code>. This component will encapsulate the HTML <code>&#x3C;fieldset></code> element along with its associated <code>&#x3C;legend></code> (the section’s title or label):</p> <pre class="grvsc-container default-dark" data-language="jsx" data-index="0"><code class="grvsc-code"><span class="grvsc-line"><span class="grvsc-source"><span class="mtk4">const</span><span class="mtk1"> </span><span class="mtk11">Fieldset</span><span class="mtk1"> = ({ </span><span class="mtk12">children</span><span class="mtk1"> }) </span><span class="mtk4">=&gt;</span><span class="mtk1"> {</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk15">return</span><span class="mtk1"> (</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk17">&lt;</span><span class="mtk4">fieldset</span><span class="mtk17">&gt;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk17">&lt;</span><span class="mtk4">legend</span><span class="mtk17">&gt;</span><span class="mtk1">title</span><span class="mtk17">&lt;/</span><span class="mtk4">legend</span><span class="mtk17">&gt;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk4">{</span><span class="mtk12">children</span><span class="mtk4">}</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk17">&lt;/</span><span class="mtk4">fieldset</span><span class="mtk17">&gt;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> );</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1">};</span></span></span></code></pre> <p>The <code>children</code> prop allows you to pass in any content that should be placed inside the <code>&#x3C;fieldset></code>.</p> <p>This is a good starting point, but it’s quite limited because the title is fixed and can’t be customized. There’s no way to pass additional properties or customize the component’s behavior.</p> <p>We can enhance the Fieldset component by introducing props to make it more flexible and reusable:</p> <ol> <li><strong>Customizing the Legend</strong>: We’ll introduce a <code>title</code> prop that allows us to dynamically modify the content of the <code>&#x3C;legend></code> element.</li> <li><strong>Optional Legend</strong>: If no title is provided, we can disable the rendering of the <code>&#x3C;legend></code> element altogether.</li> <li><strong>Prop Forwarding</strong>: To make our component more flexible, we’ll forward any additional props to the <code>&#x3C;fieldset></code> element.</li> </ol> <pre class="grvsc-container default-dark" data-language="jsx" data-index="1"><code class="grvsc-code"><span class="grvsc-line"><span class="grvsc-source"><span class="mtk4">const</span><span class="mtk1"> </span><span class="mtk11">Fieldset</span><span class="mtk1"> = ({ </span><span class="mtk12">title</span><span class="mtk1">, </span><span class="mtk12">children</span><span class="mtk1">, ...</span><span class="mtk12">props</span><span class="mtk1"> }) </span><span class="mtk4">=&gt;</span><span class="mtk1"> {</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk15">return</span><span class="mtk1"> (</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk17">&lt;</span><span class="mtk4">fieldset</span><span class="mtk1"> </span><span class="mtk4">{</span><span class="mtk1">...</span><span class="mtk12">props</span><span class="mtk4">}</span><span class="mtk17">&gt;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk4">{</span><span class="mtk12">title</span><span class="mtk1"> &amp;&amp; </span><span class="mtk17">&lt;</span><span class="mtk4">legend</span><span class="mtk17">&gt;</span><span class="mtk4">{</span><span class="mtk12">title</span><span class="mtk4">}</span><span class="mtk17">&lt;/</span><span class="mtk4">legend</span><span class="mtk17">&gt;</span><span class="mtk4">}</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk4">{</span><span class="mtk12">children</span><span class="mtk4">}</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk17">&lt;/</span><span class="mtk4">fieldset</span><span class="mtk17">&gt;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> );</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1">};</span></span></span></code></pre> <p>The <code>...props</code> syntax (known as the rest operator) captures all additional props passed to the <code>Fieldset</code> component. These props are then spread onto the <code>&#x3C;fieldset></code> element using <code>{...props}</code>. This allows you to directly pass any other attributes (such as className, style, id, etc.) to the <code>&#x3C;fieldset></code> element from the <code>Fieldset</code> component.</p> <p>Now that we’ve created the React component, using it is fun and straightforward! Below is an example of how it can be used within a form:</p> <pre class="grvsc-container default-dark" data-language="jsx" data-index="2"><code class="grvsc-code"><span class="grvsc-line"><span class="grvsc-source"><span class="mtk17">&lt;</span><span class="mtk4">form</span><span class="mtk17">&gt;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk17">&lt;</span><span class="mtk10">Fieldset</span><span class="mtk1"> </span><span class="mtk12">title</span><span class="mtk1">=</span><span class="mtk8">&quot;User Information&quot;</span><span class="mtk17">&gt;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk17">&lt;</span><span class="mtk4">label</span><span class="mtk17">&gt;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> Username: </span><span class="mtk17">&lt;</span><span class="mtk4">input</span><span class="mtk1"> </span><span class="mtk12">type</span><span class="mtk1">=</span><span class="mtk8">&quot;text&quot;</span><span class="mtk1"> </span><span class="mtk12">name</span><span class="mtk1">=</span><span class="mtk8">&quot;username&quot;</span><span class="mtk1"> </span><span class="mtk17">/&gt;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk17">&lt;/</span><span class="mtk4">label</span><span class="mtk17">&gt;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk17">&lt;</span><span class="mtk4">label</span><span class="mtk17">&gt;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> Password: </span><span class="mtk17">&lt;</span><span class="mtk4">input</span><span class="mtk1"> </span><span class="mtk12">type</span><span class="mtk1">=</span><span class="mtk8">&quot;password&quot;</span><span class="mtk1"> </span><span class="mtk12">name</span><span class="mtk1">=</span><span class="mtk8">&quot;password&quot;</span><span class="mtk1"> </span><span class="mtk17">/&gt;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk17">&lt;/</span><span class="mtk4">label</span><span class="mtk17">&gt;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk17">&lt;/</span><span class="mtk10">Fieldset</span><span class="mtk17">&gt;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk17">&lt;/</span><span class="mtk4">form</span><span class="mtk17">&gt;</span></span></span></code></pre> <div id="ReactFieldset" data-code data-height="100px"></div> <h2 id="advanced-mui-fieldset" style="position:relative;"><a href="#advanced-mui-fieldset" aria-label="advanced mui fieldset permalink" class="anchor before"><svg aria-hidden="true" focusable="false" height="16" version="1.1" viewBox="0 0 16 16" width="16"><path fill-rule="evenodd" d="M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z"></path></svg></a>Advanced MUI Fieldset</h2> <p>When working with MUI, you gain powerful tools for customizing styles. Thanks to the underlying theme system and the <code>sx</code> approaches for adding styles. Before we dive into styling, let’s first convert our previously created <code>Fieldset</code> React component into its equivalent MUI-based version:</p> <pre class="grvsc-container default-dark" data-language="jsx" data-index="3"><code class="grvsc-code"><span class="grvsc-line"><span class="grvsc-source"><span class="mtk15">import</span><span class="mtk1"> </span><span class="mtk12">React</span><span class="mtk1"> </span><span class="mtk15">from</span><span class="mtk1"> </span><span class="mtk8">&quot;react&quot;</span><span class="mtk1">;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk15">import</span><span class="mtk1"> { </span><span class="mtk12">Box</span><span class="mtk1">, </span><span class="mtk12">Typography</span><span class="mtk1"> } </span><span class="mtk15">from</span><span class="mtk1"> </span><span class="mtk8">&quot;@mui/material&quot;</span><span class="mtk1">;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk4">const</span><span class="mtk1"> </span><span class="mtk11">Fieldset</span><span class="mtk1"> = ({ </span><span class="mtk12">title</span><span class="mtk1">, </span><span class="mtk12">children</span><span class="mtk1">, ...</span><span class="mtk12">props</span><span class="mtk1"> }) </span><span class="mtk4">=&gt;</span><span class="mtk1"> {</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk15">return</span><span class="mtk1"> (</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk17">&lt;</span><span class="mtk10">Box</span><span class="mtk1"> </span><span class="mtk12">component</span><span class="mtk1">=</span><span class="mtk8">&quot;fieldset&quot;</span><span class="mtk1"> </span><span class="mtk4">{</span><span class="mtk1">...</span><span class="mtk12">props</span><span class="mtk4">}</span><span class="mtk17">&gt;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk4">{</span><span class="mtk12">title</span><span class="mtk1"> &amp;&amp; </span><span class="mtk17">&lt;</span><span class="mtk10">Typography</span><span class="mtk1"> </span><span class="mtk12">component</span><span class="mtk1">=</span><span class="mtk8">&quot;legend&quot;</span><span class="mtk17">&gt;</span><span class="mtk4">{</span><span class="mtk12">title</span><span class="mtk4">}</span><span class="mtk17">&lt;/</span><span class="mtk10">Typography</span><span class="mtk17">&gt;</span><span class="mtk4">}</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk4">{</span><span class="mtk12">children</span><span class="mtk4">}</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk17">&lt;/</span><span class="mtk10">Box</span><span class="mtk17">&gt;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> );</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1">};</span></span></span></code></pre> <ul> <li>The <a href="https://muhimasri.com/blogs/mui-box/">Box component</a> is a versatile wrapper that can take on the role of any HTML element via the <code>component</code> prop. In this case, we set <code>component="fieldset"</code> to ensure it renders as a <code>&#x3C;fieldset></code> in the DOM.</li> <li>The <a href="https://muhimasri.com/blogs/mui-typography/">Typography component</a> is used to render the <code>&#x3C;legend></code> element. MUI’s <code>Typography</code> component is highly flexible and allows consistent text styling across the application.</li> </ul> <h3 id="customizing-the-component-with-styling-props" style="position:relative;"><a href="#customizing-the-component-with-styling-props" aria-label="customizing the component with styling props permalink" class="anchor before"><svg aria-hidden="true" focusable="false" height="16" version="1.1" viewBox="0 0 16 16" width="16"><path fill-rule="evenodd" d="M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z"></path></svg></a>Customizing the Component with Styling Props</h3> <p>To make the component more flexible, we can introduce several props that allow for easy customization of common styling properties. These include properties for controlling the border and text styling. Since the <code>legend</code> title and the <code>fieldset</code> borders often share similar colors, we can group them for convenience.</p> <p>Here’s the enhanced version of our component:</p> <pre class="grvsc-container default-dark" data-language="jsx" data-index="4"><code class="grvsc-code"><span class="grvsc-line"><span class="grvsc-source"><span class="mtk15">import</span><span class="mtk1"> { </span><span class="mtk12">Box</span><span class="mtk1">, </span><span class="mtk12">Typography</span><span class="mtk1"> } </span><span class="mtk15">from</span><span class="mtk1"> </span><span class="mtk8">&quot;@mui/material&quot;</span><span class="mtk1">;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk4">const</span><span class="mtk1"> </span><span class="mtk11">Fieldset</span><span class="mtk1"> = ({</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">title</span><span class="mtk1">,</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">color</span><span class="mtk1"> = </span><span class="mtk8">&quot;inherit&quot;</span><span class="mtk1">,</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">titleSize</span><span class="mtk1"> = </span><span class="mtk8">&quot;1rem&quot;</span><span class="mtk1">,</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">borderWidth</span><span class="mtk1"> = </span><span class="mtk7">1</span><span class="mtk1">,</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">borderRadius</span><span class="mtk1"> = </span><span class="mtk7">2</span><span class="mtk1">,</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">children</span><span class="mtk1">,</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">sx</span><span class="mtk1"> = {},</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> ...</span><span class="mtk12">props</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1">}) </span><span class="mtk4">=&gt;</span><span class="mtk1"> {</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk15">return</span><span class="mtk1"> (</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk17">&lt;</span><span class="mtk10">Box</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">component</span><span class="mtk1">=</span><span class="mtk8">&quot;fieldset&quot;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">sx</span><span class="mtk1">=</span><span class="mtk4">{</span><span class="mtk1">{</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">borderColor:</span><span class="mtk1"> </span><span class="mtk12">color</span><span class="mtk1">,</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">borderWidth:</span><span class="mtk1"> </span><span class="mtk12">borderWidth</span><span class="mtk1">,</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">borderRadius:</span><span class="mtk1"> </span><span class="mtk12">borderRadius</span><span class="mtk1">,</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> ...</span><span class="mtk12">sx</span><span class="mtk1">,</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> }</span><span class="mtk4">}</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk4">{</span><span class="mtk1">...</span><span class="mtk12">props</span><span class="mtk4">}</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk17">&gt;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk4">{</span><span class="mtk12">title</span><span class="mtk1"> &amp;&amp; (</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk17">&lt;</span><span class="mtk10">Typography</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">component</span><span class="mtk1">=</span><span class="mtk8">&quot;legend&quot;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">sx</span><span class="mtk1">=</span><span class="mtk4">{</span><span class="mtk1">{</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">color:</span><span class="mtk1"> </span><span class="mtk12">color</span><span class="mtk1">,</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">fontSize:</span><span class="mtk1"> </span><span class="mtk12">titleSize</span><span class="mtk1">,</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> }</span><span class="mtk4">}</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk17">&gt;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk4">{</span><span class="mtk12">title</span><span class="mtk4">}</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk17">&lt;/</span><span class="mtk10">Typography</span><span class="mtk17">&gt;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> )</span><span class="mtk4">}</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk4">{</span><span class="mtk12">children</span><span class="mtk4">}</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk17">&lt;/</span><span class="mtk10">Box</span><span class="mtk17">&gt;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> );</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1">};</span></span></span></code></pre> <ul> <li>The <code>sx</code> prop allows you to use <a href="https://muhimasri.com/blogs/how-to-customize-theme-and-colors-in-material-ui/">MUI’s design tokens and theme system</a> directly within your components. In this example, we use <code>sx</code> to apply styles based on the props passed to the <code>Fieldset</code> component.</li> <li>Extending <code>sx</code> with the spread operator (<code>...sx</code>) ensures that any additional styles passed to the component do not override the existing styles.</li> <li>Using the <code>color</code> prop, we simplify the styling process, ensuring that the <code>fieldset</code> border and the <code>legend</code> text share the same color, which is a common requirement.</li> </ul> <p>Let’s look at how to use this enhanced <code>Fieldset</code> component in a React application:</p> <pre class="grvsc-container default-dark" data-language="jsx" data-index="5"><code class="grvsc-code"><span class="grvsc-line"><span class="grvsc-source"><span class="mtk17">&lt;</span><span class="mtk10">Fieldset</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">title</span><span class="mtk1">=</span><span class="mtk8">&quot;Basic Information&quot;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">color</span><span class="mtk1">=</span><span class="mtk8">&quot;secondary.main&quot;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">titleSize</span><span class="mtk1">=</span><span class="mtk8">&quot;1.1rem&quot;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">borderWidth</span><span class="mtk1">=</span><span class="mtk4">{</span><span class="mtk7">2</span><span class="mtk4">}</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">borderRadius</span><span class="mtk1">=</span><span class="mtk4">{</span><span class="mtk7">1</span><span class="mtk4">}</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk17">&gt;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk17">&lt;</span><span class="mtk4">label</span><span class="mtk17">&gt;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> Username: </span><span class="mtk17">&lt;</span><span class="mtk4">input</span><span class="mtk1"> </span><span class="mtk12">type</span><span class="mtk1">=</span><span class="mtk8">&quot;text&quot;</span><span class="mtk1"> </span><span class="mtk12">name</span><span class="mtk1">=</span><span class="mtk8">&quot;username&quot;</span><span class="mtk1"> </span><span class="mtk17">/&gt;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk17">&lt;/</span><span class="mtk4">label</span><span class="mtk17">&gt;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk17">&lt;</span><span class="mtk4">label</span><span class="mtk17">&gt;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> Password: </span><span class="mtk17">&lt;</span><span class="mtk4">input</span><span class="mtk1"> </span><span class="mtk12">type</span><span class="mtk1">=</span><span class="mtk8">&quot;password&quot;</span><span class="mtk1"> </span><span class="mtk12">name</span><span class="mtk1">=</span><span class="mtk8">&quot;password&quot;</span><span class="mtk1"> </span><span class="mtk17">/&gt;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk17">&lt;/</span><span class="mtk4">label</span><span class="mtk17">&gt;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk17">&lt;/</span><span class="mtk10">Fieldset</span><span class="mtk17">&gt;</span></span></span></code></pre> <div id="MUIFieldset" data-code data-height="100px"></div> <h3 id="advanced-styling-with-sx" style="position:relative;"><a href="#advanced-styling-with-sx" aria-label="advanced styling with sx permalink" class="anchor before"><svg aria-hidden="true" focusable="false" height="16" version="1.1" viewBox="0 0 16 16" width="16"><path fill-rule="evenodd" d="M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z"></path></svg></a>Advanced Styling with <code>sx</code></h3> <p>While the exposed props provide a convenient way to style the component, we can further customize using the <code>sx</code> prop directly. This allows for more advanced and detailed styling:</p> <pre class="grvsc-container default-dark" data-language="jsx" data-index="6"><code class="grvsc-code"><span class="grvsc-line"><span class="grvsc-source"><span class="mtk17">&lt;</span><span class="mtk10">Fieldset</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">title</span><span class="mtk1">=</span><span class="mtk8">&quot;Basic Information&quot;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">titleSize</span><span class="mtk1">=</span><span class="mtk8">&quot;1.2rem&quot;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">borderWidth</span><span class="mtk1">=</span><span class="mtk4">{</span><span class="mtk7">2</span><span class="mtk4">}</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">borderRadius</span><span class="mtk1">=</span><span class="mtk4">{</span><span class="mtk7">3</span><span class="mtk4">}</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">color</span><span class="mtk1">=</span><span class="mtk8">&quot;grey.400&quot;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">sx</span><span class="mtk1">=</span><span class="mtk4">{</span><span class="mtk1">{</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">borderStyle:</span><span class="mtk1"> </span><span class="mtk8">&quot;dashed&quot;</span><span class="mtk1">,</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">padding:</span><span class="mtk1"> </span><span class="mtk7">3</span><span class="mtk1">,</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk8">&quot;&amp; legend&quot;</span><span class="mtk12">:</span><span class="mtk1"> {</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">backgroundColor:</span><span class="mtk1"> </span><span class="mtk8">&quot;secondary.main&quot;</span><span class="mtk1">,</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">color:</span><span class="mtk1"> </span><span class="mtk8">&quot;grey.200&quot;</span><span class="mtk1">,</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">padding:</span><span class="mtk1"> </span><span class="mtk8">&quot;0 8px&quot;</span><span class="mtk1">,</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">borderRadius:</span><span class="mtk1"> </span><span class="mtk8">&quot;4px&quot;</span><span class="mtk1">,</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> },</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">backgroundColor:</span><span class="mtk1"> </span><span class="mtk8">&quot;grey.100&quot;</span><span class="mtk1">,</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> }</span><span class="mtk4">}</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk17">&gt;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk4">{</span><span class="mtk3">/* Form fields go here */</span><span class="mtk4">}</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk17">&lt;/</span><span class="mtk10">Fieldset</span><span class="mtk17">&gt;</span></span></span></code></pre> <div id="MUIFieldsetAdvanced" data-code data-height="100px"></div> <h3 id="adding-icons-to-the-title" style="position:relative;"><a href="#adding-icons-to-the-title" aria-label="adding icons to the title permalink" class="anchor before"><svg aria-hidden="true" focusable="false" height="16" version="1.1" viewBox="0 0 16 16" width="16"><path fill-rule="evenodd" d="M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z"></path></svg></a>Adding Icons to the Title</h3> <p>The title is not limited to only text. We can pass any React element to the <code>title</code> prop. In the example below, we are adding an icon right before the title:</p> <pre class="grvsc-container default-dark" data-language="jsx" data-index="7"><code class="grvsc-code"><span class="grvsc-line"><span class="grvsc-source"><span class="mtk15">import</span><span class="mtk1"> { </span><span class="mtk12">Typography</span><span class="mtk1">, </span><span class="mtk12">Stack</span><span class="mtk1"> } </span><span class="mtk15">from</span><span class="mtk1"> </span><span class="mtk8">&quot;@mui/material&quot;</span><span class="mtk1">;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk15">import</span><span class="mtk1"> </span><span class="mtk12">InfoIcon</span><span class="mtk1"> </span><span class="mtk15">from</span><span class="mtk1"> </span><span class="mtk8">&quot;@mui/icons-material/Info&quot;</span><span class="mtk1">;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk17">&lt;</span><span class="mtk10">Fieldset</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">title</span><span class="mtk1">=</span><span class="mtk4">{</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk17">&lt;</span><span class="mtk10">Stack</span><span class="mtk1"> </span><span class="mtk12">direction</span><span class="mtk1">=</span><span class="mtk8">&quot;row&quot;</span><span class="mtk1"> </span><span class="mtk12">alignItems</span><span class="mtk1">=</span><span class="mtk8">&quot;center&quot;</span><span class="mtk1"> </span><span class="mtk12">gap</span><span class="mtk1">=</span><span class="mtk4">{</span><span class="mtk7">1</span><span class="mtk4">}</span><span class="mtk17">&gt;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk17">&lt;</span><span class="mtk10">InfoIcon</span><span class="mtk1"> </span><span class="mtk17">/&gt;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> Basic Information</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk17">&lt;/</span><span class="mtk10">Stack</span><span class="mtk17">&gt;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk4">}</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">color</span><span class="mtk1">=</span><span class="mtk8">&quot;primary.main&quot;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">titleSize</span><span class="mtk1">=</span><span class="mtk8">&quot;1.2rem&quot;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">borderWidth</span><span class="mtk1">=</span><span class="mtk4">{</span><span class="mtk7">2</span><span class="mtk4">}</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">borderRadius</span><span class="mtk1">=</span><span class="mtk4">{</span><span class="mtk7">3</span><span class="mtk4">}</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk17">&gt;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk4">{</span><span class="mtk3">/* Form fields go here */</span><span class="mtk4">}</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk17">&lt;/</span><span class="mtk10">Fieldset</span><span class="mtk17">&gt;</span><span class="mtk1">;</span></span></span></code></pre> <div id="MUIFieldsetIcon" data-code data-height="100px"></div> <h2 id="using-typescript" style="position:relative;"><a href="#using-typescript" aria-label="using typescript permalink" class="anchor before"><svg aria-hidden="true" focusable="false" height="16" version="1.1" viewBox="0 0 16 16" width="16"><path fill-rule="evenodd" d="M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z"></path></svg></a>Using TypeScript</h2> <p>Making the <code>Fieldset</code> component TypeScript-friendly brings several benefits, including reducing runtime errors, providing better autocompletion and IntelliSense in editors, and acting as self-documentation for the component.</p> <p>To convert the previous <code>Fieldset</code> component to TypeScript, we need to create an interface that defines the types of the props and ensure that the component adheres to that interface:</p> <pre class="grvsc-container default-dark" data-language="jsx" data-index="8"><code class="grvsc-code"><span class="grvsc-line"><span class="grvsc-source"><span class="mtk15">import</span><span class="mtk1"> </span><span class="mtk12">React</span><span class="mtk1">, { </span><span class="mtk12">ReactNode</span><span class="mtk1"> } </span><span class="mtk15">from</span><span class="mtk1"> </span><span class="mtk8">&quot;react&quot;</span><span class="mtk1">;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk15">import</span><span class="mtk1"> { </span><span class="mtk12">Box</span><span class="mtk1">, </span><span class="mtk12">Typography</span><span class="mtk1"> } </span><span class="mtk15">from</span><span class="mtk1"> </span><span class="mtk8">&quot;@mui/material&quot;</span><span class="mtk1">;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk15">import</span><span class="mtk1"> { </span><span class="mtk12">SxProps</span><span class="mtk1">, </span><span class="mtk12">Theme</span><span class="mtk1"> } </span><span class="mtk15">from</span><span class="mtk1"> </span><span class="mtk8">&quot;@mui/system&quot;</span><span class="mtk1">;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk4">interface</span><span class="mtk1"> </span><span class="mtk10">FieldsetProps</span><span class="mtk1"> {</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">title</span><span class="mtk1">?: </span><span class="mtk10">ReactNode</span><span class="mtk1">;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">color</span><span class="mtk1">?: </span><span class="mtk10">string</span><span class="mtk1">;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">titleSize</span><span class="mtk1">?: </span><span class="mtk10">string</span><span class="mtk1">;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">borderWidth</span><span class="mtk1">?: </span><span class="mtk10">number</span><span class="mtk1">;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">borderRadius</span><span class="mtk1">?: </span><span class="mtk10">number</span><span class="mtk1">;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">children</span><span class="mtk1">: </span><span class="mtk10">ReactNode</span><span class="mtk1">;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">sx</span><span class="mtk1">?: </span><span class="mtk10">SxProps</span><span class="mtk1">&lt;</span><span class="mtk10">Theme</span><span class="mtk1">&gt;;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1">}</span></span></span> <span class="grvsc-line"><span class="grvsc-source"></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk4">const</span><span class="mtk1"> </span><span class="mtk11">Fieldset</span><span class="mtk1"> = ({</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">title</span><span class="mtk1">,</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">color</span><span class="mtk1"> = </span><span class="mtk8">&quot;grey.800&quot;</span><span class="mtk1">,</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">titleSize</span><span class="mtk1"> = </span><span class="mtk8">&quot;1rem&quot;</span><span class="mtk1">,</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">borderWidth</span><span class="mtk1"> = </span><span class="mtk7">1</span><span class="mtk1">,</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">borderRadius</span><span class="mtk1"> = </span><span class="mtk7">2</span><span class="mtk1">,</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">children</span><span class="mtk1">,</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">sx</span><span class="mtk1"> = {},</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> ...</span><span class="mtk12">props</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1">}: </span><span class="mtk10">FieldsetProps</span><span class="mtk1">) </span><span class="mtk4">=&gt;</span><span class="mtk1"> {</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk15">return</span><span class="mtk1"> (</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk17">&lt;</span><span class="mtk10">Box</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">component</span><span class="mtk1">=</span><span class="mtk8">&quot;fieldset&quot;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">sx</span><span class="mtk1">=</span><span class="mtk4">{</span><span class="mtk1">{</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">borderColor:</span><span class="mtk1"> </span><span class="mtk12">color</span><span class="mtk1">,</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">borderWidth:</span><span class="mtk1"> </span><span class="mtk12">borderWidth</span><span class="mtk1">,</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">borderRadius:</span><span class="mtk1"> </span><span class="mtk12">borderRadius</span><span class="mtk1">,</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> ...</span><span class="mtk12">sx</span><span class="mtk1">,</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> }</span><span class="mtk4">}</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk4">{</span><span class="mtk1">...</span><span class="mtk12">props</span><span class="mtk4">}</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk17">&gt;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk4">{</span><span class="mtk12">title</span><span class="mtk1"> &amp;&amp; (</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk17">&lt;</span><span class="mtk10">Typography</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">component</span><span class="mtk1">=</span><span class="mtk8">&quot;legend&quot;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">sx</span><span class="mtk1">=</span><span class="mtk4">{</span><span class="mtk1">{</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">color:</span><span class="mtk1"> </span><span class="mtk12">color</span><span class="mtk1">,</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">fontSize:</span><span class="mtk1"> </span><span class="mtk12">titleSize</span><span class="mtk1">,</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> }</span><span class="mtk4">}</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk17">&gt;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk4">{</span><span class="mtk12">title</span><span class="mtk4">}</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk17">&lt;/</span><span class="mtk10">Typography</span><span class="mtk17">&gt;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> )</span><span class="mtk4">}</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk4">{</span><span class="mtk12">children</span><span class="mtk4">}</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk17">&lt;/</span><span class="mtk10">Box</span><span class="mtk17">&gt;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> );</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1">};</span></span></span> <span class="grvsc-line"><span class="grvsc-source"></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk15">export</span><span class="mtk1"> </span><span class="mtk15">default</span><span class="mtk1"> </span><span class="mtk12">Fieldset</span><span class="mtk1">;</span></span></span></code></pre> <p>Each prop is defined in the <code>FieldsetProps</code> interface, and the component uses these types to ensure that the correct type of value is passed. For example, if a developer tries to pass a number to the title prop, TypeScript will throw an error.</p> <h2 id="summary--complete-code" style="position:relative;"><a href="#summary--complete-code" aria-label="summary complete code permalink" class="anchor before"><svg aria-hidden="true" focusable="false" height="16" version="1.1" viewBox="0 0 16 16" width="16"><path fill-rule="evenodd" d="M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z"></path></svg></a>Summary &#x26; Complete Code</h2> <p>In this tutorial, we created a customizable Fieldset component in React using Material-UI (MUI). Here’s a quick recap:</p> <ul> <li><strong>Basic Component</strong>: Started with a simple React component that encapsulates the <code>&#x3C;fieldset></code> and <code>&#x3C;legend></code> elements.</li> <li><strong>MUI Integration</strong>: Enhanced the component by using MUI’s <code>Box</code> and <code>Typography</code> components for better styling control.</li> <li><strong>Styling Flexibility</strong>: Introduced props like <code>borderColor</code>, <code>borderWidth</code>, <code>borderRadius</code>, and <code>color</code> to allow easy customization.</li> <li><strong>Advanced Styling</strong>: Demonstrated the use of the <code>sx</code> prop for more advanced, theme-based styling.</li> <li><strong>TypeScript Conversion</strong>: Converted the component to TypeScript, adding type safety and improving development with better autocompletion and documentation.</li> </ul> <p>Here is the complete live code:</p> <div data-stackblitz="react-mui-fieldset-component"> <button>Run Code</button> </div> <p>Bye for now 👋</p> <style class="grvsc-styles"> .grvsc-container { overflow: auto; position: relative; -webkit-overflow-scrolling: touch; padding-top: 1rem; padding-top: var(--grvsc-padding-top, var(--grvsc-padding-v, 1rem)); padding-bottom: 1rem; padding-bottom: var(--grvsc-padding-bottom, var(--grvsc-padding-v, 1rem)); border-radius: 8px; border-radius: var(--grvsc-border-radius, 8px); font-feature-settings: normal; line-height: 1.4; } .grvsc-code { display: table; } .grvsc-line { display: table-row; box-sizing: border-box; width: 100%; position: relative; } .grvsc-line > * { position: relative; } .grvsc-gutter-pad { display: table-cell; padding-left: 0.75rem; padding-left: calc(var(--grvsc-padding-left, var(--grvsc-padding-h, 1.5rem)) / 2); } .grvsc-gutter { display: table-cell; -webkit-user-select: none; -moz-user-select: none; user-select: none; } .grvsc-gutter::before { content: attr(data-content); } .grvsc-source { display: table-cell; padding-left: 1.5rem; padding-left: var(--grvsc-padding-left, var(--grvsc-padding-h, 1.5rem)); padding-right: 1.5rem; padding-right: var(--grvsc-padding-right, var(--grvsc-padding-h, 1.5rem)); } .grvsc-source:empty::after { content: ' '; -webkit-user-select: none; -moz-user-select: none; user-select: none; } .grvsc-gutter + .grvsc-source { padding-left: 0.75rem; padding-left: calc(var(--grvsc-padding-left, var(--grvsc-padding-h, 1.5rem)) / 2); } /* Line transformer styles */ .grvsc-has-line-highlighting > .grvsc-code > .grvsc-line::before { content: ' '; position: absolute; width: 100%; } .grvsc-line-diff-add::before { background-color: var(--grvsc-line-diff-add-background-color, rgba(0, 255, 60, 0.2)); } .grvsc-line-diff-del::before { background-color: var(--grvsc-line-diff-del-background-color, rgba(255, 0, 20, 0.2)); } .grvsc-line-number { padding: 0 2px; text-align: right; opacity: 0.7; } .default-dark { background-color: #1E1E1E; color: #D4D4D4; } .default-dark .mtk4 { color: #569CD6; } .default-dark .mtk1 { color: #D4D4D4; } .default-dark .mtk11 { color: #DCDCAA; } .default-dark .mtk12 { color: #9CDCFE; } .default-dark .mtk15 { color: #C586C0; } .default-dark .mtk17 { color: #808080; } .default-dark .mtk10 { color: #4EC9B0; } .default-dark .mtk8 { color: #CE9178; } .default-dark .mtk7 { color: #B5CEA8; } .default-dark .mtk3 { color: #6A9955; } .default-dark .grvsc-line-highlighted::before { background-color: var(--grvsc-line-highlighted-background-color, rgba(255, 255, 255, 0.1)); box-shadow: inset var(--grvsc-line-highlighted-border-width, 4px) 0 0 0 var(--grvsc-line-highlighted-border-color, rgba(255, 255, 255, 0.5)); } </style><![CDATA[React Responsive Navbar with MUI]]>https://muhimasri.commui-reponsive-navbarhttps://muhimasri.commui-reponsive-navbar<p>Creating a responsive header for mobile and other devices is essential to accessing a wider audience. Users increasingly access websites from various devices with different screen sizes, so a responsive navbar ensures a seamless and user-friendly experience.</p> <p>In this tutorial, we will learn how to create vertical tabs in React and Material UI. MUI provides a robust set of components and styling options that make the implementation of vertical tabs straightforward and highly customizable.</p> <video width="720" height="400" autoplay loop muted playsinline preload="none"> <source src="/0ce8b15c3c10c2580466a84671a1867d/mui-responsive-navbar.mp4" type="video/mp4"> </video> <h2 id="creating-a-basic-navbar" style="position:relative;"><a href="#creating-a-basic-navbar" aria-label="creating a basic navbar permalink" class="anchor before"><svg aria-hidden="true" focusable="false" height="16" version="1.1" viewBox="0 0 16 16" width="16"><path fill-rule="evenodd" d="M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z"></path></svg></a>Creating a Basic Navbar</h2> <p>To get started, we need to install MUI dependencies in our React project:</p> <pre class="grvsc-container default-dark" data-language="bash" data-index="0"><code class="grvsc-code"><span class="grvsc-line"><span class="grvsc-source"><span class="mtk1">npm install @mui/material @emotion/react @emotion/styled</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1">npm install @mui/icons-material</span></span></span></code></pre> <p>Let’s create a simple header with a logo on the left and navigation links on the right. The links will be defined in an array that we can loop through to populate the navbar, making it easy to add or remove items:</p> <pre class="grvsc-container default-dark" data-language="jsx" data-index="1"><code class="grvsc-code"><span class="grvsc-line"><span class="grvsc-source"><span class="mtk15">import</span><span class="mtk1"> </span><span class="mtk12">React</span><span class="mtk1"> </span><span class="mtk15">from</span><span class="mtk1"> </span><span class="mtk8">&quot;react&quot;</span><span class="mtk1">;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk15">import</span><span class="mtk1"> {</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">Stack</span><span class="mtk1">,</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">Link</span><span class="mtk1">,</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">Toolbar</span><span class="mtk1">,</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">Typography</span><span class="mtk1">,</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">Container</span><span class="mtk1">,</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">AppBar</span><span class="mtk1">,</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1">} </span><span class="mtk15">from</span><span class="mtk1"> </span><span class="mtk8">&quot;@mui/material&quot;</span><span class="mtk1">;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk4">const</span><span class="mtk1"> </span><span class="mtk12">pages</span><span class="mtk1"> = [</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> { </span><span class="mtk12">name:</span><span class="mtk1"> </span><span class="mtk8">&quot;Products&quot;</span><span class="mtk1">, </span><span class="mtk12">id:</span><span class="mtk1"> </span><span class="mtk8">&quot;products&quot;</span><span class="mtk1"> },</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> { </span><span class="mtk12">name:</span><span class="mtk1"> </span><span class="mtk8">&quot;Services&quot;</span><span class="mtk1">, </span><span class="mtk12">id:</span><span class="mtk1"> </span><span class="mtk8">&quot;services&quot;</span><span class="mtk1"> },</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> { </span><span class="mtk12">name:</span><span class="mtk1"> </span><span class="mtk8">&quot;About&quot;</span><span class="mtk1">, </span><span class="mtk12">id:</span><span class="mtk1"> </span><span class="mtk8">&quot;about&quot;</span><span class="mtk1"> },</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> { </span><span class="mtk12">name:</span><span class="mtk1"> </span><span class="mtk8">&quot;Testimonials&quot;</span><span class="mtk1">, </span><span class="mtk12">id:</span><span class="mtk1"> </span><span class="mtk8">&quot;testimonials&quot;</span><span class="mtk1"> },</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> { </span><span class="mtk12">name:</span><span class="mtk1"> </span><span class="mtk8">&quot;Contact&quot;</span><span class="mtk1">, </span><span class="mtk12">id:</span><span class="mtk1"> </span><span class="mtk8">&quot;contact&quot;</span><span class="mtk1"> },</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1">];</span></span></span> <span class="grvsc-line"><span class="grvsc-source"></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk4">const</span><span class="mtk1"> </span><span class="mtk11">Header</span><span class="mtk1"> = () </span><span class="mtk4">=&gt;</span><span class="mtk1"> {</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk15">return</span><span class="mtk1"> (</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk17">&lt;</span><span class="mtk10">AppBar</span><span class="mtk17">&gt;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk17">&lt;</span><span class="mtk10">Container</span><span class="mtk17">&gt;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk17">&lt;</span><span class="mtk10">Toolbar</span><span class="mtk17">&gt;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk17">&lt;</span><span class="mtk10">Stack</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">direction</span><span class="mtk1">=</span><span class="mtk8">&quot;row&quot;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">justifyContent</span><span class="mtk1">=</span><span class="mtk8">&quot;space-between&quot;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">alignItems</span><span class="mtk1">=</span><span class="mtk8">&quot;center&quot;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">width</span><span class="mtk1">=</span><span class="mtk8">&quot;100%&quot;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk17">&gt;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk17">&lt;</span><span class="mtk10">Typography</span><span class="mtk1"> </span><span class="mtk12">variant</span><span class="mtk1">=</span><span class="mtk8">&quot;h6&quot;</span><span class="mtk17">&gt;</span><span class="mtk1">My App</span><span class="mtk17">&lt;/</span><span class="mtk10">Typography</span><span class="mtk17">&gt;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk17">&lt;</span><span class="mtk10">Stack</span><span class="mtk1"> </span><span class="mtk12">direction</span><span class="mtk1">=</span><span class="mtk8">&quot;row&quot;</span><span class="mtk1"> </span><span class="mtk12">gap</span><span class="mtk1">=</span><span class="mtk4">{</span><span class="mtk7">3</span><span class="mtk4">}</span><span class="mtk17">&gt;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk4">{</span><span class="mtk12">pages</span><span class="mtk1">.</span><span class="mtk11">map</span><span class="mtk1">(</span><span class="mtk12">page</span><span class="mtk1"> </span><span class="mtk4">=&gt;</span><span class="mtk1"> (</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk17">&lt;</span><span class="mtk10">Link</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">key</span><span class="mtk1">=</span><span class="mtk4">{</span><span class="mtk12">page</span><span class="mtk1">.</span><span class="mtk12">id</span><span class="mtk4">}</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">sx</span><span class="mtk1">=</span><span class="mtk4">{</span><span class="mtk1">{</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">color:</span><span class="mtk1"> { </span><span class="mtk12">xs:</span><span class="mtk1"> </span><span class="mtk8">&quot;primary&quot;</span><span class="mtk1">, </span><span class="mtk12">sm:</span><span class="mtk1"> </span><span class="mtk8">&quot;white&quot;</span><span class="mtk1"> },</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> }</span><span class="mtk4">}</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk17">&gt;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk4">{</span><span class="mtk12">page</span><span class="mtk1">.</span><span class="mtk12">name</span><span class="mtk4">}</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk17">&lt;/</span><span class="mtk10">Link</span><span class="mtk17">&gt;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> ))</span><span class="mtk4">}</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk17">&lt;/</span><span class="mtk10">Stack</span><span class="mtk17">&gt;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk17">&lt;/</span><span class="mtk10">Stack</span><span class="mtk17">&gt;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk17">&lt;/</span><span class="mtk10">Toolbar</span><span class="mtk17">&gt;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk17">&lt;/</span><span class="mtk10">Container</span><span class="mtk17">&gt;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk17">&lt;/</span><span class="mtk10">AppBar</span><span class="mtk17">&gt;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> );</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1">};</span></span></span> <span class="grvsc-line"><span class="grvsc-source"></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk15">export</span><span class="mtk1"> </span><span class="mtk15">default</span><span class="mtk1"> </span><span class="mtk12">Header</span><span class="mtk1">;</span></span></span></code></pre> <div id="BasicNavbar" data-code data-height="150px"></div> <p>In the code above, we created a <code>Header</code> component that renders the following components from MUI:</p> <ul> <li><code>AppBar</code>: Creates an application bar that holds the navigation elements.</li> <li><code>Container</code>: Centers the content horizontally with padding on the sides.</li> <li><code>Toolbar</code>: Aligns its children horizontally, providing a flexible container within the <code>AppBar</code>.</li> <li><code>Stack</code>: Arranges the logo and navigation links in a row, with the logo on the left and links on the right.</li> </ul> <h2 id="responsive-navbar-with-a-drawer" style="position:relative;"><a href="#responsive-navbar-with-a-drawer" aria-label="responsive navbar with a drawer permalink" class="anchor before"><svg aria-hidden="true" focusable="false" height="16" version="1.1" viewBox="0 0 16 16" width="16"><path fill-rule="evenodd" d="M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z"></path></svg></a>Responsive navbar with a drawer</h2> <p>There are multiple ways to create responsive layouts in MUI, but in this tutorial, we’ll use the <code>sx</code> prop to handle the changes. For a more detailed understanding, you can refer to the tutorial on <a href="https://muhimasri.com/blogs/mui-breakpoint/">Breakpoints and Responsive Design</a>.</p> <p>Let’s walk through how to make a responsive navbar using a drawer for mobile devices.</p> <h4 id="simple-example-to-showhide-on-mobile" style="position:relative;"><a href="#simple-example-to-showhide-on-mobile" aria-label="simple example to showhide on mobile permalink" class="anchor before"><svg aria-hidden="true" focusable="false" height="16" version="1.1" viewBox="0 0 16 16" width="16"><path fill-rule="evenodd" d="M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z"></path></svg></a>Simple Example to Show/Hide on Mobile</h4> <p>First, we’ll demonstrate how to show and hide elements based on the screen size using the <code>sx</code> prop:</p> <pre class="grvsc-container default-dark" data-language="jsx" data-index="2"><code class="grvsc-code"><span class="grvsc-line"><span class="grvsc-source"><span class="mtk15">import</span><span class="mtk1"> { </span><span class="mtk12">Box</span><span class="mtk1">, </span><span class="mtk12">Typography</span><span class="mtk1"> } </span><span class="mtk15">from</span><span class="mtk1"> </span><span class="mtk8">&quot;@mui/material&quot;</span><span class="mtk1">;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk4">const</span><span class="mtk1"> </span><span class="mtk11">ResponsiveExample</span><span class="mtk1"> = () </span><span class="mtk4">=&gt;</span><span class="mtk1"> {</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk15">return</span><span class="mtk1"> (</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk17">&lt;</span><span class="mtk10">Box</span><span class="mtk17">&gt;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk17">&lt;</span><span class="mtk10">Typography</span><span class="mtk1"> </span><span class="mtk12">sx</span><span class="mtk1">=</span><span class="mtk4">{</span><span class="mtk1">{ </span><span class="mtk12">display:</span><span class="mtk1"> { </span><span class="mtk12">xs:</span><span class="mtk1"> </span><span class="mtk8">&quot;none&quot;</span><span class="mtk1">, </span><span class="mtk12">sm:</span><span class="mtk1"> </span><span class="mtk8">&quot;block&quot;</span><span class="mtk1"> } }</span><span class="mtk4">}</span><span class="mtk17">&gt;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> Other Devices</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk17">&lt;/</span><span class="mtk10">Typography</span><span class="mtk17">&gt;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk17">&lt;</span><span class="mtk10">Typography</span><span class="mtk1"> </span><span class="mtk12">sx</span><span class="mtk1">=</span><span class="mtk4">{</span><span class="mtk1">{ </span><span class="mtk12">display:</span><span class="mtk1"> { </span><span class="mtk12">xs:</span><span class="mtk1"> </span><span class="mtk8">&quot;block&quot;</span><span class="mtk1">, </span><span class="mtk12">sm:</span><span class="mtk1"> </span><span class="mtk8">&quot;none&quot;</span><span class="mtk1"> } }</span><span class="mtk4">}</span><span class="mtk17">&gt;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> Mobile Device</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk17">&lt;/</span><span class="mtk10">Typography</span><span class="mtk17">&gt;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk17">&lt;/</span><span class="mtk10">Box</span><span class="mtk17">&gt;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> );</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1">};</span></span></span> <span class="grvsc-line"><span class="grvsc-source"></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk15">export</span><span class="mtk1"> </span><span class="mtk15">default</span><span class="mtk1"> </span><span class="mtk12">ResponsiveExample</span><span class="mtk1">;</span></span></span></code></pre> <div id="ResponsiveExample" data-code data-height="150px" data-resize style="display:flex;justify-content: center;"></div> <p>The breakpoint <code>xs</code> applies to extra-small screens (mobile) up to <code>sm</code> screens (small devices). Meanwhile, <code>sm</code> applies to small devices and above because there is no breakpoint after <code>sm,</code> so it will be applied to all other screens.</p> <p>We can try to resize the window using the handle at the bottom right corner to see the text changing based on the screen size.</p> <h4 id="navlist-component" style="position:relative;"><a href="#navlist-component" aria-label="navlist component permalink" class="anchor before"><svg aria-hidden="true" focusable="false" height="16" version="1.1" viewBox="0 0 16 16" width="16"><path fill-rule="evenodd" d="M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z"></path></svg></a>NavList Component</h4> <p>We’ll start by creating a <code>NavList</code> component that will host the links and be responsible for updating the links’ direction, spacing, and other styling based on the breakpoint/device size:</p> <pre class="grvsc-container default-dark" data-language="jsx" data-index="3"><code class="grvsc-code"><span class="grvsc-line"><span class="grvsc-source"><span class="mtk4">const</span><span class="mtk1"> </span><span class="mtk11">NavList</span><span class="mtk1"> = ({ ...</span><span class="mtk12">props</span><span class="mtk1"> }) </span><span class="mtk4">=&gt;</span><span class="mtk1"> {</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk15">return</span><span class="mtk1"> (</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk17">&lt;</span><span class="mtk10">Stack</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">overflow</span><span class="mtk1">=</span><span class="mtk8">&quot;auto&quot;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">direction</span><span class="mtk1">=</span><span class="mtk4">{</span><span class="mtk1">{ </span><span class="mtk12">xs:</span><span class="mtk1"> </span><span class="mtk8">&quot;column&quot;</span><span class="mtk1">, </span><span class="mtk12">sm:</span><span class="mtk1"> </span><span class="mtk8">&quot;row&quot;</span><span class="mtk1"> }</span><span class="mtk4">}</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">gap</span><span class="mtk1">=</span><span class="mtk4">{</span><span class="mtk7">3</span><span class="mtk4">}</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">ml</span><span class="mtk1">=</span><span class="mtk4">{</span><span class="mtk1">{ </span><span class="mtk12">xs:</span><span class="mtk1"> </span><span class="mtk7">3</span><span class="mtk1">, </span><span class="mtk12">sm:</span><span class="mtk1"> </span><span class="mtk7">0</span><span class="mtk1"> }</span><span class="mtk4">}</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">mt</span><span class="mtk1">=</span><span class="mtk4">{</span><span class="mtk1">{ </span><span class="mtk12">xs:</span><span class="mtk1"> </span><span class="mtk7">3</span><span class="mtk1">, </span><span class="mtk12">sm:</span><span class="mtk1"> </span><span class="mtk7">0</span><span class="mtk1"> }</span><span class="mtk4">}</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">width</span><span class="mtk1">=</span><span class="mtk4">{</span><span class="mtk1">{ </span><span class="mtk12">xs:</span><span class="mtk1"> </span><span class="mtk8">&quot;150px&quot;</span><span class="mtk1">, </span><span class="mtk12">sm:</span><span class="mtk1"> </span><span class="mtk8">&quot;initial&quot;</span><span class="mtk1"> }</span><span class="mtk4">}</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk4">{</span><span class="mtk1">...</span><span class="mtk12">props</span><span class="mtk4">}</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk17">&gt;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk4">{</span><span class="mtk12">pages</span><span class="mtk1">.</span><span class="mtk11">map</span><span class="mtk1">(</span><span class="mtk12">page</span><span class="mtk1"> </span><span class="mtk4">=&gt;</span><span class="mtk1"> (</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk17">&lt;</span><span class="mtk10">Link</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">key</span><span class="mtk1">=</span><span class="mtk4">{</span><span class="mtk12">page</span><span class="mtk1">.</span><span class="mtk12">id</span><span class="mtk4">}</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">sx</span><span class="mtk1">=</span><span class="mtk4">{</span><span class="mtk1">{</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">color:</span><span class="mtk1"> { </span><span class="mtk12">xs:</span><span class="mtk1"> </span><span class="mtk8">&quot;primary&quot;</span><span class="mtk1">, </span><span class="mtk12">sm:</span><span class="mtk1"> </span><span class="mtk8">&quot;white&quot;</span><span class="mtk1"> },</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> }</span><span class="mtk4">}</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk17">&gt;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk4">{</span><span class="mtk12">page</span><span class="mtk1">.</span><span class="mtk12">name</span><span class="mtk4">}</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk17">&lt;/</span><span class="mtk10">Link</span><span class="mtk17">&gt;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> ))</span><span class="mtk4">}</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk17">&lt;/</span><span class="mtk10">Stack</span><span class="mtk17">&gt;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> );</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1">};</span></span></span></code></pre> <p>The <code>Stack</code> component arranges the links in a column on mobile devices and a row on larger screens. We also set the margin and width based on the screen size to ensure proper spacing and alignment of the links.</p> <h4 id="nav-component" style="position:relative;"><a href="#nav-component" aria-label="nav component permalink" class="anchor before"><svg aria-hidden="true" focusable="false" height="16" version="1.1" viewBox="0 0 16 16" width="16"><path fill-rule="evenodd" d="M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z"></path></svg></a>Nav Component</h4> <p>The <code>Nav</code> component will contain the menu button icon and <code>Drawer</code> for mobile devices. The <code>NavList</code> will be used within the <code>Drawer</code> component for mobile and displayed directly for larger screens:</p> <pre class="grvsc-container default-dark" data-language="jsx" data-index="4"><code class="grvsc-code"><span class="grvsc-line"><span class="grvsc-source"><span class="mtk4">const</span><span class="mtk1"> </span><span class="mtk11">Nav</span><span class="mtk1"> = () </span><span class="mtk4">=&gt;</span><span class="mtk1"> {</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk4">const</span><span class="mtk1"> [</span><span class="mtk12">open</span><span class="mtk1">, </span><span class="mtk12">setOpen</span><span class="mtk1">] = </span><span class="mtk11">useState</span><span class="mtk1">(</span><span class="mtk4">false</span><span class="mtk1">);</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk4">const</span><span class="mtk1"> </span><span class="mtk11">toggleDrawer</span><span class="mtk1"> = </span><span class="mtk12">newOpen</span><span class="mtk1"> </span><span class="mtk4">=&gt;</span><span class="mtk1"> () </span><span class="mtk4">=&gt;</span><span class="mtk1"> {</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk11">setOpen</span><span class="mtk1">(</span><span class="mtk12">newOpen</span><span class="mtk1">);</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> };</span></span></span> <span class="grvsc-line"><span class="grvsc-source"></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk15">return</span><span class="mtk1"> (</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk17">&lt;&gt;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk17">&lt;</span><span class="mtk10">Button</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">variant</span><span class="mtk1">=</span><span class="mtk8">&quot;text&quot;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">onClick</span><span class="mtk1">=</span><span class="mtk4">{</span><span class="mtk11">toggleDrawer</span><span class="mtk1">(</span><span class="mtk4">true</span><span class="mtk1">)</span><span class="mtk4">}</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">sx</span><span class="mtk1">=</span><span class="mtk4">{</span><span class="mtk1">{ </span><span class="mtk12">color:</span><span class="mtk1"> </span><span class="mtk8">&quot;white&quot;</span><span class="mtk1">, </span><span class="mtk12">display:</span><span class="mtk1"> { </span><span class="mtk12">xs:</span><span class="mtk1"> </span><span class="mtk8">&quot;flex&quot;</span><span class="mtk1">, </span><span class="mtk12">sm:</span><span class="mtk1"> </span><span class="mtk8">&quot;none&quot;</span><span class="mtk1"> } }</span><span class="mtk4">}</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk17">&gt;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk17">&lt;</span><span class="mtk10">MenuIcon</span><span class="mtk1"> </span><span class="mtk17">/&gt;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk17">&lt;/</span><span class="mtk10">Button</span><span class="mtk17">&gt;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk17">&lt;</span><span class="mtk10">Drawer</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">open</span><span class="mtk1">=</span><span class="mtk4">{</span><span class="mtk12">open</span><span class="mtk4">}</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">onClose</span><span class="mtk1">=</span><span class="mtk4">{</span><span class="mtk11">toggleDrawer</span><span class="mtk1">(</span><span class="mtk4">false</span><span class="mtk1">)</span><span class="mtk4">}</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">anchor</span><span class="mtk1">=</span><span class="mtk8">&quot;right&quot;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">sx</span><span class="mtk1">=</span><span class="mtk4">{</span><span class="mtk1">{</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">display:</span><span class="mtk1"> { </span><span class="mtk12">xs:</span><span class="mtk1"> </span><span class="mtk8">&quot;inherit&quot;</span><span class="mtk1">, </span><span class="mtk12">sm:</span><span class="mtk1"> </span><span class="mtk8">&quot;none&quot;</span><span class="mtk1"> },</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> }</span><span class="mtk4">}</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk17">&gt;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk17">&lt;</span><span class="mtk10">NavList</span><span class="mtk1"> </span><span class="mtk17">/&gt;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk17">&lt;/</span><span class="mtk10">Drawer</span><span class="mtk17">&gt;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk17">&lt;</span><span class="mtk10">NavList</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">sx</span><span class="mtk1">=</span><span class="mtk4">{</span><span class="mtk1">{</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">display:</span><span class="mtk1"> { </span><span class="mtk12">xs:</span><span class="mtk1"> </span><span class="mtk8">&quot;none&quot;</span><span class="mtk1">, </span><span class="mtk12">sm:</span><span class="mtk1"> </span><span class="mtk8">&quot;inherit&quot;</span><span class="mtk1"> },</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> }</span><span class="mtk4">}</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk17">/&gt;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk17">&lt;/&gt;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> );</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1">};</span></span></span></code></pre> <p>The <code>Drawer</code> component creates a sliding menu that opens from the right side of the screen on mobile devices. The <code>open</code> state and <code>toggleDrawer</code> function are used to control the drawer’s visibility.</p> <h4 id="complete-header-component" style="position:relative;"><a href="#complete-header-component" aria-label="complete header component permalink" class="anchor before"><svg aria-hidden="true" focusable="false" height="16" version="1.1" viewBox="0 0 16 16" width="16"><path fill-rule="evenodd" d="M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z"></path></svg></a>Complete Header Component</h4> <p>Now, we’ll put everything together by replacing the initial links we had in the header with the new <code>Nav</code> component:</p> <pre class="grvsc-container default-dark" data-language="jsx" data-index="5"><code class="grvsc-code"><span class="grvsc-line"><span class="grvsc-source"><span class="mtk15">import</span><span class="mtk1"> </span><span class="mtk12">React</span><span class="mtk1">, { </span><span class="mtk12">useState</span><span class="mtk1"> } </span><span class="mtk15">from</span><span class="mtk1"> </span><span class="mtk8">&quot;react&quot;</span><span class="mtk1">;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk15">import</span><span class="mtk1"> {</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">Stack</span><span class="mtk1">,</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">Link</span><span class="mtk1">,</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">Toolbar</span><span class="mtk1">,</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">Typography</span><span class="mtk1">,</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">Container</span><span class="mtk1">,</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">AppBar</span><span class="mtk1">,</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">Button</span><span class="mtk1">,</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">Drawer</span><span class="mtk1">,</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1">} </span><span class="mtk15">from</span><span class="mtk1"> </span><span class="mtk8">&quot;@mui/material&quot;</span><span class="mtk1">;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk15">import</span><span class="mtk1"> </span><span class="mtk12">MenuIcon</span><span class="mtk1"> </span><span class="mtk15">from</span><span class="mtk1"> </span><span class="mtk8">&quot;@mui/icons-material/Menu&quot;</span><span class="mtk1">;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk4">const</span><span class="mtk1"> </span><span class="mtk12">pages</span><span class="mtk1"> = [</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> { </span><span class="mtk12">name:</span><span class="mtk1"> </span><span class="mtk8">&quot;Products&quot;</span><span class="mtk1">, </span><span class="mtk12">id:</span><span class="mtk1"> </span><span class="mtk8">&quot;products&quot;</span><span class="mtk1"> },</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> { </span><span class="mtk12">name:</span><span class="mtk1"> </span><span class="mtk8">&quot;Services&quot;</span><span class="mtk1">, </span><span class="mtk12">id:</span><span class="mtk1"> </span><span class="mtk8">&quot;services&quot;</span><span class="mtk1"> },</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> { </span><span class="mtk12">name:</span><span class="mtk1"> </span><span class="mtk8">&quot;About&quot;</span><span class="mtk1">, </span><span class="mtk12">id:</span><span class="mtk1"> </span><span class="mtk8">&quot;about&quot;</span><span class="mtk1"> },</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> { </span><span class="mtk12">name:</span><span class="mtk1"> </span><span class="mtk8">&quot;Testimonials&quot;</span><span class="mtk1">, </span><span class="mtk12">id:</span><span class="mtk1"> </span><span class="mtk8">&quot;testimonials&quot;</span><span class="mtk1"> },</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> { </span><span class="mtk12">name:</span><span class="mtk1"> </span><span class="mtk8">&quot;Contact&quot;</span><span class="mtk1">, </span><span class="mtk12">id:</span><span class="mtk1"> </span><span class="mtk8">&quot;contact&quot;</span><span class="mtk1"> },</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1">];</span></span></span> <span class="grvsc-line"><span class="grvsc-source"></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk4">const</span><span class="mtk1"> </span><span class="mtk11">NavList</span><span class="mtk1"> = ({ ...</span><span class="mtk12">props</span><span class="mtk1"> }) </span><span class="mtk4">=&gt;</span><span class="mtk1"> {</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk15">return</span><span class="mtk1"> (</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk17">&lt;</span><span class="mtk10">Stack</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">overflow</span><span class="mtk1">=</span><span class="mtk8">&quot;auto&quot;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">direction</span><span class="mtk1">=</span><span class="mtk4">{</span><span class="mtk1">{ </span><span class="mtk12">xs:</span><span class="mtk1"> </span><span class="mtk8">&quot;column&quot;</span><span class="mtk1">, </span><span class="mtk12">sm:</span><span class="mtk1"> </span><span class="mtk8">&quot;row&quot;</span><span class="mtk1"> }</span><span class="mtk4">}</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">gap</span><span class="mtk1">=</span><span class="mtk4">{</span><span class="mtk7">3</span><span class="mtk4">}</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">ml</span><span class="mtk1">=</span><span class="mtk4">{</span><span class="mtk1">{ </span><span class="mtk12">xs:</span><span class="mtk1"> </span><span class="mtk7">3</span><span class="mtk1">, </span><span class="mtk12">sm:</span><span class="mtk1"> </span><span class="mtk7">0</span><span class="mtk1"> }</span><span class="mtk4">}</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">mt</span><span class="mtk1">=</span><span class="mtk4">{</span><span class="mtk1">{ </span><span class="mtk12">xs:</span><span class="mtk1"> </span><span class="mtk7">3</span><span class="mtk1">, </span><span class="mtk12">sm:</span><span class="mtk1"> </span><span class="mtk7">0</span><span class="mtk1"> }</span><span class="mtk4">}</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">width</span><span class="mtk1">=</span><span class="mtk4">{</span><span class="mtk1">{ </span><span class="mtk12">xs:</span><span class="mtk1"> </span><span class="mtk8">&quot;150px&quot;</span><span class="mtk1">, </span><span class="mtk12">sm:</span><span class="mtk1"> </span><span class="mtk8">&quot;initial&quot;</span><span class="mtk1"> }</span><span class="mtk4">}</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk4">{</span><span class="mtk1">...</span><span class="mtk12">props</span><span class="mtk4">}</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk17">&gt;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk4">{</span><span class="mtk12">pages</span><span class="mtk1">.</span><span class="mtk11">map</span><span class="mtk1">(</span><span class="mtk12">page</span><span class="mtk1"> </span><span class="mtk4">=&gt;</span><span class="mtk1"> (</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk17">&lt;</span><span class="mtk10">Link</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">key</span><span class="mtk1">=</span><span class="mtk4">{</span><span class="mtk12">page</span><span class="mtk1">.</span><span class="mtk12">id</span><span class="mtk4">}</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">sx</span><span class="mtk1">=</span><span class="mtk4">{</span><span class="mtk1">{</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">color:</span><span class="mtk1"> { </span><span class="mtk12">xs:</span><span class="mtk1"> </span><span class="mtk8">&quot;primary&quot;</span><span class="mtk1">, </span><span class="mtk12">sm:</span><span class="mtk1"> </span><span class="mtk8">&quot;white&quot;</span><span class="mtk1"> },</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> }</span><span class="mtk4">}</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk17">&gt;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk4">{</span><span class="mtk12">page</span><span class="mtk1">.</span><span class="mtk12">name</span><span class="mtk4">}</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk17">&lt;/</span><span class="mtk10">Link</span><span class="mtk17">&gt;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> ))</span><span class="mtk4">}</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk17">&lt;/</span><span class="mtk10">Stack</span><span class="mtk17">&gt;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> );</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1">};</span></span></span> <span class="grvsc-line"><span class="grvsc-source"></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk4">const</span><span class="mtk1"> </span><span class="mtk11">Nav</span><span class="mtk1"> = () </span><span class="mtk4">=&gt;</span><span class="mtk1"> {</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk4">const</span><span class="mtk1"> [</span><span class="mtk12">open</span><span class="mtk1">, </span><span class="mtk12">setOpen</span><span class="mtk1">] = </span><span class="mtk11">useState</span><span class="mtk1">(</span><span class="mtk4">false</span><span class="mtk1">);</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk4">const</span><span class="mtk1"> </span><span class="mtk11">toggleDrawer</span><span class="mtk1"> = </span><span class="mtk12">newOpen</span><span class="mtk1"> </span><span class="mtk4">=&gt;</span><span class="mtk1"> () </span><span class="mtk4">=&gt;</span><span class="mtk1"> {</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk11">setOpen</span><span class="mtk1">(</span><span class="mtk12">newOpen</span><span class="mtk1">);</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> };</span></span></span> <span class="grvsc-line"><span class="grvsc-source"></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk15">return</span><span class="mtk1"> (</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk17">&lt;&gt;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk17">&lt;</span><span class="mtk10">Button</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">variant</span><span class="mtk1">=</span><span class="mtk8">&quot;text&quot;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">onClick</span><span class="mtk1">=</span><span class="mtk4">{</span><span class="mtk11">toggleDrawer</span><span class="mtk1">(</span><span class="mtk4">true</span><span class="mtk1">)</span><span class="mtk4">}</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">sx</span><span class="mtk1">=</span><span class="mtk4">{</span><span class="mtk1">{ </span><span class="mtk12">color:</span><span class="mtk1"> </span><span class="mtk8">&quot;white&quot;</span><span class="mtk1">, </span><span class="mtk12">display:</span><span class="mtk1"> { </span><span class="mtk12">xs:</span><span class="mtk1"> </span><span class="mtk8">&quot;flex&quot;</span><span class="mtk1">, </span><span class="mtk12">sm:</span><span class="mtk1"> </span><span class="mtk8">&quot;none&quot;</span><span class="mtk1"> } }</span><span class="mtk4">}</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk17">&gt;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk17">&lt;</span><span class="mtk10">MenuIcon</span><span class="mtk1"> </span><span class="mtk17">/&gt;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk17">&lt;/</span><span class="mtk10">Button</span><span class="mtk17">&gt;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk17">&lt;</span><span class="mtk10">Drawer</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">open</span><span class="mtk1">=</span><span class="mtk4">{</span><span class="mtk12">open</span><span class="mtk4">}</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">onClose</span><span class="mtk1">=</span><span class="mtk4">{</span><span class="mtk11">toggleDrawer</span><span class="mtk1">(</span><span class="mtk4">false</span><span class="mtk1">)</span><span class="mtk4">}</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">anchor</span><span class="mtk1">=</span><span class="mtk8">&quot;right&quot;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">sx</span><span class="mtk1">=</span><span class="mtk4">{</span><span class="mtk1">{</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">display:</span><span class="mtk1"> { </span><span class="mtk12">xs:</span><span class="mtk1"> </span><span class="mtk8">&quot;inherit&quot;</span><span class="mtk1">, </span><span class="mtk12">sm:</span><span class="mtk1"> </span><span class="mtk8">&quot;none&quot;</span><span class="mtk1"> },</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> }</span><span class="mtk4">}</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk17">&gt;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk17">&lt;</span><span class="mtk10">NavList</span><span class="mtk1"> </span><span class="mtk17">/&gt;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk17">&lt;/</span><span class="mtk10">Drawer</span><span class="mtk17">&gt;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk17">&lt;</span><span class="mtk10">NavList</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">sx</span><span class="mtk1">=</span><span class="mtk4">{</span><span class="mtk1">{</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">display:</span><span class="mtk1"> { </span><span class="mtk12">xs:</span><span class="mtk1"> </span><span class="mtk8">&quot;none&quot;</span><span class="mtk1">, </span><span class="mtk12">sm:</span><span class="mtk1"> </span><span class="mtk8">&quot;inherit&quot;</span><span class="mtk1"> },</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> }</span><span class="mtk4">}</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk17">/&gt;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk17">&lt;/&gt;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> );</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1">};</span></span></span> <span class="grvsc-line"><span class="grvsc-source"></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk4">const</span><span class="mtk1"> </span><span class="mtk11">Header</span><span class="mtk1"> = () </span><span class="mtk4">=&gt;</span><span class="mtk1"> {</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk15">return</span><span class="mtk1"> (</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk17">&lt;</span><span class="mtk10">AppBar</span><span class="mtk17">&gt;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk17">&lt;</span><span class="mtk10">Container</span><span class="mtk17">&gt;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk17">&lt;</span><span class="mtk10">Toolbar</span><span class="mtk17">&gt;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk17">&lt;</span><span class="mtk10">Stack</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">direction</span><span class="mtk1">=</span><span class="mtk8">&quot;row&quot;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">justifyContent</span><span class="mtk1">=</span><span class="mtk8">&quot;space-between&quot;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">alignItems</span><span class="mtk1">=</span><span class="mtk8">&quot;center&quot;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">width</span><span class="mtk1">=</span><span class="mtk8">&quot;100%&quot;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk17">&gt;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk17">&lt;</span><span class="mtk10">Typography</span><span class="mtk1"> </span><span class="mtk12">variant</span><span class="mtk1">=</span><span class="mtk8">&quot;h6&quot;</span><span class="mtk17">&gt;</span><span class="mtk1">My App</span><span class="mtk17">&lt;/</span><span class="mtk10">Typography</span><span class="mtk17">&gt;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk17">&lt;</span><span class="mtk10">Nav</span><span class="mtk1"> </span><span class="mtk17">/&gt;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk17">&lt;/</span><span class="mtk10">Stack</span><span class="mtk17">&gt;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk17">&lt;/</span><span class="mtk10">Toolbar</span><span class="mtk17">&gt;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk17">&lt;/</span><span class="mtk10">Container</span><span class="mtk17">&gt;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk17">&lt;/</span><span class="mtk10">AppBar</span><span class="mtk17">&gt;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> );</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1">};</span></span></span> <span class="grvsc-line"><span class="grvsc-source"></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk15">export</span><span class="mtk1"> </span><span class="mtk15">default</span><span class="mtk1"> </span><span class="mtk12">Header</span><span class="mtk1">;</span></span></span></code></pre> <div id="ResponsiveNavbar" data-code data-height="400px" data-resize style="display:flex;justify-content: center;"></div> <p>When resizing the window in the above code example, the navbar changes its layout based on the screen size, and the navigation links are displayed in a drawer on mobile devices.</p> <h2 id="mobile-menu-customization" style="position:relative;"><a href="#mobile-menu-customization" aria-label="mobile menu customization permalink" class="anchor before"><svg aria-hidden="true" focusable="false" height="16" version="1.1" viewBox="0 0 16 16" width="16"><path fill-rule="evenodd" d="M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z"></path></svg></a>Mobile Menu Customization</h2> <p>MUI drawers allow us to change the position of the sliding menu using the anchor prop. Here’s an example of making the menu slide from the top:</p> <pre class="grvsc-container default-dark" data-language="jsx" data-index="6"><code class="grvsc-code"><span class="grvsc-line"><span class="grvsc-source"><span class="mtk17">&lt;</span><span class="mtk10">Drawer</span><span class="mtk1"> </span><span class="mtk12">open</span><span class="mtk1">=</span><span class="mtk4">{</span><span class="mtk12">open</span><span class="mtk4">}</span><span class="mtk1"> </span><span class="mtk12">onClose</span><span class="mtk1">=</span><span class="mtk4">{</span><span class="mtk11">toggleDrawer</span><span class="mtk1">(</span><span class="mtk4">false</span><span class="mtk1">)</span><span class="mtk4">}</span><span class="mtk1"> </span><span class="mtk12">anchor</span><span class="mtk1">=</span><span class="mtk8">&quot;top&quot;</span><span class="mtk17">&gt;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk17">&lt;</span><span class="mtk10">NavList</span><span class="mtk1"> </span><span class="mtk17">/&gt;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk17">&lt;/</span><span class="mtk10">Drawer</span><span class="mtk17">&gt;</span></span></span></code></pre> <p>The options for the <code>anchor</code> prop are <code>top</code>, <code>bottom</code>, <code>left</code>, and <code>right</code>. For more details on the <code>Drawer</code> component API, you can refer to the <a href="https://mui.com/material-ui/api/drawer/">MUI Drawer documentation</a>.</p> <h4 id="customizing-the-mobile-menu-to-slide-full-screen" style="position:relative;"><a href="#customizing-the-mobile-menu-to-slide-full-screen" aria-label="customizing the mobile menu to slide full screen permalink" class="anchor before"><svg aria-hidden="true" focusable="false" height="16" version="1.1" viewBox="0 0 16 16" width="16"><path fill-rule="evenodd" d="M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z"></path></svg></a>Customizing the Mobile Menu to Slide Full Screen</h4> <p>To make the menu appear friendlier on mobile devices, we can make it slide in as a full screen and tweak the drawer’s style. We’ll also add a handy “X” icon at the top right corner for users to easily close the menu, especially since clicking outside won’t work when the whole screen is covered.</p> <pre class="grvsc-container grvsc-has-line-highlighting default-dark" data-language="jsx" data-index="7"><code class="grvsc-code"><span class="grvsc-line"><span class="grvsc-source"><span class="mtk15">import</span><span class="mtk1"> </span><span class="mtk12">React</span><span class="mtk1">, { </span><span class="mtk12">useState</span><span class="mtk1"> } </span><span class="mtk15">from</span><span class="mtk1"> </span><span class="mtk8">&quot;react&quot;</span><span class="mtk1">;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk15">import</span><span class="mtk1"> {</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">Stack</span><span class="mtk1">,</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">Link</span><span class="mtk1">,</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">Toolbar</span><span class="mtk1">,</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">Typography</span><span class="mtk1">,</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">Container</span><span class="mtk1">,</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">AppBar</span><span class="mtk1">,</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">Button</span><span class="mtk1">,</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">Drawer</span><span class="mtk1">,</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">Box</span><span class="mtk1">,</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1">} </span><span class="mtk15">from</span><span class="mtk1"> </span><span class="mtk8">&quot;@mui/material&quot;</span><span class="mtk1">;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk15">import</span><span class="mtk1"> </span><span class="mtk12">MenuIcon</span><span class="mtk1"> </span><span class="mtk15">from</span><span class="mtk1"> </span><span class="mtk8">&quot;@mui/icons-material/Menu&quot;</span><span class="mtk1">;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk15">import</span><span class="mtk1"> </span><span class="mtk12">CloseIcon</span><span class="mtk1"> </span><span class="mtk15">from</span><span class="mtk1"> </span><span class="mtk8">&quot;@mui/icons-material/Close&quot;</span><span class="mtk1">;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk4">const</span><span class="mtk1"> </span><span class="mtk12">pages</span><span class="mtk1"> = [</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> { </span><span class="mtk12">name:</span><span class="mtk1"> </span><span class="mtk8">&quot;Products&quot;</span><span class="mtk1">, </span><span class="mtk12">id:</span><span class="mtk1"> </span><span class="mtk8">&quot;products&quot;</span><span class="mtk1"> },</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> { </span><span class="mtk12">name:</span><span class="mtk1"> </span><span class="mtk8">&quot;Services&quot;</span><span class="mtk1">, </span><span class="mtk12">id:</span><span class="mtk1"> </span><span class="mtk8">&quot;services&quot;</span><span class="mtk1"> },</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> { </span><span class="mtk12">name:</span><span class="mtk1"> </span><span class="mtk8">&quot;About&quot;</span><span class="mtk1">, </span><span class="mtk12">id:</span><span class="mtk1"> </span><span class="mtk8">&quot;about&quot;</span><span class="mtk1"> },</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> { </span><span class="mtk12">name:</span><span class="mtk1"> </span><span class="mtk8">&quot;Testimonials&quot;</span><span class="mtk1">, </span><span class="mtk12">id:</span><span class="mtk1"> </span><span class="mtk8">&quot;testimonials&quot;</span><span class="mtk1"> },</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> { </span><span class="mtk12">name:</span><span class="mtk1"> </span><span class="mtk8">&quot;Contact&quot;</span><span class="mtk1">, </span><span class="mtk12">id:</span><span class="mtk1"> </span><span class="mtk8">&quot;contact&quot;</span><span class="mtk1"> },</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1">];</span></span></span> <span class="grvsc-line"><span class="grvsc-source"></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk4">const</span><span class="mtk1"> </span><span class="mtk11">Nav</span><span class="mtk1"> = () </span><span class="mtk4">=&gt;</span><span class="mtk1"> {</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk4">const</span><span class="mtk1"> [</span><span class="mtk12">open</span><span class="mtk1">, </span><span class="mtk12">setOpen</span><span class="mtk1">] = </span><span class="mtk11">useState</span><span class="mtk1">(</span><span class="mtk4">false</span><span class="mtk1">);</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk4">const</span><span class="mtk1"> </span><span class="mtk11">toggleDrawer</span><span class="mtk1"> = </span><span class="mtk12">newOpen</span><span class="mtk1"> </span><span class="mtk4">=&gt;</span><span class="mtk1"> () </span><span class="mtk4">=&gt;</span><span class="mtk1"> {</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk11">setOpen</span><span class="mtk1">(</span><span class="mtk12">newOpen</span><span class="mtk1">);</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> };</span></span></span> <span class="grvsc-line"><span class="grvsc-source"></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk15">return</span><span class="mtk1"> (</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk17">&lt;&gt;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk17">&lt;</span><span class="mtk10">Button</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">variant</span><span class="mtk1">=</span><span class="mtk8">&quot;text&quot;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">onClick</span><span class="mtk1">=</span><span class="mtk4">{</span><span class="mtk11">toggleDrawer</span><span class="mtk1">(</span><span class="mtk4">true</span><span class="mtk1">)</span><span class="mtk4">}</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">sx</span><span class="mtk1">=</span><span class="mtk4">{</span><span class="mtk1">{ </span><span class="mtk12">color:</span><span class="mtk1"> </span><span class="mtk8">&quot;white&quot;</span><span class="mtk1">, </span><span class="mtk12">display:</span><span class="mtk1"> { </span><span class="mtk12">xs:</span><span class="mtk1"> </span><span class="mtk8">&quot;flex&quot;</span><span class="mtk1">, </span><span class="mtk12">sm:</span><span class="mtk1"> </span><span class="mtk8">&quot;none&quot;</span><span class="mtk1"> } }</span><span class="mtk4">}</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk17">&gt;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk17">&lt;</span><span class="mtk10">MenuIcon</span><span class="mtk1"> </span><span class="mtk17">/&gt;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk17">&lt;/</span><span class="mtk10">Button</span><span class="mtk17">&gt;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk17">&lt;</span><span class="mtk10">Drawer</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">open</span><span class="mtk1">=</span><span class="mtk4">{</span><span class="mtk12">open</span><span class="mtk4">}</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">onClose</span><span class="mtk1">=</span><span class="mtk4">{</span><span class="mtk11">toggleDrawer</span><span class="mtk1">(</span><span class="mtk4">false</span><span class="mtk1">)</span><span class="mtk4">}</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">anchor</span><span class="mtk1">=</span><span class="mtk8">&quot;right&quot;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">sx</span><span class="mtk1">=</span><span class="mtk4">{</span><span class="mtk1">{</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">display:</span><span class="mtk1"> { </span><span class="mtk12">xs:</span><span class="mtk1"> </span><span class="mtk8">&quot;inherit&quot;</span><span class="mtk1">, </span><span class="mtk12">sm:</span><span class="mtk1"> </span><span class="mtk8">&quot;none&quot;</span><span class="mtk1"> },</span></span></span> <span class="grvsc-line grvsc-line-highlighted"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk8">&quot;&amp; .MuiDrawer-paper&quot;</span><span class="mtk12">:</span><span class="mtk1"> {</span></span></span> <span class="grvsc-line grvsc-line-highlighted"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">height:</span><span class="mtk1"> </span><span class="mtk8">&quot;100%&quot;</span><span class="mtk1">,</span></span></span> <span class="grvsc-line grvsc-line-highlighted"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">width:</span><span class="mtk1"> </span><span class="mtk8">&quot;100%&quot;</span><span class="mtk1">,</span></span></span> <span class="grvsc-line grvsc-line-highlighted"><span class="grvsc-source"><span class="mtk1"> },</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> }</span><span class="mtk4">}</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk17">&gt;</span></span></span> <span class="grvsc-line grvsc-line-highlighted"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk17">&lt;</span><span class="mtk10">Box</span></span></span> <span class="grvsc-line grvsc-line-highlighted"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">sx</span><span class="mtk1">=</span><span class="mtk4">{</span><span class="mtk1">{</span></span></span> <span class="grvsc-line grvsc-line-highlighted"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">display:</span><span class="mtk1"> </span><span class="mtk8">&quot;flex&quot;</span><span class="mtk1">,</span></span></span> <span class="grvsc-line grvsc-line-highlighted"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">justifyContent:</span><span class="mtk1"> </span><span class="mtk8">&quot;flex-end&quot;</span><span class="mtk1">,</span></span></span> <span class="grvsc-line grvsc-line-highlighted"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">p:</span><span class="mtk1"> </span><span class="mtk7">2</span><span class="mtk1">,</span></span></span> <span class="grvsc-line grvsc-line-highlighted"><span class="grvsc-source"><span class="mtk1"> }</span><span class="mtk4">}</span></span></span> <span class="grvsc-line grvsc-line-highlighted"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk17">&gt;</span></span></span> <span class="grvsc-line grvsc-line-highlighted"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk17">&lt;</span><span class="mtk10">Button</span><span class="mtk1"> </span><span class="mtk12">onClick</span><span class="mtk1">=</span><span class="mtk4">{</span><span class="mtk11">toggleDrawer</span><span class="mtk1">(</span><span class="mtk4">false</span><span class="mtk1">)</span><span class="mtk4">}</span><span class="mtk17">&gt;</span></span></span> <span class="grvsc-line grvsc-line-highlighted"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk17">&lt;</span><span class="mtk10">CloseIcon</span><span class="mtk1"> </span><span class="mtk17">/&gt;</span></span></span> <span class="grvsc-line grvsc-line-highlighted"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk17">&lt;/</span><span class="mtk10">Button</span><span class="mtk17">&gt;</span></span></span> <span class="grvsc-line grvsc-line-highlighted"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk17">&lt;/</span><span class="mtk10">Box</span><span class="mtk17">&gt;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk17">&lt;</span><span class="mtk10">NavList</span><span class="mtk1"> </span><span class="mtk17">/&gt;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk17">&lt;/</span><span class="mtk10">Drawer</span><span class="mtk17">&gt;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk17">&lt;</span><span class="mtk10">NavList</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">sx</span><span class="mtk1">=</span><span class="mtk4">{</span><span class="mtk1">{</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">display:</span><span class="mtk1"> { </span><span class="mtk12">xs:</span><span class="mtk1"> </span><span class="mtk8">&quot;none&quot;</span><span class="mtk1">, </span><span class="mtk12">sm:</span><span class="mtk1"> </span><span class="mtk8">&quot;inherit&quot;</span><span class="mtk1"> },</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> }</span><span class="mtk4">}</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk17">/&gt;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk17">&lt;/&gt;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> );</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1">};</span></span></span> <span class="grvsc-line"><span class="grvsc-source"></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk4">const</span><span class="mtk1"> </span><span class="mtk11">NavList</span><span class="mtk1"> = ({ ...</span><span class="mtk12">props</span><span class="mtk1"> }) </span><span class="mtk4">=&gt;</span><span class="mtk1"> {</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk15">return</span><span class="mtk1"> (</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk17">&lt;</span><span class="mtk10">Stack</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">overflow</span><span class="mtk1">=</span><span class="mtk8">&quot;auto&quot;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">direction</span><span class="mtk1">=</span><span class="mtk4">{</span><span class="mtk1">{ </span><span class="mtk12">xs:</span><span class="mtk1"> </span><span class="mtk8">&quot;column&quot;</span><span class="mtk1">, </span><span class="mtk12">sm:</span><span class="mtk1"> </span><span class="mtk8">&quot;row&quot;</span><span class="mtk1"> }</span><span class="mtk4">}</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">gap</span><span class="mtk1">=</span><span class="mtk4">{</span><span class="mtk7">3</span><span class="mtk4">}</span></span></span> <span class="grvsc-line grvsc-line-highlighted"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">width</span><span class="mtk1">=</span><span class="mtk4">{</span><span class="mtk1">{ </span><span class="mtk12">xs:</span><span class="mtk1"> </span><span class="mtk8">&quot;100%&quot;</span><span class="mtk1">, </span><span class="mtk12">sm:</span><span class="mtk1"> </span><span class="mtk8">&quot;initial&quot;</span><span class="mtk1"> }</span><span class="mtk4">}</span></span></span> <span class="grvsc-line grvsc-line-highlighted"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">textAlign</span><span class="mtk1">=</span><span class="mtk4">{</span><span class="mtk1">{ </span><span class="mtk12">xs:</span><span class="mtk1"> </span><span class="mtk8">&quot;center&quot;</span><span class="mtk1">, </span><span class="mtk12">sm:</span><span class="mtk1"> </span><span class="mtk8">&quot;initial&quot;</span><span class="mtk1"> }</span><span class="mtk4">}</span></span></span> <span class="grvsc-line grvsc-line-highlighted"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">fontSize</span><span class="mtk1">=</span><span class="mtk4">{</span><span class="mtk1">{ </span><span class="mtk12">xs:</span><span class="mtk1"> </span><span class="mtk8">&quot;22px&quot;</span><span class="mtk1">, </span><span class="mtk12">sm:</span><span class="mtk1"> </span><span class="mtk8">&quot;initial&quot;</span><span class="mtk1"> }</span><span class="mtk4">}</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk4">{</span><span class="mtk1">...</span><span class="mtk12">props</span><span class="mtk4">}</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk17">&gt;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk4">{</span><span class="mtk12">pages</span><span class="mtk1">.</span><span class="mtk11">map</span><span class="mtk1">(</span><span class="mtk12">page</span><span class="mtk1"> </span><span class="mtk4">=&gt;</span><span class="mtk1"> (</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk17">&lt;</span><span class="mtk10">Link</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">key</span><span class="mtk1">=</span><span class="mtk4">{</span><span class="mtk12">page</span><span class="mtk1">.</span><span class="mtk12">id</span><span class="mtk4">}</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">sx</span><span class="mtk1">=</span><span class="mtk4">{</span><span class="mtk1">{</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">color:</span><span class="mtk1"> { </span><span class="mtk12">xs:</span><span class="mtk1"> </span><span class="mtk8">&quot;primary&quot;</span><span class="mtk1">, </span><span class="mtk12">sm:</span><span class="mtk1"> </span><span class="mtk8">&quot;white&quot;</span><span class="mtk1"> },</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">textDecoration:</span><span class="mtk1"> </span><span class="mtk8">&quot;none&quot;</span><span class="mtk1">,</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> }</span><span class="mtk4">}</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk17">&gt;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk4">{</span><span class="mtk12">page</span><span class="mtk1">.</span><span class="mtk12">name</span><span class="mtk4">}</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk17">&lt;/</span><span class="mtk10">Link</span><span class="mtk17">&gt;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> ))</span><span class="mtk4">}</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk17">&lt;/</span><span class="mtk10">Stack</span><span class="mtk17">&gt;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> );</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1">};</span></span></span> <span class="grvsc-line"><span class="grvsc-source"></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk4">const</span><span class="mtk1"> </span><span class="mtk11">Header</span><span class="mtk1"> = () </span><span class="mtk4">=&gt;</span><span class="mtk1"> {</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk15">return</span><span class="mtk1"> (</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk17">&lt;</span><span class="mtk10">AppBar</span><span class="mtk17">&gt;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk17">&lt;</span><span class="mtk10">Container</span><span class="mtk17">&gt;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk17">&lt;</span><span class="mtk10">Toolbar</span><span class="mtk17">&gt;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk17">&lt;</span><span class="mtk10">Stack</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">direction</span><span class="mtk1">=</span><span class="mtk8">&quot;row&quot;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">justifyContent</span><span class="mtk1">=</span><span class="mtk8">&quot;space-between&quot;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">alignItems</span><span class="mtk1">=</span><span class="mtk8">&quot;center&quot;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">width</span><span class="mtk1">=</span><span class="mtk8">&quot;100%&quot;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk17">&gt;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk17">&lt;</span><span class="mtk10">Typography</span><span class="mtk1"> </span><span class="mtk12">variant</span><span class="mtk1">=</span><span class="mtk8">&quot;h6&quot;</span><span class="mtk17">&gt;</span><span class="mtk1">My App</span><span class="mtk17">&lt;/</span><span class="mtk10">Typography</span><span class="mtk17">&gt;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk17">&lt;</span><span class="mtk10">Nav</span><span class="mtk1"> </span><span class="mtk17">/&gt;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk17">&lt;/</span><span class="mtk10">Stack</span><span class="mtk17">&gt;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk17">&lt;/</span><span class="mtk10">Toolbar</span><span class="mtk17">&gt;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk17">&lt;/</span><span class="mtk10">Container</span><span class="mtk17">&gt;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk17">&lt;/</span><span class="mtk10">AppBar</span><span class="mtk17">&gt;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> );</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1">};</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk15">export</span><span class="mtk1"> </span><span class="mtk15">default</span><span class="mtk1"> </span><span class="mtk12">Header</span><span class="mtk1">;</span></span></span></code></pre> <div id="CustomizedMobileMenu" data-code data-height="400px" data-width="200px" data-resize style="display:flex;justify-content: center;"></div> <p>In the code above, we added a <code>CloseIcon</code> to the drawer and customized its styling to cover the entire screen using the <code>.MuiDrawer-paper</code> class. The <code>NavList</code> component was also updated to adjust the text alignment, font size, and width based on the screen size.</p> <h2 id="summary" style="position:relative;"><a href="#summary" aria-label="summary permalink" class="anchor before"><svg aria-hidden="true" focusable="false" height="16" version="1.1" viewBox="0 0 16 16" width="16"><path fill-rule="evenodd" d="M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z"></path></svg></a>Summary</h2> <p>In this tutorial, we created a responsive navbar using React and Material UI (MUI). Initially, we designed a basic navbar with a logo and navigation links. Then, we made the navbar responsive and added a drawer for better mobile experience. The result is a dynamic and user-friendly navbar for desktop and mobile devices.</p> <style class="grvsc-styles"> .grvsc-container { overflow: auto; position: relative; -webkit-overflow-scrolling: touch; padding-top: 1rem; padding-top: var(--grvsc-padding-top, var(--grvsc-padding-v, 1rem)); padding-bottom: 1rem; padding-bottom: var(--grvsc-padding-bottom, var(--grvsc-padding-v, 1rem)); border-radius: 8px; border-radius: var(--grvsc-border-radius, 8px); font-feature-settings: normal; line-height: 1.4; } .grvsc-code { display: table; } .grvsc-line { display: table-row; box-sizing: border-box; width: 100%; position: relative; } .grvsc-line > * { position: relative; } .grvsc-gutter-pad { display: table-cell; padding-left: 0.75rem; padding-left: calc(var(--grvsc-padding-left, var(--grvsc-padding-h, 1.5rem)) / 2); } .grvsc-gutter { display: table-cell; -webkit-user-select: none; -moz-user-select: none; user-select: none; } .grvsc-gutter::before { content: attr(data-content); } .grvsc-source { display: table-cell; padding-left: 1.5rem; padding-left: var(--grvsc-padding-left, var(--grvsc-padding-h, 1.5rem)); padding-right: 1.5rem; padding-right: var(--grvsc-padding-right, var(--grvsc-padding-h, 1.5rem)); } .grvsc-source:empty::after { content: ' '; -webkit-user-select: none; -moz-user-select: none; user-select: none; } .grvsc-gutter + .grvsc-source { padding-left: 0.75rem; padding-left: calc(var(--grvsc-padding-left, var(--grvsc-padding-h, 1.5rem)) / 2); } /* Line transformer styles */ .grvsc-has-line-highlighting > .grvsc-code > .grvsc-line::before { content: ' '; position: absolute; width: 100%; } .grvsc-line-diff-add::before { background-color: var(--grvsc-line-diff-add-background-color, rgba(0, 255, 60, 0.2)); } .grvsc-line-diff-del::before { background-color: var(--grvsc-line-diff-del-background-color, rgba(255, 0, 20, 0.2)); } .grvsc-line-number { padding: 0 2px; text-align: right; opacity: 0.7; } .default-dark { background-color: #1E1E1E; color: #D4D4D4; } .default-dark .mtk1 { color: #D4D4D4; } .default-dark .mtk15 { color: #C586C0; } .default-dark .mtk12 { color: #9CDCFE; } .default-dark .mtk8 { color: #CE9178; } .default-dark .mtk4 { color: #569CD6; } .default-dark .mtk11 { color: #DCDCAA; } .default-dark .mtk17 { color: #808080; } .default-dark .mtk10 { color: #4EC9B0; } .default-dark .mtk7 { color: #B5CEA8; } .default-dark .grvsc-line-highlighted::before { background-color: var(--grvsc-line-highlighted-background-color, rgba(255, 255, 255, 0.1)); box-shadow: inset var(--grvsc-line-highlighted-border-width, 4px) 0 0 0 var(--grvsc-line-highlighted-border-color, rgba(255, 255, 255, 0.5)); } </style><![CDATA[React Vertical Tabs: Complete Customization with MUI]]>https://muhimasri.commui-vertical-tabshttps://muhimasri.commui-vertical-tabs<p>Tabs are a commonly used layout approach to display different pieces of information on the same screen. Users can quickly switch between different content sections without leaving the current page.</p> <p>Vertical tabs offer a powerful design approach for creating side menus. They are practical in layouts where you want to keep the primary navigation on the side, efficiently using horizontal space.</p> <p>In this tutorial, we will learn how to create vertical tabs in React and Material UI. MUI provides a robust set of components and styling options that make the implementation of vertical tabs straightforward and highly customizable.</p> <p>Here’s a preview of what the final implementation will look like:</p> <video width="720" height="400" autoplay loop muted playsinline preload="none"> <source src="/37f721338176afc0fbff2b8eb804dcfe/mui-vertical-tabs.mp4" type="video/mp4"> </video> <h2 id="creating-basic-vertical-tabs" style="position:relative;"><a href="#creating-basic-vertical-tabs" aria-label="creating basic vertical tabs permalink" class="anchor before"><svg aria-hidden="true" focusable="false" height="16" version="1.1" viewBox="0 0 16 16" width="16"><path fill-rule="evenodd" d="M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z"></path></svg></a>Creating Basic Vertical Tabs</h2> <p>Let’s start with importing and using the necessary components from MUI:</p> <h3 id="setting-up-mui-tabs" style="position:relative;"><a href="#setting-up-mui-tabs" aria-label="setting up mui tabs permalink" class="anchor before"><svg aria-hidden="true" focusable="false" height="16" version="1.1" viewBox="0 0 16 16" width="16"><path fill-rule="evenodd" d="M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z"></path></svg></a>Setting Up MUI Tabs</h3> <pre class="grvsc-container default-dark" data-language="jsx" data-index="0"><code class="grvsc-code"><span class="grvsc-line"><span class="grvsc-source"><span class="mtk15">import</span><span class="mtk1"> </span><span class="mtk12">React</span><span class="mtk1"> </span><span class="mtk15">from</span><span class="mtk1"> </span><span class="mtk8">&quot;react&quot;</span><span class="mtk1">;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk15">import</span><span class="mtk1"> { </span><span class="mtk12">Box</span><span class="mtk1">, </span><span class="mtk12">Tabs</span><span class="mtk1">, </span><span class="mtk12">Tab</span><span class="mtk1"> } </span><span class="mtk15">from</span><span class="mtk1"> </span><span class="mtk8">&quot;@mui/material&quot;</span><span class="mtk1">;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk15">export</span><span class="mtk1"> </span><span class="mtk15">default</span><span class="mtk1"> </span><span class="mtk4">function</span><span class="mtk1"> </span><span class="mtk11">VerticalTabs</span><span class="mtk1">() {</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk15">return</span><span class="mtk1"> (</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk17">&lt;</span><span class="mtk10">Box</span><span class="mtk17">&gt;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk17">&lt;</span><span class="mtk10">Tabs</span><span class="mtk17">&gt;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk17">&lt;</span><span class="mtk10">Tab</span><span class="mtk1"> </span><span class="mtk12">label</span><span class="mtk1">=</span><span class="mtk8">&quot;Item One&quot;</span><span class="mtk1"> </span><span class="mtk17">/&gt;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk17">&lt;</span><span class="mtk10">Tab</span><span class="mtk1"> </span><span class="mtk12">label</span><span class="mtk1">=</span><span class="mtk8">&quot;Item Two&quot;</span><span class="mtk1"> </span><span class="mtk17">/&gt;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk17">&lt;</span><span class="mtk10">Tab</span><span class="mtk1"> </span><span class="mtk12">label</span><span class="mtk1">=</span><span class="mtk8">&quot;Item Three&quot;</span><span class="mtk1"> </span><span class="mtk17">/&gt;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk17">&lt;/</span><span class="mtk10">Tabs</span><span class="mtk17">&gt;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk17">&lt;</span><span class="mtk10">Box</span><span class="mtk17">&gt;</span><span class="mtk1">Item One</span><span class="mtk17">&lt;/</span><span class="mtk10">Box</span><span class="mtk17">&gt;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk17">&lt;</span><span class="mtk10">Box</span><span class="mtk17">&gt;</span><span class="mtk1">Item Two</span><span class="mtk17">&lt;/</span><span class="mtk10">Box</span><span class="mtk17">&gt;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk17">&lt;</span><span class="mtk10">Box</span><span class="mtk17">&gt;</span><span class="mtk1">Item Three</span><span class="mtk17">&lt;/</span><span class="mtk10">Box</span><span class="mtk17">&gt;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk17">&lt;/</span><span class="mtk10">Box</span><span class="mtk17">&gt;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> );</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1">}</span></span></span></code></pre> <p>The <code>Tabs</code> component wraps each <code>Tab</code> component, and each <code>Tab</code> content is placed inside a <code>Box</code> component.</p> <p>To make the tabs functional, we need to handle the change event and update the selected tab index:</p> <pre class="grvsc-container grvsc-has-line-highlighting default-dark" data-language="jsx" data-index="1"><code class="grvsc-code"><span class="grvsc-line"><span class="grvsc-source"><span class="mtk15">import</span><span class="mtk1"> </span><span class="mtk12">React</span><span class="mtk1"> </span><span class="mtk15">from</span><span class="mtk1"> </span><span class="mtk8">&quot;react&quot;</span><span class="mtk1">;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk15">import</span><span class="mtk1"> { </span><span class="mtk12">Box</span><span class="mtk1">, </span><span class="mtk12">Tabs</span><span class="mtk1">, </span><span class="mtk12">Tab</span><span class="mtk1"> } </span><span class="mtk15">from</span><span class="mtk1"> </span><span class="mtk8">&quot;@mui/material&quot;</span><span class="mtk1">;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk15">export</span><span class="mtk1"> </span><span class="mtk15">default</span><span class="mtk1"> </span><span class="mtk4">function</span><span class="mtk1"> </span><span class="mtk11">VerticalTabs</span><span class="mtk1">() {</span></span></span> <span class="grvsc-line grvsc-line-highlighted"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk4">const</span><span class="mtk1"> [</span><span class="mtk12">value</span><span class="mtk1">, </span><span class="mtk12">setValue</span><span class="mtk1">] = </span><span class="mtk12">React</span><span class="mtk1">.</span><span class="mtk11">useState</span><span class="mtk1">(</span><span class="mtk7">0</span><span class="mtk1">);</span></span></span> <span class="grvsc-line"><span class="grvsc-source"></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk15">return</span><span class="mtk1"> (</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk17">&lt;</span><span class="mtk10">Box</span><span class="mtk17">&gt;</span></span></span> <span class="grvsc-line grvsc-line-highlighted"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk17">&lt;</span><span class="mtk10">Tabs</span><span class="mtk1"> </span><span class="mtk12">value</span><span class="mtk1">=</span><span class="mtk4">{</span><span class="mtk12">value</span><span class="mtk4">}</span><span class="mtk1"> </span><span class="mtk12">onChange</span><span class="mtk1">=</span><span class="mtk4">{</span><span class="mtk1">(</span><span class="mtk12">_event</span><span class="mtk1">, </span><span class="mtk12">newValue</span><span class="mtk1">) </span><span class="mtk4">=&gt;</span><span class="mtk1"> </span><span class="mtk11">setValue</span><span class="mtk1">(</span><span class="mtk12">newValue</span><span class="mtk1">)</span><span class="mtk4">}</span><span class="mtk17">&gt;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk17">&lt;</span><span class="mtk10">Tab</span><span class="mtk1"> </span><span class="mtk12">label</span><span class="mtk1">=</span><span class="mtk8">&quot;Item One&quot;</span><span class="mtk1"> </span><span class="mtk17">/&gt;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk17">&lt;</span><span class="mtk10">Tab</span><span class="mtk1"> </span><span class="mtk12">label</span><span class="mtk1">=</span><span class="mtk8">&quot;Item Two&quot;</span><span class="mtk1"> </span><span class="mtk17">/&gt;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk17">&lt;</span><span class="mtk10">Tab</span><span class="mtk1"> </span><span class="mtk12">label</span><span class="mtk1">=</span><span class="mtk8">&quot;Item Three&quot;</span><span class="mtk1"> </span><span class="mtk17">/&gt;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk17">&lt;/</span><span class="mtk10">Tabs</span><span class="mtk17">&gt;</span></span></span> <span class="grvsc-line grvsc-line-highlighted"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk17">&lt;</span><span class="mtk10">TabPanel</span><span class="mtk1"> </span><span class="mtk12">value</span><span class="mtk1">=</span><span class="mtk4">{</span><span class="mtk12">value</span><span class="mtk4">}</span><span class="mtk1"> </span><span class="mtk12">index</span><span class="mtk1">=</span><span class="mtk4">{</span><span class="mtk7">0</span><span class="mtk4">}</span><span class="mtk17">&gt;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> Item One</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk17">&lt;/</span><span class="mtk10">TabPanel</span><span class="mtk17">&gt;</span></span></span> <span class="grvsc-line grvsc-line-highlighted"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk17">&lt;</span><span class="mtk10">TabPanel</span><span class="mtk1"> </span><span class="mtk12">value</span><span class="mtk1">=</span><span class="mtk4">{</span><span class="mtk12">value</span><span class="mtk4">}</span><span class="mtk1"> </span><span class="mtk12">index</span><span class="mtk1">=</span><span class="mtk4">{</span><span class="mtk7">1</span><span class="mtk4">}</span><span class="mtk17">&gt;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> Item Two</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk17">&lt;/</span><span class="mtk10">TabPanel</span><span class="mtk17">&gt;</span></span></span> <span class="grvsc-line grvsc-line-highlighted"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk17">&lt;</span><span class="mtk10">TabPanel</span><span class="mtk1"> </span><span class="mtk12">value</span><span class="mtk1">=</span><span class="mtk4">{</span><span class="mtk12">value</span><span class="mtk4">}</span><span class="mtk1"> </span><span class="mtk12">index</span><span class="mtk1">=</span><span class="mtk4">{</span><span class="mtk7">2</span><span class="mtk4">}</span><span class="mtk17">&gt;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> Item Three</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk17">&lt;/</span><span class="mtk10">TabPanel</span><span class="mtk17">&gt;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk17">&lt;/</span><span class="mtk10">Box</span><span class="mtk17">&gt;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> );</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1">}</span></span></span> <span class="grvsc-line"><span class="grvsc-source"></span></span> <span class="grvsc-line grvsc-line-highlighted"><span class="grvsc-source"><span class="mtk4">const</span><span class="mtk1"> </span><span class="mtk11">TabPanel</span><span class="mtk1"> = ({ </span><span class="mtk12">children</span><span class="mtk1">, </span><span class="mtk12">value</span><span class="mtk1">, </span><span class="mtk12">index</span><span class="mtk1"> }) </span><span class="mtk4">=&gt;</span><span class="mtk1"> {</span></span></span> <span class="grvsc-line grvsc-line-highlighted"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk15">return</span><span class="mtk1"> </span><span class="mtk12">value</span><span class="mtk1"> === </span><span class="mtk12">index</span><span class="mtk1"> &amp;&amp; </span><span class="mtk17">&lt;</span><span class="mtk10">Box</span><span class="mtk17">&gt;</span><span class="mtk4">{</span><span class="mtk12">children</span><span class="mtk4">}</span><span class="mtk17">&lt;/</span><span class="mtk10">Box</span><span class="mtk17">&gt;</span><span class="mtk1">;</span></span></span> <span class="grvsc-line grvsc-line-highlighted"><span class="grvsc-source"><span class="mtk1">};</span></span></span></code></pre> <div id="BasicVerticalTabs" data-code data-height="150px"></div> <p>In the above code, we have added the <code>value</code> state to keep track of the selected tab index. The <code>onChange</code> event handler updates this state when a tab is clicked. We also created a <code>TabPanel</code> component to render the content conditionally based on the selected index.</p> <h3 id="enable-vertical-tabs" style="position:relative;"><a href="#enable-vertical-tabs" aria-label="enable vertical tabs permalink" class="anchor before"><svg aria-hidden="true" focusable="false" height="16" version="1.1" viewBox="0 0 16 16" width="16"><path fill-rule="evenodd" d="M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z"></path></svg></a>Enable Vertical Tabs</h3> <p>To make the tabs vertical, we can pass the <code>orientation</code> prop to the <code>Tabs</code> component:</p> <pre class="grvsc-container grvsc-has-line-highlighting default-dark" data-language="jsx" data-index="2"><code class="grvsc-code"><span class="grvsc-line"><span class="grvsc-source"><span class="mtk1">...</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk17">&lt;</span><span class="mtk10">Tabs</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">value</span><span class="mtk1">=</span><span class="mtk4">{</span><span class="mtk12">value</span><span class="mtk4">}</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">onChange</span><span class="mtk1">=</span><span class="mtk4">{</span><span class="mtk1">(</span><span class="mtk12">_event</span><span class="mtk1">, </span><span class="mtk12">newValue</span><span class="mtk1">) </span><span class="mtk4">=&gt;</span><span class="mtk1"> </span><span class="mtk11">setValue</span><span class="mtk1">(</span><span class="mtk12">newValue</span><span class="mtk1">)</span><span class="mtk4">}</span></span></span> <span class="grvsc-line grvsc-line-highlighted"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">orientation</span><span class="mtk1">=</span><span class="mtk8">&quot;vertical&quot;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk17">&gt;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk17">&lt;</span><span class="mtk10">Tab</span><span class="mtk1"> </span><span class="mtk12">label</span><span class="mtk1">=</span><span class="mtk8">&quot;Item One&quot;</span><span class="mtk1"> </span><span class="mtk17">/&gt;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk17">&lt;</span><span class="mtk10">Tab</span><span class="mtk1"> </span><span class="mtk12">label</span><span class="mtk1">=</span><span class="mtk8">&quot;Item Two&quot;</span><span class="mtk1"> </span><span class="mtk17">/&gt;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk17">&lt;</span><span class="mtk10">Tab</span><span class="mtk1"> </span><span class="mtk12">label</span><span class="mtk1">=</span><span class="mtk8">&quot;Item Three&quot;</span><span class="mtk1"> </span><span class="mtk17">/&gt;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk17">&lt;/</span><span class="mtk10">Tabs</span><span class="mtk17">&gt;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> ...</span></span></span></code></pre> <p>The current code will only change the orientation of the tabs, but the content will still be displayed below the tabs. To align the content properly, we can use the <code>Stack</code> component from MUI:</p> <pre class="grvsc-container grvsc-has-line-highlighting default-dark" data-language="jsx" data-index="3"><code class="grvsc-code"><span class="grvsc-line"><span class="grvsc-source"><span class="mtk15">import</span><span class="mtk1"> </span><span class="mtk12">React</span><span class="mtk1"> </span><span class="mtk15">from</span><span class="mtk1"> </span><span class="mtk8">&quot;react&quot;</span><span class="mtk1">;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk15">import</span><span class="mtk1"> { </span><span class="mtk12">Box</span><span class="mtk1">, </span><span class="mtk12">Stack</span><span class="mtk1">, </span><span class="mtk12">Tabs</span><span class="mtk1">, </span><span class="mtk12">Tab</span><span class="mtk1"> } </span><span class="mtk15">from</span><span class="mtk1"> </span><span class="mtk8">&quot;@mui/material&quot;</span><span class="mtk1">;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk15">export</span><span class="mtk1"> </span><span class="mtk15">default</span><span class="mtk1"> </span><span class="mtk4">function</span><span class="mtk1"> </span><span class="mtk11">VerticalTabs</span><span class="mtk1">() {</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk4">const</span><span class="mtk1"> [</span><span class="mtk12">value</span><span class="mtk1">, </span><span class="mtk12">setValue</span><span class="mtk1">] = </span><span class="mtk12">React</span><span class="mtk1">.</span><span class="mtk11">useState</span><span class="mtk1">(</span><span class="mtk7">0</span><span class="mtk1">);</span></span></span> <span class="grvsc-line"><span class="grvsc-source"></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk15">return</span><span class="mtk1"> (</span></span></span> <span class="grvsc-line grvsc-line-highlighted"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk17">&lt;</span><span class="mtk10">Stack</span><span class="mtk1"> </span><span class="mtk12">direction</span><span class="mtk1">=</span><span class="mtk8">&quot;row&quot;</span><span class="mtk1"> </span><span class="mtk12">gap</span><span class="mtk1">=</span><span class="mtk4">{</span><span class="mtk7">2</span><span class="mtk4">}</span><span class="mtk17">&gt;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk17">&lt;</span><span class="mtk10">Tabs</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">orientation</span><span class="mtk1">=</span><span class="mtk8">&quot;vertical&quot;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">value</span><span class="mtk1">=</span><span class="mtk4">{</span><span class="mtk12">value</span><span class="mtk4">}</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">onChange</span><span class="mtk1">=</span><span class="mtk4">{</span><span class="mtk1">(</span><span class="mtk12">_event</span><span class="mtk1">, </span><span class="mtk12">newValue</span><span class="mtk1">) </span><span class="mtk4">=&gt;</span><span class="mtk1"> </span><span class="mtk11">setValue</span><span class="mtk1">(</span><span class="mtk12">newValue</span><span class="mtk1">)</span><span class="mtk4">}</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk17">&gt;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk17">&lt;</span><span class="mtk10">Tab</span><span class="mtk1"> </span><span class="mtk12">label</span><span class="mtk1">=</span><span class="mtk8">&quot;Item One&quot;</span><span class="mtk1"> </span><span class="mtk17">/&gt;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk17">&lt;</span><span class="mtk10">Tab</span><span class="mtk1"> </span><span class="mtk12">label</span><span class="mtk1">=</span><span class="mtk8">&quot;Item Two&quot;</span><span class="mtk1"> </span><span class="mtk17">/&gt;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk17">&lt;</span><span class="mtk10">Tab</span><span class="mtk1"> </span><span class="mtk12">label</span><span class="mtk1">=</span><span class="mtk8">&quot;Item Three&quot;</span><span class="mtk1"> </span><span class="mtk17">/&gt;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk17">&lt;/</span><span class="mtk10">Tabs</span><span class="mtk17">&gt;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk17">&lt;</span><span class="mtk10">TabPanel</span><span class="mtk1"> </span><span class="mtk12">value</span><span class="mtk1">=</span><span class="mtk4">{</span><span class="mtk12">value</span><span class="mtk4">}</span><span class="mtk1"> </span><span class="mtk12">index</span><span class="mtk1">=</span><span class="mtk4">{</span><span class="mtk7">0</span><span class="mtk4">}</span><span class="mtk17">&gt;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> Item One</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk17">&lt;/</span><span class="mtk10">TabPanel</span><span class="mtk17">&gt;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk17">&lt;</span><span class="mtk10">TabPanel</span><span class="mtk1"> </span><span class="mtk12">value</span><span class="mtk1">=</span><span class="mtk4">{</span><span class="mtk12">value</span><span class="mtk4">}</span><span class="mtk1"> </span><span class="mtk12">index</span><span class="mtk1">=</span><span class="mtk4">{</span><span class="mtk7">1</span><span class="mtk4">}</span><span class="mtk17">&gt;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> Item Two</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk17">&lt;/</span><span class="mtk10">TabPanel</span><span class="mtk17">&gt;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk17">&lt;</span><span class="mtk10">TabPanel</span><span class="mtk1"> </span><span class="mtk12">value</span><span class="mtk1">=</span><span class="mtk4">{</span><span class="mtk12">value</span><span class="mtk4">}</span><span class="mtk1"> </span><span class="mtk12">index</span><span class="mtk1">=</span><span class="mtk4">{</span><span class="mtk7">2</span><span class="mtk4">}</span><span class="mtk17">&gt;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> Item Three</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk17">&lt;/</span><span class="mtk10">TabPanel</span><span class="mtk17">&gt;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk17">&lt;/</span><span class="mtk10">Stack</span><span class="mtk17">&gt;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> );</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1">}</span></span></span> <span class="grvsc-line"><span class="grvsc-source"></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk4">const</span><span class="mtk1"> </span><span class="mtk11">TabPanel</span><span class="mtk1"> = ({ </span><span class="mtk12">children</span><span class="mtk1">, </span><span class="mtk12">value</span><span class="mtk1">, </span><span class="mtk12">index</span><span class="mtk1"> }) </span><span class="mtk4">=&gt;</span><span class="mtk1"> {</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk15">return</span><span class="mtk1"> </span><span class="mtk12">value</span><span class="mtk1"> === </span><span class="mtk12">index</span><span class="mtk1"> &amp;&amp; </span><span class="mtk17">&lt;</span><span class="mtk10">Box</span><span class="mtk17">&gt;</span><span class="mtk4">{</span><span class="mtk12">children</span><span class="mtk4">}</span><span class="mtk17">&lt;/</span><span class="mtk10">Box</span><span class="mtk17">&gt;</span><span class="mtk1">;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1">};</span></span></span></code></pre> <p>Finally, to simplify creating new tabs, we can define a JSON object containing all the tabs and their contents, then loop through this object to populate the elements:</p> <pre class="grvsc-container grvsc-has-line-highlighting default-dark" data-language="jsx" data-index="4"><code class="grvsc-code"><span class="grvsc-line"><span class="grvsc-source"><span class="mtk15">import</span><span class="mtk1"> </span><span class="mtk12">React</span><span class="mtk1"> </span><span class="mtk15">from</span><span class="mtk1"> </span><span class="mtk8">&quot;react&quot;</span><span class="mtk1">;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk15">import</span><span class="mtk1"> { </span><span class="mtk12">Box</span><span class="mtk1">, </span><span class="mtk12">Stack</span><span class="mtk1">, </span><span class="mtk12">Tabs</span><span class="mtk1">, </span><span class="mtk12">Tab</span><span class="mtk1"> } </span><span class="mtk15">from</span><span class="mtk1"> </span><span class="mtk8">&quot;@mui/material&quot;</span><span class="mtk1">;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"></span></span> <span class="grvsc-line grvsc-line-highlighted"><span class="grvsc-source"><span class="mtk4">const</span><span class="mtk1"> </span><span class="mtk12">tabData</span><span class="mtk1"> = [</span></span></span> <span class="grvsc-line grvsc-line-highlighted"><span class="grvsc-source"><span class="mtk1"> { </span><span class="mtk12">label:</span><span class="mtk1"> </span><span class="mtk8">&quot;Item One&quot;</span><span class="mtk1">, </span><span class="mtk12">content:</span><span class="mtk1"> </span><span class="mtk8">&quot;Content for Item One&quot;</span><span class="mtk1"> },</span></span></span> <span class="grvsc-line grvsc-line-highlighted"><span class="grvsc-source"><span class="mtk1"> { </span><span class="mtk12">label:</span><span class="mtk1"> </span><span class="mtk8">&quot;Item Two&quot;</span><span class="mtk1">, </span><span class="mtk12">content:</span><span class="mtk1"> </span><span class="mtk8">&quot;Content for Item Two&quot;</span><span class="mtk1"> },</span></span></span> <span class="grvsc-line grvsc-line-highlighted"><span class="grvsc-source"><span class="mtk1"> { </span><span class="mtk12">label:</span><span class="mtk1"> </span><span class="mtk8">&quot;Item Three&quot;</span><span class="mtk1">, </span><span class="mtk12">content:</span><span class="mtk1"> </span><span class="mtk8">&quot;Content for Item Three&quot;</span><span class="mtk1"> },</span></span></span> <span class="grvsc-line grvsc-line-highlighted"><span class="grvsc-source"><span class="mtk1">];</span></span></span> <span class="grvsc-line"><span class="grvsc-source"></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk15">export</span><span class="mtk1"> </span><span class="mtk15">default</span><span class="mtk1"> </span><span class="mtk4">function</span><span class="mtk1"> </span><span class="mtk11">VerticalTabs</span><span class="mtk1">() {</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk4">const</span><span class="mtk1"> [</span><span class="mtk12">value</span><span class="mtk1">, </span><span class="mtk12">setValue</span><span class="mtk1">] = </span><span class="mtk12">React</span><span class="mtk1">.</span><span class="mtk11">useState</span><span class="mtk1">(</span><span class="mtk7">0</span><span class="mtk1">);</span></span></span> <span class="grvsc-line"><span class="grvsc-source"></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk15">return</span><span class="mtk1"> (</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk17">&lt;</span><span class="mtk10">Stack</span><span class="mtk1"> </span><span class="mtk12">direction</span><span class="mtk1">=</span><span class="mtk8">&quot;row&quot;</span><span class="mtk1"> </span><span class="mtk12">gap</span><span class="mtk1">=</span><span class="mtk4">{</span><span class="mtk7">2</span><span class="mtk4">}</span><span class="mtk17">&gt;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk17">&lt;</span><span class="mtk10">Tabs</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">orientation</span><span class="mtk1">=</span><span class="mtk8">&quot;vertical&quot;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">value</span><span class="mtk1">=</span><span class="mtk4">{</span><span class="mtk12">value</span><span class="mtk4">}</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">onChange</span><span class="mtk1">=</span><span class="mtk4">{</span><span class="mtk1">(</span><span class="mtk12">_event</span><span class="mtk1">, </span><span class="mtk12">newValue</span><span class="mtk1">) </span><span class="mtk4">=&gt;</span><span class="mtk1"> </span><span class="mtk11">setValue</span><span class="mtk1">(</span><span class="mtk12">newValue</span><span class="mtk1">)</span><span class="mtk4">}</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk17">&gt;</span></span></span> <span class="grvsc-line grvsc-line-highlighted"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk4">{</span><span class="mtk12">tabData</span><span class="mtk1">.</span><span class="mtk11">map</span><span class="mtk1">((</span><span class="mtk12">tab</span><span class="mtk1">, </span><span class="mtk12">index</span><span class="mtk1">) </span><span class="mtk4">=&gt;</span><span class="mtk1"> (</span></span></span> <span class="grvsc-line grvsc-line-highlighted"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk17">&lt;</span><span class="mtk10">Tab</span><span class="mtk1"> </span><span class="mtk12">key</span><span class="mtk1">=</span><span class="mtk4">{</span><span class="mtk12">index</span><span class="mtk4">}</span><span class="mtk1"> </span><span class="mtk12">label</span><span class="mtk1">=</span><span class="mtk4">{</span><span class="mtk12">tab</span><span class="mtk1">.</span><span class="mtk12">label</span><span class="mtk4">}</span><span class="mtk1"> </span><span class="mtk17">/&gt;</span></span></span> <span class="grvsc-line grvsc-line-highlighted"><span class="grvsc-source"><span class="mtk1"> ))</span><span class="mtk4">}</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk17">&lt;/</span><span class="mtk10">Tabs</span><span class="mtk17">&gt;</span></span></span> <span class="grvsc-line grvsc-line-highlighted"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk4">{</span><span class="mtk12">tabData</span><span class="mtk1">.</span><span class="mtk11">map</span><span class="mtk1">((</span><span class="mtk12">tab</span><span class="mtk1">, </span><span class="mtk12">index</span><span class="mtk1">) </span><span class="mtk4">=&gt;</span><span class="mtk1"> (</span></span></span> <span class="grvsc-line grvsc-line-highlighted"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk17">&lt;</span><span class="mtk10">TabPanel</span><span class="mtk1"> </span><span class="mtk12">key</span><span class="mtk1">=</span><span class="mtk4">{</span><span class="mtk12">index</span><span class="mtk4">}</span><span class="mtk1"> </span><span class="mtk12">value</span><span class="mtk1">=</span><span class="mtk4">{</span><span class="mtk12">value</span><span class="mtk4">}</span><span class="mtk1"> </span><span class="mtk12">index</span><span class="mtk1">=</span><span class="mtk4">{</span><span class="mtk12">index</span><span class="mtk4">}</span><span class="mtk17">&gt;</span></span></span> <span class="grvsc-line grvsc-line-highlighted"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk4">{</span><span class="mtk12">tab</span><span class="mtk1">.</span><span class="mtk12">content</span><span class="mtk4">}</span></span></span> <span class="grvsc-line grvsc-line-highlighted"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk17">&lt;/</span><span class="mtk10">TabPanel</span><span class="mtk17">&gt;</span></span></span> <span class="grvsc-line grvsc-line-highlighted"><span class="grvsc-source"><span class="mtk1"> ))</span><span class="mtk4">}</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk17">&lt;/</span><span class="mtk10">Stack</span><span class="mtk17">&gt;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> );</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1">}</span></span></span> <span class="grvsc-line"><span class="grvsc-source"></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk4">const</span><span class="mtk1"> </span><span class="mtk11">TabPanel</span><span class="mtk1"> = ({ </span><span class="mtk12">children</span><span class="mtk1">, </span><span class="mtk12">value</span><span class="mtk1">, </span><span class="mtk12">index</span><span class="mtk1"> }) </span><span class="mtk4">=&gt;</span><span class="mtk1"> {</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk15">return</span><span class="mtk1"> </span><span class="mtk12">value</span><span class="mtk1"> === </span><span class="mtk12">index</span><span class="mtk1"> &amp;&amp; </span><span class="mtk17">&lt;</span><span class="mtk10">Box</span><span class="mtk17">&gt;</span><span class="mtk4">{</span><span class="mtk12">children</span><span class="mtk4">}</span><span class="mtk17">&lt;/</span><span class="mtk10">Box</span><span class="mtk17">&gt;</span><span class="mtk1">;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1">};</span></span></span></code></pre> <div id="FinalVerticalTabs" data-code data-height="150px"></div> <h2 id="advanced-customization" style="position:relative;"><a href="#advanced-customization" aria-label="advanced customization permalink" class="anchor before"><svg aria-hidden="true" focusable="false" height="16" version="1.1" viewBox="0 0 16 16" width="16"><path fill-rule="evenodd" d="M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z"></path></svg></a>Advanced Customization</h2> <p>In this section, we’ll transform the basic vertical tabs into a practical example showcasing their true capabilities. We aim to make the tabs look and behave like menu elements with icons and additional customizations.</p> <h3 id="enhancing-tab-labels-with-icons" style="position:relative;"><a href="#enhancing-tab-labels-with-icons" aria-label="enhancing tab labels with icons permalink" class="anchor before"><svg aria-hidden="true" focusable="false" height="16" version="1.1" viewBox="0 0 16 16" width="16"><path fill-rule="evenodd" d="M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z"></path></svg></a>Enhancing Tab Labels with Icons</h3> <p>First, let’s replace the tab <code>label</code> content with a <code>Stack</code> component to host the label text and an icon. Since we generate the tabs dynamically, we can include the required icons in the <code>tabData</code> array:</p> <pre class="grvsc-container default-dark" data-language="jsx" data-index="5"><code class="grvsc-code"><span class="grvsc-line"><span class="grvsc-source"><span class="mtk1">...</span></span></span> <span class="grvsc-line"><span class="grvsc-source"></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk4">const</span><span class="mtk1"> </span><span class="mtk12">tabData</span><span class="mtk1"> = [</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> {</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">label:</span><span class="mtk1"> </span><span class="mtk8">&#39;My Projects&#39;</span><span class="mtk1">,</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">content:</span><span class="mtk1"> </span><span class="mtk8">&#39;My Projects&#39;</span><span class="mtk1">,</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">icon:</span><span class="mtk1"> </span><span class="mtk17">&lt;</span><span class="mtk10">ListAltOutlinedIcon</span><span class="mtk1"> </span><span class="mtk17">/&gt;</span><span class="mtk1">,</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> },</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> {</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">label:</span><span class="mtk1"> </span><span class="mtk8">&#39;Account Settings&#39;</span><span class="mtk1">,</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">content:</span><span class="mtk1"> </span><span class="mtk8">&#39;Account Settings&#39;</span><span class="mtk1">,</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">icon:</span><span class="mtk1"> </span><span class="mtk17">&lt;</span><span class="mtk10">BuildCircleOutlinedIcon</span><span class="mtk1"> </span><span class="mtk17">/&gt;</span><span class="mtk1">,</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> },</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> {</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">label:</span><span class="mtk1"> </span><span class="mtk8">&#39;Payment Information&#39;</span><span class="mtk1">,</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">content:</span><span class="mtk1"> </span><span class="mtk8">&#39;Payment Information&#39;</span><span class="mtk1">,</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">icon:</span><span class="mtk1"> </span><span class="mtk17">&lt;</span><span class="mtk10">PaymentOutlinedIcon</span><span class="mtk1"> </span><span class="mtk17">/&gt;</span><span class="mtk1">,</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> },</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1">];</span></span></span> <span class="grvsc-line"><span class="grvsc-source"></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1">...</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk3">// Inside the Tabs component</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk17">&lt;</span><span class="mtk10">Tab</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">key</span><span class="mtk1">=</span><span class="mtk4">{</span><span class="mtk12">index</span><span class="mtk4">}</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">label</span><span class="mtk1">=</span><span class="mtk4">{</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk17">&lt;</span><span class="mtk10">Stack</span><span class="mtk1"> </span><span class="mtk12">direction</span><span class="mtk1">=</span><span class="mtk8">&quot;row&quot;</span><span class="mtk1"> </span><span class="mtk12">alignItems</span><span class="mtk1">=</span><span class="mtk8">&quot;center&quot;</span><span class="mtk1"> </span><span class="mtk12">gap</span><span class="mtk1">=</span><span class="mtk4">{</span><span class="mtk7">1</span><span class="mtk4">}</span><span class="mtk17">&gt;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk4">{</span><span class="mtk12">tab</span><span class="mtk1">.</span><span class="mtk12">icon</span><span class="mtk4">}</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk17">&lt;</span><span class="mtk10">Box</span><span class="mtk17">&gt;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk17">&lt;</span><span class="mtk10">Typography</span><span class="mtk1"> </span><span class="mtk12">whiteSpace</span><span class="mtk1">=</span><span class="mtk8">&quot;nowrap&quot;</span><span class="mtk17">&gt;</span><span class="mtk4">{</span><span class="mtk12">tab</span><span class="mtk1">.</span><span class="mtk12">label</span><span class="mtk4">}</span><span class="mtk17">&lt;/</span><span class="mtk10">Typography</span><span class="mtk17">&gt;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk17">&lt;/</span><span class="mtk10">Box</span><span class="mtk17">&gt;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk17">&lt;/</span><span class="mtk10">Stack</span><span class="mtk17">&gt;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk4">}</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk17">/&gt;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1">...</span></span></span></code></pre> <h3 id="styling-the-tabs" style="position:relative;"><a href="#styling-the-tabs" aria-label="styling the tabs permalink" class="anchor before"><svg aria-hidden="true" focusable="false" height="16" version="1.1" viewBox="0 0 16 16" width="16"><path fill-rule="evenodd" d="M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z"></path></svg></a>Styling the Tabs</h3> <p>Next, we can create a <code>StyledTab</code> component to add some aesthetic look and feel to the tabs:</p> <pre class="grvsc-container default-dark" data-language="jsx" data-index="6"><code class="grvsc-code"><span class="grvsc-line"><span class="grvsc-source"><span class="mtk15">import</span><span class="mtk1"> { </span><span class="mtk12">styled</span><span class="mtk1"> } </span><span class="mtk15">from</span><span class="mtk1"> </span><span class="mtk8">&quot;@mui/material/styles&quot;</span><span class="mtk1">;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk15">import</span><span class="mtk1"> { </span><span class="mtk12">grey</span><span class="mtk1">, </span><span class="mtk12">blue</span><span class="mtk1"> } </span><span class="mtk15">from</span><span class="mtk1"> </span><span class="mtk8">&quot;@mui/material/colors&quot;</span><span class="mtk1">;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk15">import</span><span class="mtk1"> </span><span class="mtk12">Tab</span><span class="mtk1"> </span><span class="mtk15">from</span><span class="mtk1"> </span><span class="mtk8">&quot;@mui/material/Tab&quot;</span><span class="mtk1">;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk4">const</span><span class="mtk1"> </span><span class="mtk12">StyledTab</span><span class="mtk1"> = </span><span class="mtk11">styled</span><span class="mtk1">(</span><span class="mtk12">Tab</span><span class="mtk1">)(({ </span><span class="mtk12">theme</span><span class="mtk1"> }) </span><span class="mtk4">=&gt;</span><span class="mtk1"> ({</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">alignItems:</span><span class="mtk1"> </span><span class="mtk8">&quot;flex-start&quot;</span><span class="mtk1">,</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">border:</span><span class="mtk1"> </span><span class="mtk8">&quot;1px solid&quot;</span><span class="mtk1">,</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">borderColor:</span><span class="mtk1"> </span><span class="mtk12">grey</span><span class="mtk1">[</span><span class="mtk7">300</span><span class="mtk1">],</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">textTransform:</span><span class="mtk1"> </span><span class="mtk8">&quot;none&quot;</span><span class="mtk1">,</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">backgroundColor:</span><span class="mtk1"> </span><span class="mtk12">grey</span><span class="mtk1">[</span><span class="mtk7">50</span><span class="mtk1">],</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">borderRadius:</span><span class="mtk1"> </span><span class="mtk8">&quot;12px&quot;</span><span class="mtk1">,</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">padding:</span><span class="mtk1"> </span><span class="mtk8">&quot;24px&quot;</span><span class="mtk1">,</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">transition:</span><span class="mtk1"> </span><span class="mtk8">&quot;all 0.2s ease-in-out&quot;</span><span class="mtk1">,</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk8">&quot;&amp; p&quot;</span><span class="mtk12">:</span><span class="mtk1"> {</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">color:</span><span class="mtk1"> </span><span class="mtk12">grey</span><span class="mtk1">[</span><span class="mtk7">600</span><span class="mtk1">],</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> },</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk8">&quot;&amp; svg&quot;</span><span class="mtk12">:</span><span class="mtk1"> {</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">fontSize:</span><span class="mtk1"> </span><span class="mtk7">30</span><span class="mtk1">,</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">color:</span><span class="mtk1"> </span><span class="mtk12">grey</span><span class="mtk1">[</span><span class="mtk7">500</span><span class="mtk1">],</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> },</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk8">&quot;&amp;.Mui-selected, &amp;:hover&quot;</span><span class="mtk12">:</span><span class="mtk1"> {</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">backgroundColor:</span><span class="mtk1"> </span><span class="mtk8">&quot;#fff&quot;</span><span class="mtk1">,</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">boxShadow:</span><span class="mtk1"> </span><span class="mtk12">theme</span><span class="mtk1">.</span><span class="mtk12">shadows</span><span class="mtk1">[</span><span class="mtk7">3</span><span class="mtk1">],</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk8">&quot;&amp; p&quot;</span><span class="mtk12">:</span><span class="mtk1"> {</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">color:</span><span class="mtk1"> </span><span class="mtk12">blue</span><span class="mtk1">[</span><span class="mtk7">500</span><span class="mtk1">],</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> },</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk8">&quot;&amp; svg&quot;</span><span class="mtk12">:</span><span class="mtk1"> {</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">color:</span><span class="mtk1"> </span><span class="mtk12">blue</span><span class="mtk1">[</span><span class="mtk7">400</span><span class="mtk1">],</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> },</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> },</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1">}));</span></span></span></code></pre> <p>In this code:</p> <ul> <li>We use the <code>styled</code> function from MUI to create a custom <code>StyledTab</code> component.</li> <li>Include styles for the tab’s background, border, padding, and transitions.</li> <li>The <code>&#x26; p</code> and <code>&#x26; svg</code> selectors target the text and icon inside the tab, respectively.</li> <li>The <code>&#x26;.Mui-selected</code>, <code>&#x26;:hover</code> selector styles the tab when it’s selected or hovered over.</li> </ul> <h3 id="customizing-the-tabpanel" style="position:relative;"><a href="#customizing-the-tabpanel" aria-label="customizing the tabpanel permalink" class="anchor before"><svg aria-hidden="true" focusable="false" height="16" version="1.1" viewBox="0 0 16 16" width="16"><path fill-rule="evenodd" d="M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z"></path></svg></a>Customizing the TabPanel</h3> <p>Finally, we can make the <code>TabPanel</code> a <code>Paper</code> component to give it a proper section look:</p> <pre class="grvsc-container default-dark" data-language="jsx" data-index="7"><code class="grvsc-code"><span class="grvsc-line"><span class="grvsc-source"><span class="mtk15">import</span><span class="mtk1"> </span><span class="mtk12">Paper</span><span class="mtk1"> </span><span class="mtk15">from</span><span class="mtk1"> </span><span class="mtk8">&quot;@mui/material/Paper&quot;</span><span class="mtk1">;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk4">const</span><span class="mtk1"> </span><span class="mtk11">TabPanel</span><span class="mtk1"> = ({ </span><span class="mtk12">children</span><span class="mtk1">, </span><span class="mtk12">value</span><span class="mtk1">, </span><span class="mtk12">index</span><span class="mtk1"> }) </span><span class="mtk4">=&gt;</span><span class="mtk1"> {</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk15">return</span><span class="mtk1"> (</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">value</span><span class="mtk1"> === </span><span class="mtk12">index</span><span class="mtk1"> &amp;&amp; (</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk17">&lt;</span><span class="mtk10">Paper</span><span class="mtk1"> </span><span class="mtk12">elevation</span><span class="mtk1">=</span><span class="mtk4">{</span><span class="mtk7">3</span><span class="mtk4">}</span><span class="mtk1"> </span><span class="mtk12">sx</span><span class="mtk1">=</span><span class="mtk4">{</span><span class="mtk1">{ </span><span class="mtk12">p:</span><span class="mtk1"> </span><span class="mtk7">3</span><span class="mtk1">, </span><span class="mtk12">width:</span><span class="mtk1"> </span><span class="mtk8">&quot;60%&quot;</span><span class="mtk1">, </span><span class="mtk12">borderRadius:</span><span class="mtk1"> </span><span class="mtk8">&quot;12px&quot;</span><span class="mtk1"> }</span><span class="mtk4">}</span><span class="mtk17">&gt;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk4">{</span><span class="mtk12">children</span><span class="mtk4">}</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk17">&lt;/</span><span class="mtk10">Paper</span><span class="mtk17">&gt;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> )</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> );</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1">};</span></span></span></code></pre> <h3 id="putting-it-all-together" style="position:relative;"><a href="#putting-it-all-together" aria-label="putting it all together permalink" class="anchor before"><svg aria-hidden="true" focusable="false" height="16" version="1.1" viewBox="0 0 16 16" width="16"><path fill-rule="evenodd" d="M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z"></path></svg></a>Putting It All Together</h3> <p>Let’s combine all the pieces and look at the final result:</p> <pre class="grvsc-container default-dark" data-language="jsx" data-index="8"><code class="grvsc-code"><span class="grvsc-line"><span class="grvsc-source"><span class="mtk15">import</span><span class="mtk1"> </span><span class="mtk12">React</span><span class="mtk1"> </span><span class="mtk15">from</span><span class="mtk1"> </span><span class="mtk8">&quot;react&quot;</span><span class="mtk1">;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk15">import</span><span class="mtk1"> {</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">Box</span><span class="mtk1">,</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">Stack</span><span class="mtk1">,</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">Tabs</span><span class="mtk1">,</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">Tab</span><span class="mtk1">,</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">Typography</span><span class="mtk1">,</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">Paper</span><span class="mtk1">,</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">styled</span><span class="mtk1">,</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1">} </span><span class="mtk15">from</span><span class="mtk1"> </span><span class="mtk8">&quot;@mui/material&quot;</span><span class="mtk1">;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk15">import</span><span class="mtk1"> { </span><span class="mtk12">blue</span><span class="mtk1">, </span><span class="mtk12">grey</span><span class="mtk1"> } </span><span class="mtk15">from</span><span class="mtk1"> </span><span class="mtk8">&quot;@mui/material/colors&quot;</span><span class="mtk1">;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk15">import</span><span class="mtk1"> </span><span class="mtk12">BuildCircleOutlinedIcon</span><span class="mtk1"> </span><span class="mtk15">from</span><span class="mtk1"> </span><span class="mtk8">&quot;@mui/icons-material/BuildCircleOutlined&quot;</span><span class="mtk1">;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk15">import</span><span class="mtk1"> </span><span class="mtk12">ListAltOutlinedIcon</span><span class="mtk1"> </span><span class="mtk15">from</span><span class="mtk1"> </span><span class="mtk8">&quot;@mui/icons-material/ListAltOutlined&quot;</span><span class="mtk1">;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk15">import</span><span class="mtk1"> </span><span class="mtk12">PaymentOutlinedIcon</span><span class="mtk1"> </span><span class="mtk15">from</span><span class="mtk1"> </span><span class="mtk8">&quot;@mui/icons-material/PaymentOutlined&quot;</span><span class="mtk1">;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk4">const</span><span class="mtk1"> </span><span class="mtk12">tabData</span><span class="mtk1"> = [</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> {</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">label:</span><span class="mtk1"> </span><span class="mtk8">&quot;My Projects&quot;</span><span class="mtk1">,</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">content:</span><span class="mtk1"> </span><span class="mtk8">&quot;My Projects&quot;</span><span class="mtk1">,</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">icon:</span><span class="mtk1"> </span><span class="mtk17">&lt;</span><span class="mtk10">ListAltOutlinedIcon</span><span class="mtk1"> </span><span class="mtk17">/&gt;</span><span class="mtk1">,</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> },</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> {</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">label:</span><span class="mtk1"> </span><span class="mtk8">&quot;Account Settings&quot;</span><span class="mtk1">,</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">content:</span><span class="mtk1"> </span><span class="mtk8">&quot;Account Settings&quot;</span><span class="mtk1">,</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">icon:</span><span class="mtk1"> </span><span class="mtk17">&lt;</span><span class="mtk10">BuildCircleOutlinedIcon</span><span class="mtk1"> </span><span class="mtk17">/&gt;</span><span class="mtk1">,</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> },</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> {</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">label:</span><span class="mtk1"> </span><span class="mtk8">&quot;Payment Information&quot;</span><span class="mtk1">,</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">content:</span><span class="mtk1"> </span><span class="mtk8">&quot;Payment Information&quot;</span><span class="mtk1">,</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">icon:</span><span class="mtk1"> </span><span class="mtk17">&lt;</span><span class="mtk10">PaymentOutlinedIcon</span><span class="mtk1"> </span><span class="mtk17">/&gt;</span><span class="mtk1">,</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> },</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1">];</span></span></span> <span class="grvsc-line"><span class="grvsc-source"></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk15">export</span><span class="mtk1"> </span><span class="mtk15">default</span><span class="mtk1"> </span><span class="mtk4">function</span><span class="mtk1"> </span><span class="mtk11">CustomThemeTextField</span><span class="mtk1">() {</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk4">const</span><span class="mtk1"> [</span><span class="mtk12">value</span><span class="mtk1">, </span><span class="mtk12">setValue</span><span class="mtk1">] = </span><span class="mtk12">React</span><span class="mtk1">.</span><span class="mtk11">useState</span><span class="mtk1">(</span><span class="mtk7">0</span><span class="mtk1">);</span></span></span> <span class="grvsc-line"><span class="grvsc-source"></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk15">return</span><span class="mtk1"> (</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk17">&lt;</span><span class="mtk10">Stack</span><span class="mtk1"> </span><span class="mtk12">direction</span><span class="mtk1">=</span><span class="mtk8">&quot;row&quot;</span><span class="mtk1"> </span><span class="mtk12">gap</span><span class="mtk1">=</span><span class="mtk4">{</span><span class="mtk7">2</span><span class="mtk4">}</span><span class="mtk1"> </span><span class="mtk12">height</span><span class="mtk1">=</span><span class="mtk8">&quot;265px&quot;</span><span class="mtk17">&gt;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk17">&lt;</span><span class="mtk10">Tabs</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">orientation</span><span class="mtk1">=</span><span class="mtk8">&quot;vertical&quot;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">indicatorColor</span><span class="mtk1">=</span><span class="mtk8">&quot;white&quot;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">value</span><span class="mtk1">=</span><span class="mtk4">{</span><span class="mtk12">value</span><span class="mtk4">}</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">onChange</span><span class="mtk1">=</span><span class="mtk4">{</span><span class="mtk1">(</span><span class="mtk12">_event</span><span class="mtk1">, </span><span class="mtk12">newValue</span><span class="mtk1">) </span><span class="mtk4">=&gt;</span><span class="mtk1"> </span><span class="mtk11">setValue</span><span class="mtk1">(</span><span class="mtk12">newValue</span><span class="mtk1">)</span><span class="mtk4">}</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">sx</span><span class="mtk1">=</span><span class="mtk4">{</span><span class="mtk1">{</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk8">&quot;&amp; .MuiTabs-flexContainer&quot;</span><span class="mtk12">:</span><span class="mtk1"> {</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">gap:</span><span class="mtk1"> </span><span class="mtk7">1</span><span class="mtk1">,</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> },</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> }</span><span class="mtk4">}</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk17">&gt;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk4">{</span><span class="mtk12">tabData</span><span class="mtk1">.</span><span class="mtk11">map</span><span class="mtk1">((</span><span class="mtk12">tab</span><span class="mtk1">, </span><span class="mtk12">index</span><span class="mtk1">) </span><span class="mtk4">=&gt;</span><span class="mtk1"> (</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk17">&lt;</span><span class="mtk10">StyledTab</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">key</span><span class="mtk1">=</span><span class="mtk4">{</span><span class="mtk12">index</span><span class="mtk4">}</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">label</span><span class="mtk1">=</span><span class="mtk4">{</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk17">&lt;</span><span class="mtk10">Stack</span><span class="mtk1"> </span><span class="mtk12">direction</span><span class="mtk1">=</span><span class="mtk8">&quot;row&quot;</span><span class="mtk1"> </span><span class="mtk12">alignItems</span><span class="mtk1">=</span><span class="mtk8">&quot;center&quot;</span><span class="mtk1"> </span><span class="mtk12">gap</span><span class="mtk1">=</span><span class="mtk4">{</span><span class="mtk7">1</span><span class="mtk4">}</span><span class="mtk17">&gt;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk4">{</span><span class="mtk12">tab</span><span class="mtk1">.</span><span class="mtk12">icon</span><span class="mtk4">}</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk17">&lt;</span><span class="mtk10">Box</span><span class="mtk17">&gt;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk17">&lt;</span><span class="mtk10">Typography</span><span class="mtk1"> </span><span class="mtk12">whiteSpace</span><span class="mtk1">=</span><span class="mtk8">&quot;nowrap&quot;</span><span class="mtk17">&gt;</span><span class="mtk4">{</span><span class="mtk12">tab</span><span class="mtk1">.</span><span class="mtk12">label</span><span class="mtk4">}</span><span class="mtk17">&lt;/</span><span class="mtk10">Typography</span><span class="mtk17">&gt;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk17">&lt;/</span><span class="mtk10">Box</span><span class="mtk17">&gt;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk17">&lt;/</span><span class="mtk10">Stack</span><span class="mtk17">&gt;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk4">}</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk17">/&gt;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> ))</span><span class="mtk4">}</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk17">&lt;/</span><span class="mtk10">Tabs</span><span class="mtk17">&gt;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk4">{</span><span class="mtk12">tabData</span><span class="mtk1">.</span><span class="mtk11">map</span><span class="mtk1">((</span><span class="mtk12">tab</span><span class="mtk1">, </span><span class="mtk12">index</span><span class="mtk1">) </span><span class="mtk4">=&gt;</span><span class="mtk1"> (</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk17">&lt;</span><span class="mtk10">TabPanel</span><span class="mtk1"> </span><span class="mtk12">key</span><span class="mtk1">=</span><span class="mtk4">{</span><span class="mtk12">index</span><span class="mtk4">}</span><span class="mtk1"> </span><span class="mtk12">value</span><span class="mtk1">=</span><span class="mtk4">{</span><span class="mtk12">value</span><span class="mtk4">}</span><span class="mtk1"> </span><span class="mtk12">index</span><span class="mtk1">=</span><span class="mtk4">{</span><span class="mtk12">index</span><span class="mtk4">}</span><span class="mtk17">&gt;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk4">{</span><span class="mtk12">tab</span><span class="mtk1">.</span><span class="mtk12">content</span><span class="mtk4">}</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk17">&lt;/</span><span class="mtk10">TabPanel</span><span class="mtk17">&gt;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> ))</span><span class="mtk4">}</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk17">&lt;/</span><span class="mtk10">Stack</span><span class="mtk17">&gt;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> );</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1">}</span></span></span> <span class="grvsc-line"><span class="grvsc-source"></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk4">const</span><span class="mtk1"> </span><span class="mtk12">StyledTab</span><span class="mtk1"> = </span><span class="mtk11">styled</span><span class="mtk1">(</span><span class="mtk12">Tab</span><span class="mtk1">)(({ </span><span class="mtk12">theme</span><span class="mtk1"> }) </span><span class="mtk4">=&gt;</span><span class="mtk1"> ({</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">alignItems:</span><span class="mtk1"> </span><span class="mtk8">&quot;flex-start&quot;</span><span class="mtk1">,</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">border:</span><span class="mtk1"> </span><span class="mtk8">&quot;1px solid&quot;</span><span class="mtk1">,</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">borderColor:</span><span class="mtk1"> </span><span class="mtk12">grey</span><span class="mtk1">[</span><span class="mtk7">300</span><span class="mtk1">],</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">textTransform:</span><span class="mtk1"> </span><span class="mtk8">&quot;none&quot;</span><span class="mtk1">,</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">backgroundColor:</span><span class="mtk1"> </span><span class="mtk12">grey</span><span class="mtk1">[</span><span class="mtk7">50</span><span class="mtk1">],</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">borderRadius:</span><span class="mtk1"> </span><span class="mtk8">&quot;12px&quot;</span><span class="mtk1">,</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">padding:</span><span class="mtk1"> </span><span class="mtk8">&quot;24px&quot;</span><span class="mtk1">,</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">transition:</span><span class="mtk1"> </span><span class="mtk8">&quot;all 0.2s ease-in-out&quot;</span><span class="mtk1">,</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk8">&quot;&amp; p&quot;</span><span class="mtk12">:</span><span class="mtk1"> {</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">color:</span><span class="mtk1"> </span><span class="mtk12">grey</span><span class="mtk1">[</span><span class="mtk7">600</span><span class="mtk1">],</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> },</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk8">&quot;&amp; svg&quot;</span><span class="mtk12">:</span><span class="mtk1"> {</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">fontSize:</span><span class="mtk1"> </span><span class="mtk7">30</span><span class="mtk1">,</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">color:</span><span class="mtk1"> </span><span class="mtk12">grey</span><span class="mtk1">[</span><span class="mtk7">500</span><span class="mtk1">],</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> },</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk8">&quot;&amp;.Mui-selected, &amp;:hover&quot;</span><span class="mtk12">:</span><span class="mtk1"> {</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">backgroundColor:</span><span class="mtk1"> </span><span class="mtk8">&quot;#fff&quot;</span><span class="mtk1">,</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">boxShadow:</span><span class="mtk1"> </span><span class="mtk12">theme</span><span class="mtk1">.</span><span class="mtk12">shadows</span><span class="mtk1">[</span><span class="mtk7">3</span><span class="mtk1">],</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk8">&quot;&amp; p&quot;</span><span class="mtk12">:</span><span class="mtk1"> {</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">color:</span><span class="mtk1"> </span><span class="mtk12">blue</span><span class="mtk1">[</span><span class="mtk7">500</span><span class="mtk1">],</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> },</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk8">&quot;&amp; svg&quot;</span><span class="mtk12">:</span><span class="mtk1"> {</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">color:</span><span class="mtk1"> </span><span class="mtk12">blue</span><span class="mtk1">[</span><span class="mtk7">400</span><span class="mtk1">],</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> },</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> },</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1">}));</span></span></span> <span class="grvsc-line"><span class="grvsc-source"></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk4">const</span><span class="mtk1"> </span><span class="mtk11">TabPanel</span><span class="mtk1"> = ({ </span><span class="mtk12">children</span><span class="mtk1">, </span><span class="mtk12">value</span><span class="mtk1">, </span><span class="mtk12">index</span><span class="mtk1"> }) </span><span class="mtk4">=&gt;</span><span class="mtk1"> {</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk15">return</span><span class="mtk1"> (</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">value</span><span class="mtk1"> === </span><span class="mtk12">index</span><span class="mtk1"> &amp;&amp; (</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk17">&lt;</span><span class="mtk10">Paper</span><span class="mtk1"> </span><span class="mtk12">elevation</span><span class="mtk1">=</span><span class="mtk4">{</span><span class="mtk7">3</span><span class="mtk4">}</span><span class="mtk1"> </span><span class="mtk12">sx</span><span class="mtk1">=</span><span class="mtk4">{</span><span class="mtk1">{ </span><span class="mtk12">p:</span><span class="mtk1"> </span><span class="mtk7">3</span><span class="mtk1">, </span><span class="mtk12">width:</span><span class="mtk1"> </span><span class="mtk8">&quot;60%&quot;</span><span class="mtk1">, </span><span class="mtk12">borderRadius:</span><span class="mtk1"> </span><span class="mtk8">&quot;12px&quot;</span><span class="mtk1"> }</span><span class="mtk4">}</span><span class="mtk17">&gt;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk4">{</span><span class="mtk12">children</span><span class="mtk4">}</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk17">&lt;/</span><span class="mtk10">Paper</span><span class="mtk17">&gt;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> )</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> );</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1">};</span></span></span></code></pre> <div id="FinalCustomVerticalTabs" data-code data-height="400px"></div> <h2 id="summary" style="position:relative;"><a href="#summary" aria-label="summary permalink" class="anchor before"><svg aria-hidden="true" focusable="false" height="16" version="1.1" viewBox="0 0 16 16" width="16"><path fill-rule="evenodd" d="M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z"></path></svg></a>Summary</h2> <p>In this tutorial, we learned how to create vertical tabs in React using MUI. We started with the basic implementation of vertical tabs and then enhanced them with icons, custom styles, and additional features. By leveraging MUI’s powerful components and styling options, we created a practical and visually appealing vertical tabs layout.</p> <p>Bye for now 👋</p> <style class="grvsc-styles"> .grvsc-container { overflow: auto; position: relative; -webkit-overflow-scrolling: touch; padding-top: 1rem; padding-top: var(--grvsc-padding-top, var(--grvsc-padding-v, 1rem)); padding-bottom: 1rem; padding-bottom: var(--grvsc-padding-bottom, var(--grvsc-padding-v, 1rem)); border-radius: 8px; border-radius: var(--grvsc-border-radius, 8px); font-feature-settings: normal; line-height: 1.4; } .grvsc-code { display: table; } .grvsc-line { display: table-row; box-sizing: border-box; width: 100%; position: relative; } .grvsc-line > * { position: relative; } .grvsc-gutter-pad { display: table-cell; padding-left: 0.75rem; padding-left: calc(var(--grvsc-padding-left, var(--grvsc-padding-h, 1.5rem)) / 2); } .grvsc-gutter { display: table-cell; -webkit-user-select: none; -moz-user-select: none; user-select: none; } .grvsc-gutter::before { content: attr(data-content); } .grvsc-source { display: table-cell; padding-left: 1.5rem; padding-left: var(--grvsc-padding-left, var(--grvsc-padding-h, 1.5rem)); padding-right: 1.5rem; padding-right: var(--grvsc-padding-right, var(--grvsc-padding-h, 1.5rem)); } .grvsc-source:empty::after { content: ' '; -webkit-user-select: none; -moz-user-select: none; user-select: none; } .grvsc-gutter + .grvsc-source { padding-left: 0.75rem; padding-left: calc(var(--grvsc-padding-left, var(--grvsc-padding-h, 1.5rem)) / 2); } /* Line transformer styles */ .grvsc-has-line-highlighting > .grvsc-code > .grvsc-line::before { content: ' '; position: absolute; width: 100%; } .grvsc-line-diff-add::before { background-color: var(--grvsc-line-diff-add-background-color, rgba(0, 255, 60, 0.2)); } .grvsc-line-diff-del::before { background-color: var(--grvsc-line-diff-del-background-color, rgba(255, 0, 20, 0.2)); } .grvsc-line-number { padding: 0 2px; text-align: right; opacity: 0.7; } .default-dark { background-color: #1E1E1E; color: #D4D4D4; } .default-dark .mtk15 { color: #C586C0; } .default-dark .mtk1 { color: #D4D4D4; } .default-dark .mtk12 { color: #9CDCFE; } .default-dark .mtk8 { color: #CE9178; } .default-dark .mtk4 { color: #569CD6; } .default-dark .mtk11 { color: #DCDCAA; } .default-dark .mtk17 { color: #808080; } .default-dark .mtk10 { color: #4EC9B0; } .default-dark .mtk7 { color: #B5CEA8; } .default-dark .mtk3 { color: #6A9955; } .default-dark .grvsc-line-highlighted::before { background-color: var(--grvsc-line-highlighted-background-color, rgba(255, 255, 255, 0.1)); box-shadow: inset var(--grvsc-line-highlighted-border-width, 4px) 0 0 0 var(--grvsc-line-highlighted-border-color, rgba(255, 255, 255, 0.5)); } </style><![CDATA[How to Create a Sticky Header & Column in React]]>https://muhimasri.comreact-sticky-header-columnhttps://muhimasri.comreact-sticky-header-column<p>In the modern digital era, where data is growing faster than ever, efficiently handling and displaying complex tabular data becomes crucial for the UI. Whether it’s financial reports, inventory management, or extensive datasets for machine learning, the ability to scroll through large amounts of data without losing context is essential. This is where the concept of sticky headers and columns comes into play, providing a fixed point of reference that enhances readability and user experience.</p> <p>In this tutorial, we will build a React component that features a table with sticky headers and columns. This means that the header row and specific columns will remain visible on the screen even as we scroll vertically or horizontally through our dataset.</p> <h2 id="creating-a-scrollable-table-in-react" style="position:relative;"><a href="#creating-a-scrollable-table-in-react" aria-label="creating a scrollable table in react permalink" class="anchor before"><svg aria-hidden="true" focusable="false" height="16" version="1.1" viewBox="0 0 16 16" width="16"><path fill-rule="evenodd" d="M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z"></path></svg></a>Creating a Scrollable Table in React</h2> <p>To start, we’ll build a basic scrollable table in React that displays student information. This table will dynamically populate rows based on a dataset and be styled to support both vertical and horizontal scrolling. Let’s break down the steps and write the necessary code.</p> <h3 id="step-1-creating-a-basic-table-component" style="position:relative;"><a href="#step-1-creating-a-basic-table-component" aria-label="step 1 creating a basic table component permalink" class="anchor before"><svg aria-hidden="true" focusable="false" height="16" version="1.1" viewBox="0 0 16 16" width="16"><path fill-rule="evenodd" d="M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z"></path></svg></a>Step 1: Creating a Basic Table Component</h3> <pre class="grvsc-container default-dark" data-language="jsx" data-index="0"><code class="grvsc-code"><span class="grvsc-line"><span class="grvsc-source"><span class="mtk15">import</span><span class="mtk1"> </span><span class="mtk8">&quot;./App.css&quot;</span><span class="mtk1">;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk4">const</span><span class="mtk1"> </span><span class="mtk12">students</span><span class="mtk1"> = [</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> {</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1">  </span><span class="mtk12">id:</span><span class="mtk1"> </span><span class="mtk7">1</span><span class="mtk1">,</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1">  </span><span class="mtk12">name:</span><span class="mtk1"> </span><span class="mtk8">&quot;John Doe&quot;</span><span class="mtk1">,</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1">  </span><span class="mtk12">age:</span><span class="mtk1"> </span><span class="mtk7">20</span><span class="mtk1">,</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1">  </span><span class="mtk12">course:</span><span class="mtk1"> </span><span class="mtk8">&quot;Business&quot;</span><span class="mtk1">,</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1">  </span><span class="mtk12">grade:</span><span class="mtk1"> </span><span class="mtk8">&quot;A&quot;</span><span class="mtk1">,</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1">  </span><span class="mtk12">attendance:</span><span class="mtk1"> </span><span class="mtk8">&quot;Present&quot;</span><span class="mtk1">,</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1">  </span><span class="mtk12">status:</span><span class="mtk1"> </span><span class="mtk8">&quot;Active&quot;</span><span class="mtk1">,</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1">  </span><span class="mtk12">remarks:</span><span class="mtk1"> </span><span class="mtk8">&quot;Good&quot;</span><span class="mtk1">,</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> },</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> {</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1">  </span><span class="mtk12">id:</span><span class="mtk1"> </span><span class="mtk7">2</span><span class="mtk1">,</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1">  </span><span class="mtk12">name:</span><span class="mtk1"> </span><span class="mtk8">&quot;Jane Smith&quot;</span><span class="mtk1">,</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1">  </span><span class="mtk12">age:</span><span class="mtk1"> </span><span class="mtk7">22</span><span class="mtk1">,</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1">  </span><span class="mtk12">course:</span><span class="mtk1"> </span><span class="mtk8">&quot;Engineering&quot;</span><span class="mtk1">,</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1">  </span><span class="mtk12">grade:</span><span class="mtk1"> </span><span class="mtk8">&quot;B&quot;</span><span class="mtk1">,</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1">  </span><span class="mtk12">attendance:</span><span class="mtk1"> </span><span class="mtk8">&quot;Absent&quot;</span><span class="mtk1">,</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1">  </span><span class="mtk12">status:</span><span class="mtk1"> </span><span class="mtk8">&quot;Inactive&quot;</span><span class="mtk1">,</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1">  </span><span class="mtk12">remarks:</span><span class="mtk1"> </span><span class="mtk8">&quot;Average&quot;</span><span class="mtk1">,</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> },</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> {</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1">  </span><span class="mtk12">id:</span><span class="mtk1"> </span><span class="mtk7">3</span><span class="mtk1">,</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1">  </span><span class="mtk12">name:</span><span class="mtk1"> </span><span class="mtk8">&quot;Alice Johnson&quot;</span><span class="mtk1">,</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1">  </span><span class="mtk12">age:</span><span class="mtk1"> </span><span class="mtk7">21</span><span class="mtk1">,</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1">  </span><span class="mtk12">course:</span><span class="mtk1"> </span><span class="mtk8">&quot;Medicine&quot;</span><span class="mtk1">,</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1">  </span><span class="mtk12">grade:</span><span class="mtk1"> </span><span class="mtk8">&quot;A+&quot;</span><span class="mtk1">,</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1">  </span><span class="mtk12">attendance:</span><span class="mtk1"> </span><span class="mtk8">&quot;Present&quot;</span><span class="mtk1">,</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1">  </span><span class="mtk12">status:</span><span class="mtk1"> </span><span class="mtk8">&quot;Active&quot;</span><span class="mtk1">,</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1">  </span><span class="mtk12">remarks:</span><span class="mtk1"> </span><span class="mtk8">&quot;Excellent&quot;</span><span class="mtk1">,</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> },</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> {</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1">  </span><span class="mtk12">id:</span><span class="mtk1"> </span><span class="mtk7">4</span><span class="mtk1">,</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1">  </span><span class="mtk12">name:</span><span class="mtk1"> </span><span class="mtk8">&quot;Bob Brown&quot;</span><span class="mtk1">,</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1">  </span><span class="mtk12">age:</span><span class="mtk1"> </span><span class="mtk7">23</span><span class="mtk1">,</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1">  </span><span class="mtk12">course:</span><span class="mtk1"> </span><span class="mtk8">&quot;Computer Science&quot;</span><span class="mtk1">,</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1">  </span><span class="mtk12">grade:</span><span class="mtk1"> </span><span class="mtk8">&quot;C&quot;</span><span class="mtk1">,</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1">  </span><span class="mtk12">attendance:</span><span class="mtk1"> </span><span class="mtk8">&quot;Present&quot;</span><span class="mtk1">,</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1">  </span><span class="mtk12">status:</span><span class="mtk1"> </span><span class="mtk8">&quot;Active&quot;</span><span class="mtk1">,</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1">  </span><span class="mtk12">remarks:</span><span class="mtk1"> </span><span class="mtk8">&quot;Fair&quot;</span><span class="mtk1">,</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> },</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> {</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1">  </span><span class="mtk12">id:</span><span class="mtk1"> </span><span class="mtk7">5</span><span class="mtk1">,</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1">  </span><span class="mtk12">name:</span><span class="mtk1"> </span><span class="mtk8">&quot;Eve Wilson&quot;</span><span class="mtk1">,</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1">  </span><span class="mtk12">age:</span><span class="mtk1"> </span><span class="mtk7">24</span><span class="mtk1">,</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1">  </span><span class="mtk12">course:</span><span class="mtk1"> </span><span class="mtk8">&quot;Arts&quot;</span><span class="mtk1">,</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1">  </span><span class="mtk12">grade:</span><span class="mtk1"> </span><span class="mtk8">&quot;B+&quot;</span><span class="mtk1">,</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1">  </span><span class="mtk12">attendance:</span><span class="mtk1"> </span><span class="mtk8">&quot;Absent&quot;</span><span class="mtk1">,</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1">  </span><span class="mtk12">status:</span><span class="mtk1"> </span><span class="mtk8">&quot;Inactive&quot;</span><span class="mtk1">,</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1">  </span><span class="mtk12">remarks:</span><span class="mtk1"> </span><span class="mtk8">&quot;Good&quot;</span><span class="mtk1">,</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> },</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> {</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1">  </span><span class="mtk12">id:</span><span class="mtk1"> </span><span class="mtk7">6</span><span class="mtk1">,</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1">  </span><span class="mtk12">name:</span><span class="mtk1"> </span><span class="mtk8">&quot;David Lee&quot;</span><span class="mtk1">,</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1">  </span><span class="mtk12">age:</span><span class="mtk1"> </span><span class="mtk7">25</span><span class="mtk1">,</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1">  </span><span class="mtk12">course:</span><span class="mtk1"> </span><span class="mtk8">&quot;Law&quot;</span><span class="mtk1">,</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1">  </span><span class="mtk12">grade:</span><span class="mtk1"> </span><span class="mtk8">&quot;A-&quot;</span><span class="mtk1">,</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1">  </span><span class="mtk12">attendance:</span><span class="mtk1"> </span><span class="mtk8">&quot;Present&quot;</span><span class="mtk1">,</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1">  </span><span class="mtk12">status:</span><span class="mtk1"> </span><span class="mtk8">&quot;Active&quot;</span><span class="mtk1">,</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1">  </span><span class="mtk12">remarks:</span><span class="mtk1"> </span><span class="mtk8">&quot;Very Good&quot;</span><span class="mtk1">,</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> },</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> {</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1">  </span><span class="mtk12">id:</span><span class="mtk1"> </span><span class="mtk7">7</span><span class="mtk1">,</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1">  </span><span class="mtk12">name:</span><span class="mtk1"> </span><span class="mtk8">&quot;Grace Clark&quot;</span><span class="mtk1">,</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1">  </span><span class="mtk12">age:</span><span class="mtk1"> </span><span class="mtk7">26</span><span class="mtk1">,</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1">  </span><span class="mtk12">course:</span><span class="mtk1"> </span><span class="mtk8">&quot;Science&quot;</span><span class="mtk1">,</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1">  </span><span class="mtk12">grade:</span><span class="mtk1"> </span><span class="mtk8">&quot;D&quot;</span><span class="mtk1">,</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1">  </span><span class="mtk12">attendance:</span><span class="mtk1"> </span><span class="mtk8">&quot;Absent&quot;</span><span class="mtk1">,</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1">  </span><span class="mtk12">status:</span><span class="mtk1"> </span><span class="mtk8">&quot;Inactive&quot;</span><span class="mtk1">,</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1">  </span><span class="mtk12">remarks:</span><span class="mtk1"> </span><span class="mtk8">&quot;Poor&quot;</span><span class="mtk1">,</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> },</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1">];</span></span></span> <span class="grvsc-line"><span class="grvsc-source"></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk4">const</span><span class="mtk1"> </span><span class="mtk11">TableComponent</span><span class="mtk1"> = () </span><span class="mtk4">=&gt;</span><span class="mtk1"> {</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk15">return</span><span class="mtk1"> (</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1">  </span><span class="mtk17">&lt;</span><span class="mtk4">table</span><span class="mtk17">&gt;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1">   </span><span class="mtk17">&lt;</span><span class="mtk4">thead</span><span class="mtk17">&gt;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1">    </span><span class="mtk17">&lt;</span><span class="mtk4">tr</span><span class="mtk17">&gt;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1">     </span><span class="mtk17">&lt;</span><span class="mtk4">th</span><span class="mtk17">&gt;</span><span class="mtk1">ID</span><span class="mtk17">&lt;/</span><span class="mtk4">th</span><span class="mtk17">&gt;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1">     </span><span class="mtk17">&lt;</span><span class="mtk4">th</span><span class="mtk17">&gt;</span><span class="mtk1">Name</span><span class="mtk17">&lt;/</span><span class="mtk4">th</span><span class="mtk17">&gt;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1">     </span><span class="mtk17">&lt;</span><span class="mtk4">th</span><span class="mtk17">&gt;</span><span class="mtk1">Age</span><span class="mtk17">&lt;/</span><span class="mtk4">th</span><span class="mtk17">&gt;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1">     </span><span class="mtk17">&lt;</span><span class="mtk4">th</span><span class="mtk17">&gt;</span><span class="mtk1">Course</span><span class="mtk17">&lt;/</span><span class="mtk4">th</span><span class="mtk17">&gt;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1">     </span><span class="mtk17">&lt;</span><span class="mtk4">th</span><span class="mtk17">&gt;</span><span class="mtk1">Grade</span><span class="mtk17">&lt;/</span><span class="mtk4">th</span><span class="mtk17">&gt;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1">     </span><span class="mtk17">&lt;</span><span class="mtk4">th</span><span class="mtk17">&gt;</span><span class="mtk1">Attendance</span><span class="mtk17">&lt;/</span><span class="mtk4">th</span><span class="mtk17">&gt;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1">     </span><span class="mtk17">&lt;</span><span class="mtk4">th</span><span class="mtk17">&gt;</span><span class="mtk1">Status</span><span class="mtk17">&lt;/</span><span class="mtk4">th</span><span class="mtk17">&gt;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1">     </span><span class="mtk17">&lt;</span><span class="mtk4">th</span><span class="mtk17">&gt;</span><span class="mtk1">Remarks</span><span class="mtk17">&lt;/</span><span class="mtk4">th</span><span class="mtk17">&gt;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1">    </span><span class="mtk17">&lt;/</span><span class="mtk4">tr</span><span class="mtk17">&gt;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1">   </span><span class="mtk17">&lt;/</span><span class="mtk4">thead</span><span class="mtk17">&gt;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1">   </span><span class="mtk17">&lt;</span><span class="mtk4">tbody</span><span class="mtk17">&gt;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1">    </span><span class="mtk4">{</span><span class="mtk12">students</span><span class="mtk1">.</span><span class="mtk11">map</span><span class="mtk1">(</span><span class="mtk12">student</span><span class="mtk1"> </span><span class="mtk4">=&gt;</span><span class="mtk1"> (</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1">     </span><span class="mtk17">&lt;</span><span class="mtk4">tr</span><span class="mtk1"> </span><span class="mtk12">key</span><span class="mtk1">=</span><span class="mtk4">{</span><span class="mtk12">student</span><span class="mtk1">.</span><span class="mtk12">id</span><span class="mtk4">}</span><span class="mtk17">&gt;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1">      </span><span class="mtk17">&lt;</span><span class="mtk4">td</span><span class="mtk17">&gt;</span><span class="mtk4">{</span><span class="mtk12">student</span><span class="mtk1">.</span><span class="mtk12">id</span><span class="mtk4">}</span><span class="mtk17">&lt;/</span><span class="mtk4">td</span><span class="mtk17">&gt;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1">      </span><span class="mtk17">&lt;</span><span class="mtk4">td</span><span class="mtk17">&gt;</span><span class="mtk4">{</span><span class="mtk12">student</span><span class="mtk1">.</span><span class="mtk12">name</span><span class="mtk4">}</span><span class="mtk17">&lt;/</span><span class="mtk4">td</span><span class="mtk17">&gt;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1">      </span><span class="mtk17">&lt;</span><span class="mtk4">td</span><span class="mtk17">&gt;</span><span class="mtk4">{</span><span class="mtk12">student</span><span class="mtk1">.</span><span class="mtk12">age</span><span class="mtk4">}</span><span class="mtk17">&lt;/</span><span class="mtk4">td</span><span class="mtk17">&gt;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1">      </span><span class="mtk17">&lt;</span><span class="mtk4">td</span><span class="mtk17">&gt;</span><span class="mtk4">{</span><span class="mtk12">student</span><span class="mtk1">.</span><span class="mtk12">course</span><span class="mtk4">}</span><span class="mtk17">&lt;/</span><span class="mtk4">td</span><span class="mtk17">&gt;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1">      </span><span class="mtk17">&lt;</span><span class="mtk4">td</span><span class="mtk17">&gt;</span><span class="mtk4">{</span><span class="mtk12">student</span><span class="mtk1">.</span><span class="mtk12">grade</span><span class="mtk4">}</span><span class="mtk17">&lt;/</span><span class="mtk4">td</span><span class="mtk17">&gt;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1">      </span><span class="mtk17">&lt;</span><span class="mtk4">td</span><span class="mtk17">&gt;</span><span class="mtk4">{</span><span class="mtk12">student</span><span class="mtk1">.</span><span class="mtk12">attendance</span><span class="mtk4">}</span><span class="mtk17">&lt;/</span><span class="mtk4">td</span><span class="mtk17">&gt;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1">      </span><span class="mtk17">&lt;</span><span class="mtk4">td</span><span class="mtk17">&gt;</span><span class="mtk4">{</span><span class="mtk12">student</span><span class="mtk1">.</span><span class="mtk12">status</span><span class="mtk4">}</span><span class="mtk17">&lt;/</span><span class="mtk4">td</span><span class="mtk17">&gt;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1">      </span><span class="mtk17">&lt;</span><span class="mtk4">td</span><span class="mtk17">&gt;</span><span class="mtk4">{</span><span class="mtk12">student</span><span class="mtk1">.</span><span class="mtk12">remarks</span><span class="mtk4">}</span><span class="mtk17">&lt;/</span><span class="mtk4">td</span><span class="mtk17">&gt;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1">     </span><span class="mtk17">&lt;/</span><span class="mtk4">tr</span><span class="mtk17">&gt;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1">    ))</span><span class="mtk4">}</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1">   </span><span class="mtk17">&lt;/</span><span class="mtk4">tbody</span><span class="mtk17">&gt;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1">  </span><span class="mtk17">&lt;/</span><span class="mtk4">table</span><span class="mtk17">&gt;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> );</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1">};</span></span></span> <span class="grvsc-line"><span class="grvsc-source"></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk15">export</span><span class="mtk1"> </span><span class="mtk15">default</span><span class="mtk1"> </span><span class="mtk12">TableComponent</span><span class="mtk1">;</span></span></span></code></pre> <p>In this code:</p> <ul> <li>We define a simple array of objects containing student data.</li> <li><code>TableComponent</code> outputs a table where we use <code>.map()</code> to create a row for each student.</li> </ul> <p>Let’s add some styling to make the table visually appealing:</p> <pre class="grvsc-container default-dark" data-language="css" data-index="1"><code class="grvsc-code"><span class="grvsc-line"><span class="grvsc-source"><span class="mtk6">table</span><span class="mtk1"> {</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">width</span><span class="mtk1">: </span><span class="mtk7">100%</span><span class="mtk1">;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">border-collapse</span><span class="mtk1">: </span><span class="mtk8">collapse</span><span class="mtk1">;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1">}</span></span></span> <span class="grvsc-line"><span class="grvsc-source"></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk6">th</span><span class="mtk1">,</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk6">td</span><span class="mtk1"> {</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">padding</span><span class="mtk1">: </span><span class="mtk7">8px</span><span class="mtk1">;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">text-align</span><span class="mtk1">: </span><span class="mtk8">left</span><span class="mtk1">;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">border-bottom</span><span class="mtk1">: </span><span class="mtk7">1px</span><span class="mtk1"> </span><span class="mtk8">solid</span><span class="mtk1"> </span><span class="mtk8">#ddd</span><span class="mtk1">;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1">}</span></span></span> <span class="grvsc-line"><span class="grvsc-source"></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk6">thead</span><span class="mtk1"> </span><span class="mtk6">th</span><span class="mtk1"> {</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">background-color</span><span class="mtk1">: </span><span class="mtk8">#f2f2f2</span><span class="mtk1">;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1">}</span></span></span> <span class="grvsc-line"><span class="grvsc-source"></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk6">tr:nth-child</span><span class="mtk1">(even) {</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">background-color</span><span class="mtk1">: </span><span class="mtk8">#f2f2f2</span><span class="mtk1">;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1">}</span></span></span></code></pre> <h3 id="step-2-enabling-scrolling" style="position:relative;"><a href="#step-2-enabling-scrolling" aria-label="step 2 enabling scrolling permalink" class="anchor before"><svg aria-hidden="true" focusable="false" height="16" version="1.1" viewBox="0 0 16 16" width="16"><path fill-rule="evenodd" d="M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z"></path></svg></a>Step 2: Enabling Scrolling</h3> <p>Since the <code>&#x3C;table></code> element itself does not support scrolling, we need to wrap the table in a <code>div</code> container that handles overflow.</p> <pre class="grvsc-container default-dark" data-language="jsx" data-index="2"><code class="grvsc-code"><span class="grvsc-line"><span class="grvsc-source"><span class="mtk17">&lt;</span><span class="mtk4">div</span><span class="mtk1"> </span><span class="mtk12">className</span><span class="mtk1">=</span><span class="mtk8">&quot;table-container&quot;</span><span class="mtk17">&gt;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk17">&lt;</span><span class="mtk4">table</span><span class="mtk17">&gt;</span><span class="mtk4">{</span><span class="mtk3">/* Table content */</span><span class="mtk4">}</span><span class="mtk17">&lt;/</span><span class="mtk4">table</span><span class="mtk17">&gt;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk17">&lt;/</span><span class="mtk4">div</span><span class="mtk17">&gt;</span></span></span></code></pre> <pre class="grvsc-container default-dark" data-language="css" data-index="3"><code class="grvsc-code"><span class="grvsc-line"><span class="grvsc-source"><span class="mtk6">.table-container</span><span class="mtk1"> {</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">max-height</span><span class="mtk1">: </span><span class="mtk7">200px</span><span class="mtk1">;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">max-width</span><span class="mtk1">: </span><span class="mtk7">500px</span><span class="mtk1">;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">overflow</span><span class="mtk1">: </span><span class="mtk8">auto</span><span class="mtk1">;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">border</span><span class="mtk1">: </span><span class="mtk7">1px</span><span class="mtk1"> </span><span class="mtk8">solid</span><span class="mtk1"> </span><span class="mtk8">#ddd</span><span class="mtk1">;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1">}</span></span></span> <span class="grvsc-line"><span class="grvsc-source"></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk6">th</span><span class="mtk1">,</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk6">td</span><span class="mtk1"> {</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> ...</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">white-space</span><span class="mtk1">: </span><span class="mtk8">nowrap</span><span class="mtk1">;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1">}</span></span></span></code></pre> <p>In this code:</p> <ul> <li>We wrap <code>TableComponent</code> inside a <code>&#x3C;div></code> with a style that sets a maximum height and width and enables scrolling (<code>overflow: auto</code>), allowing the table to scroll vertically and horizontally when the content exceeds the specified dimensions.</li> <li>We set <code>white-space: nowrap</code> on th and <code>td</code> elements to prevent text wrapping on smaller screens.</li> <li>We are adding a border around the scrolling div instead of the table to make the scrollbar appear as part of the table.</li> </ul> <p>Here is the basic scrollable table in action:</p> <div id="ScrollableTableComponent" data-code data-height="225px" data-width="500px" style="display:flex;justify-content: center;"></div> <h2 id="implementing-a-sticky-header" style="position:relative;"><a href="#implementing-a-sticky-header" aria-label="implementing a sticky header permalink" class="anchor before"><svg aria-hidden="true" focusable="false" height="16" version="1.1" viewBox="0 0 16 16" width="16"><path fill-rule="evenodd" d="M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z"></path></svg></a>Implementing a Sticky Header</h2> <p>With the basic scrollable table set up, we can work on the sticky headers by keeping them visible at the top of a table even when the user scrolls down through a long list.</p> <h3 id="using-css-position-sticky" style="position:relative;"><a href="#using-css-position-sticky" aria-label="using css position sticky permalink" class="anchor before"><svg aria-hidden="true" focusable="false" height="16" version="1.1" viewBox="0 0 16 16" width="16"><path fill-rule="evenodd" d="M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z"></path></svg></a>Using CSS position: sticky</h3> <p>The CSS <code>position: sticky</code> is a powerful feature that toggles between relative and fixed positioning based on the scroll position. It sticks to the top of the scrollable area when content scrolls under it, and it is supported in most modern browsers.</p> <p>To make the table header sticky, we need to add specific styles to the <code>&#x3C;thead></code> element’s cells.</p> <pre class="grvsc-container default-dark" data-language="css" data-index="4"><code class="grvsc-code"><span class="grvsc-line"><span class="grvsc-source"><span class="mtk6">thead</span><span class="mtk1"> </span><span class="mtk6">th</span><span class="mtk1"> {</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">background-color</span><span class="mtk1">: </span><span class="mtk8">#f2f2f2</span><span class="mtk1">;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">position</span><span class="mtk1">: </span><span class="mtk8">sticky</span><span class="mtk1">;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">top</span><span class="mtk1">: </span><span class="mtk7">0</span><span class="mtk1">;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">z-index</span><span class="mtk1">: </span><span class="mtk7">1</span><span class="mtk1">;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1">}</span></span></span></code></pre> <p>In this code:</p> <ul> <li>We set the position of the <code>&#x3C;th></code> elements inside the <code>&#x3C;thead></code> to sticky.</li> <li>The <code>top: 0</code> property ensures that the header sticks to the top of the scrollable area.</li> <li>The <code>z-index: 1</code> property ensures the header remains above the table content.</li> </ul> <div id="StickyHeaderComponent" data-code data-height="225px" data-width="500px" style="display:flex;justify-content: center;"></div> <h2 id="implementing-a-sticky-column" style="position:relative;"><a href="#implementing-a-sticky-column" aria-label="implementing a sticky column permalink" class="anchor before"><svg aria-hidden="true" focusable="false" height="16" version="1.1" viewBox="0 0 16 16" width="16"><path fill-rule="evenodd" d="M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z"></path></svg></a>Implementing a Sticky Column</h2> <p>As sticky headers provide a constant visual reference for the data rows, sticky columns are equally beneficial when navigating through wide tables requiring horizontal scrolling.</p> <p>Implementing sticky columns involves a similar approach to sticky headers but targets horizontal positioning.</p> <p>Let’s modify the existing styles to include sticky columns. We’ll start with making the first column sticky:</p> <pre class="grvsc-container default-dark" data-language="css" data-index="5"><code class="grvsc-code"><span class="grvsc-line"><span class="grvsc-source"><span class="mtk6">th:first-child</span><span class="mtk1">,</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk6">td:first-child</span><span class="mtk1"> {</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">position</span><span class="mtk1">: </span><span class="mtk8">sticky</span><span class="mtk1">;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">left</span><span class="mtk1">: </span><span class="mtk7">0</span><span class="mtk1">;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">z-index</span><span class="mtk1">: </span><span class="mtk7">2</span><span class="mtk1">;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">background-color</span><span class="mtk1">: </span><span class="mtk8">#f2f2f2</span><span class="mtk1">;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1">}</span></span></span> <span class="grvsc-line"><span class="grvsc-source"></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk6">th:first-child</span><span class="mtk1"> {</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">z-index</span><span class="mtk1">: </span><span class="mtk7">3</span><span class="mtk1">;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1">}</span></span></span></code></pre> <p>In this code:</p> <ul> <li>We target the first <code>&#x3C;th></code> and <code>&#x3C;td></code> elements in the table.</li> <li>We set the position of the first column to <code>sticky</code>.</li> <li>The <code>left: 0</code> property ensures that the first column sticks to the left side of the scrollable area.</li> <li>The <code>z-index</code> property ensures that the first column remains above the header row.</li> </ul> <div id="StickyHeaderColumnComponent" data-code data-height="225px" data-width="500px" style="display:flex;justify-content: center;"></div> <p>To make multiple columns sticky, we can adjust the left value of each subsequent column, accounting for the width of the preceding columns. This requires calculating or setting fixed widths for these columns:</p> <pre class="grvsc-container default-dark" data-language="css" data-index="6"><code class="grvsc-code"><span class="grvsc-line"><span class="grvsc-source"><span class="mtk6">th:first-child</span><span class="mtk1">,</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk6">td:first-child</span><span class="mtk1"> {</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">position</span><span class="mtk1">: </span><span class="mtk8">sticky</span><span class="mtk1">;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">left</span><span class="mtk1">: </span><span class="mtk7">0</span><span class="mtk1">;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">z-index</span><span class="mtk1">: </span><span class="mtk7">2</span><span class="mtk1">;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">background-color</span><span class="mtk1">: </span><span class="mtk8">#f2f2f2</span><span class="mtk1">;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1">}</span></span></span> <span class="grvsc-line"><span class="grvsc-source"></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk6">th:nth-child</span><span class="mtk1">(</span><span class="mtk7">2</span><span class="mtk1">),</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk6">td:nth-child</span><span class="mtk1">(</span><span class="mtk7">2</span><span class="mtk1">) {</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">position</span><span class="mtk1">: </span><span class="mtk8">sticky</span><span class="mtk1">;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">left</span><span class="mtk1">: </span><span class="mtk7">32px</span><span class="mtk1">; </span><span class="mtk3">/* Adjust based on the width of the first column */</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">z-index</span><span class="mtk1">: </span><span class="mtk7">2</span><span class="mtk1">;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">background-color</span><span class="mtk1">: </span><span class="mtk8">#f2f2f2</span><span class="mtk1">;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1">}</span></span></span> <span class="grvsc-line"><span class="grvsc-source"></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk6">th:first-child</span><span class="mtk1">,</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk6">th:nth-child</span><span class="mtk1">(</span><span class="mtk7">2</span><span class="mtk1">) {</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">z-index</span><span class="mtk1">: </span><span class="mtk7">3</span><span class="mtk1">;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1">}</span></span></span> <span class="grvsc-line"><span class="grvsc-source"></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk3">/* Repeat for additional columns */</span></span></span></code></pre> <p>Below is the complete code with a live demo:</p> <pre class="grvsc-container default-dark" data-language="jsx" data-index="7"><code class="grvsc-code"><span class="grvsc-line"><span class="grvsc-source"><span class="mtk15">import</span><span class="mtk1"> </span><span class="mtk8">&quot;./App.css&quot;</span><span class="mtk1">;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk4">const</span><span class="mtk1"> </span><span class="mtk12">students</span><span class="mtk1"> = [</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> {</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1">  </span><span class="mtk12">id:</span><span class="mtk1"> </span><span class="mtk7">1</span><span class="mtk1">,</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1">  </span><span class="mtk12">name:</span><span class="mtk1"> </span><span class="mtk8">&quot;John Doe&quot;</span><span class="mtk1">,</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1">  </span><span class="mtk12">age:</span><span class="mtk1"> </span><span class="mtk7">20</span><span class="mtk1">,</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1">  </span><span class="mtk12">course:</span><span class="mtk1"> </span><span class="mtk8">&quot;Business&quot;</span><span class="mtk1">,</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1">  </span><span class="mtk12">grade:</span><span class="mtk1"> </span><span class="mtk8">&quot;A&quot;</span><span class="mtk1">,</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1">  </span><span class="mtk12">attendance:</span><span class="mtk1"> </span><span class="mtk8">&quot;Present&quot;</span><span class="mtk1">,</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1">  </span><span class="mtk12">status:</span><span class="mtk1"> </span><span class="mtk8">&quot;Active&quot;</span><span class="mtk1">,</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1">  </span><span class="mtk12">remarks:</span><span class="mtk1"> </span><span class="mtk8">&quot;Good&quot;</span><span class="mtk1">,</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> },</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> {</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1">  </span><span class="mtk12">id:</span><span class="mtk1"> </span><span class="mtk7">2</span><span class="mtk1">,</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1">  </span><span class="mtk12">name:</span><span class="mtk1"> </span><span class="mtk8">&quot;Jane Smith&quot;</span><span class="mtk1">,</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1">  </span><span class="mtk12">age:</span><span class="mtk1"> </span><span class="mtk7">22</span><span class="mtk1">,</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1">  </span><span class="mtk12">course:</span><span class="mtk1"> </span><span class="mtk8">&quot;Engineering&quot;</span><span class="mtk1">,</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1">  </span><span class="mtk12">grade:</span><span class="mtk1"> </span><span class="mtk8">&quot;B&quot;</span><span class="mtk1">,</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1">  </span><span class="mtk12">attendance:</span><span class="mtk1"> </span><span class="mtk8">&quot;Absent&quot;</span><span class="mtk1">,</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1">  </span><span class="mtk12">status:</span><span class="mtk1"> </span><span class="mtk8">&quot;Inactive&quot;</span><span class="mtk1">,</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1">  </span><span class="mtk12">remarks:</span><span class="mtk1"> </span><span class="mtk8">&quot;Average&quot;</span><span class="mtk1">,</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> },</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> {</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1">  </span><span class="mtk12">id:</span><span class="mtk1"> </span><span class="mtk7">3</span><span class="mtk1">,</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1">  </span><span class="mtk12">name:</span><span class="mtk1"> </span><span class="mtk8">&quot;Alice Johnson&quot;</span><span class="mtk1">,</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1">  </span><span class="mtk12">age:</span><span class="mtk1"> </span><span class="mtk7">21</span><span class="mtk1">,</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1">  </span><span class="mtk12">course:</span><span class="mtk1"> </span><span class="mtk8">&quot;Medicine&quot;</span><span class="mtk1">,</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1">  </span><span class="mtk12">grade:</span><span class="mtk1"> </span><span class="mtk8">&quot;A+&quot;</span><span class="mtk1">,</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1">  </span><span class="mtk12">attendance:</span><span class="mtk1"> </span><span class="mtk8">&quot;Present&quot;</span><span class="mtk1">,</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1">  </span><span class="mtk12">status:</span><span class="mtk1"> </span><span class="mtk8">&quot;Active&quot;</span><span class="mtk1">,</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1">  </span><span class="mtk12">remarks:</span><span class="mtk1"> </span><span class="mtk8">&quot;Excellent&quot;</span><span class="mtk1">,</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> },</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> {</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1">  </span><span class="mtk12">id:</span><span class="mtk1"> </span><span class="mtk7">4</span><span class="mtk1">,</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1">  </span><span class="mtk12">name:</span><span class="mtk1"> </span><span class="mtk8">&quot;Bob Brown&quot;</span><span class="mtk1">,</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1">  </span><span class="mtk12">age:</span><span class="mtk1"> </span><span class="mtk7">23</span><span class="mtk1">,</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1">  </span><span class="mtk12">course:</span><span class="mtk1"> </span><span class="mtk8">&quot;Computer Science&quot;</span><span class="mtk1">,</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1">  </span><span class="mtk12">grade:</span><span class="mtk1"> </span><span class="mtk8">&quot;C&quot;</span><span class="mtk1">,</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1">  </span><span class="mtk12">attendance:</span><span class="mtk1"> </span><span class="mtk8">&quot;Present&quot;</span><span class="mtk1">,</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1">  </span><span class="mtk12">status:</span><span class="mtk1"> </span><span class="mtk8">&quot;Active&quot;</span><span class="mtk1">,</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1">  </span><span class="mtk12">remarks:</span><span class="mtk1"> </span><span class="mtk8">&quot;Fair&quot;</span><span class="mtk1">,</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> },</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> {</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1">  </span><span class="mtk12">id:</span><span class="mtk1"> </span><span class="mtk7">5</span><span class="mtk1">,</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1">  </span><span class="mtk12">name:</span><span class="mtk1"> </span><span class="mtk8">&quot;Eve Wilson&quot;</span><span class="mtk1">,</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1">  </span><span class="mtk12">age:</span><span class="mtk1"> </span><span class="mtk7">24</span><span class="mtk1">,</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1">  </span><span class="mtk12">course:</span><span class="mtk1"> </span><span class="mtk8">&quot;Arts&quot;</span><span class="mtk1">,</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1">  </span><span class="mtk12">grade:</span><span class="mtk1"> </span><span class="mtk8">&quot;B+&quot;</span><span class="mtk1">,</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1">  </span><span class="mtk12">attendance:</span><span class="mtk1"> </span><span class="mtk8">&quot;Absent&quot;</span><span class="mtk1">,</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1">  </span><span class="mtk12">status:</span><span class="mtk1"> </span><span class="mtk8">&quot;Inactive&quot;</span><span class="mtk1">,</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1">  </span><span class="mtk12">remarks:</span><span class="mtk1"> </span><span class="mtk8">&quot;Good&quot;</span><span class="mtk1">,</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> },</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> {</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1">  </span><span class="mtk12">id:</span><span class="mtk1"> </span><span class="mtk7">6</span><span class="mtk1">,</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1">  </span><span class="mtk12">name:</span><span class="mtk1"> </span><span class="mtk8">&quot;David Lee&quot;</span><span class="mtk1">,</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1">  </span><span class="mtk12">age:</span><span class="mtk1"> </span><span class="mtk7">25</span><span class="mtk1">,</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1">  </span><span class="mtk12">course:</span><span class="mtk1"> </span><span class="mtk8">&quot;Law&quot;</span><span class="mtk1">,</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1">  </span><span class="mtk12">grade:</span><span class="mtk1"> </span><span class="mtk8">&quot;A-&quot;</span><span class="mtk1">,</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1">  </span><span class="mtk12">attendance:</span><span class="mtk1"> </span><span class="mtk8">&quot;Present&quot;</span><span class="mtk1">,</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1">  </span><span class="mtk12">status:</span><span class="mtk1"> </span><span class="mtk8">&quot;Active&quot;</span><span class="mtk1">,</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1">  </span><span class="mtk12">remarks:</span><span class="mtk1"> </span><span class="mtk8">&quot;Very Good&quot;</span><span class="mtk1">,</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> },</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> {</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1">  </span><span class="mtk12">id:</span><span class="mtk1"> </span><span class="mtk7">7</span><span class="mtk1">,</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1">  </span><span class="mtk12">name:</span><span class="mtk1"> </span><span class="mtk8">&quot;Grace Clark&quot;</span><span class="mtk1">,</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1">  </span><span class="mtk12">age:</span><span class="mtk1"> </span><span class="mtk7">26</span><span class="mtk1">,</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1">  </span><span class="mtk12">course:</span><span class="mtk1"> </span><span class="mtk8">&quot;Science&quot;</span><span class="mtk1">,</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1">  </span><span class="mtk12">grade:</span><span class="mtk1"> </span><span class="mtk8">&quot;D&quot;</span><span class="mtk1">,</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1">  </span><span class="mtk12">attendance:</span><span class="mtk1"> </span><span class="mtk8">&quot;Absent&quot;</span><span class="mtk1">,</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1">  </span><span class="mtk12">status:</span><span class="mtk1"> </span><span class="mtk8">&quot;Inactive&quot;</span><span class="mtk1">,</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1">  </span><span class="mtk12">remarks:</span><span class="mtk1"> </span><span class="mtk8">&quot;Poor&quot;</span><span class="mtk1">,</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> },</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1">];</span></span></span> <span class="grvsc-line"><span class="grvsc-source"></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk4">const</span><span class="mtk1"> </span><span class="mtk11">TableComponent</span><span class="mtk1"> = () </span><span class="mtk4">=&gt;</span><span class="mtk1"> {</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk15">return</span><span class="mtk1"> (</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1">  </span><span class="mtk17">&lt;</span><span class="mtk4">div</span><span class="mtk1"> </span><span class="mtk12">className</span><span class="mtk1">=</span><span class="mtk8">&quot;table-container&quot;</span><span class="mtk17">&gt;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1">   </span><span class="mtk17">&lt;</span><span class="mtk4">table</span><span class="mtk17">&gt;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1">    </span><span class="mtk17">&lt;</span><span class="mtk4">thead</span><span class="mtk17">&gt;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1">     </span><span class="mtk17">&lt;</span><span class="mtk4">tr</span><span class="mtk17">&gt;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1">      </span><span class="mtk17">&lt;</span><span class="mtk4">th</span><span class="mtk17">&gt;</span><span class="mtk1">ID</span><span class="mtk17">&lt;/</span><span class="mtk4">th</span><span class="mtk17">&gt;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1">      </span><span class="mtk17">&lt;</span><span class="mtk4">th</span><span class="mtk17">&gt;</span><span class="mtk1">Name</span><span class="mtk17">&lt;/</span><span class="mtk4">th</span><span class="mtk17">&gt;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1">      </span><span class="mtk17">&lt;</span><span class="mtk4">th</span><span class="mtk17">&gt;</span><span class="mtk1">Age</span><span class="mtk17">&lt;/</span><span class="mtk4">th</span><span class="mtk17">&gt;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1">      </span><span class="mtk17">&lt;</span><span class="mtk4">th</span><span class="mtk17">&gt;</span><span class="mtk1">Course</span><span class="mtk17">&lt;/</span><span class="mtk4">th</span><span class="mtk17">&gt;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1">      </span><span class="mtk17">&lt;</span><span class="mtk4">th</span><span class="mtk17">&gt;</span><span class="mtk1">Grade</span><span class="mtk17">&lt;/</span><span class="mtk4">th</span><span class="mtk17">&gt;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1">      </span><span class="mtk17">&lt;</span><span class="mtk4">th</span><span class="mtk17">&gt;</span><span class="mtk1">Attendance</span><span class="mtk17">&lt;/</span><span class="mtk4">th</span><span class="mtk17">&gt;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1">      </span><span class="mtk17">&lt;</span><span class="mtk4">th</span><span class="mtk17">&gt;</span><span class="mtk1">Status</span><span class="mtk17">&lt;/</span><span class="mtk4">th</span><span class="mtk17">&gt;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1">      </span><span class="mtk17">&lt;</span><span class="mtk4">th</span><span class="mtk17">&gt;</span><span class="mtk1">Remarks</span><span class="mtk17">&lt;/</span><span class="mtk4">th</span><span class="mtk17">&gt;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1">     </span><span class="mtk17">&lt;/</span><span class="mtk4">tr</span><span class="mtk17">&gt;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1">    </span><span class="mtk17">&lt;/</span><span class="mtk4">thead</span><span class="mtk17">&gt;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1">    </span><span class="mtk17">&lt;</span><span class="mtk4">tbody</span><span class="mtk17">&gt;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1">     </span><span class="mtk4">{</span><span class="mtk12">students</span><span class="mtk1">.</span><span class="mtk11">map</span><span class="mtk1">(</span><span class="mtk12">student</span><span class="mtk1"> </span><span class="mtk4">=&gt;</span><span class="mtk1"> (</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1">      </span><span class="mtk17">&lt;</span><span class="mtk4">tr</span><span class="mtk1"> </span><span class="mtk12">key</span><span class="mtk1">=</span><span class="mtk4">{</span><span class="mtk12">student</span><span class="mtk1">.</span><span class="mtk12">id</span><span class="mtk4">}</span><span class="mtk17">&gt;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1">       </span><span class="mtk17">&lt;</span><span class="mtk4">td</span><span class="mtk17">&gt;</span><span class="mtk4">{</span><span class="mtk12">student</span><span class="mtk1">.</span><span class="mtk12">id</span><span class="mtk4">}</span><span class="mtk17">&lt;/</span><span class="mtk4">td</span><span class="mtk17">&gt;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1">       </span><span class="mtk17">&lt;</span><span class="mtk4">td</span><span class="mtk17">&gt;</span><span class="mtk4">{</span><span class="mtk12">student</span><span class="mtk1">.</span><span class="mtk12">name</span><span class="mtk4">}</span><span class="mtk17">&lt;/</span><span class="mtk4">td</span><span class="mtk17">&gt;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1">       </span><span class="mtk17">&lt;</span><span class="mtk4">td</span><span class="mtk17">&gt;</span><span class="mtk4">{</span><span class="mtk12">student</span><span class="mtk1">.</span><span class="mtk12">age</span><span class="mtk4">}</span><span class="mtk17">&lt;/</span><span class="mtk4">td</span><span class="mtk17">&gt;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1">       </span><span class="mtk17">&lt;</span><span class="mtk4">td</span><span class="mtk17">&gt;</span><span class="mtk4">{</span><span class="mtk12">student</span><span class="mtk1">.</span><span class="mtk12">course</span><span class="mtk4">}</span><span class="mtk17">&lt;/</span><span class="mtk4">td</span><span class="mtk17">&gt;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1">       </span><span class="mtk17">&lt;</span><span class="mtk4">td</span><span class="mtk17">&gt;</span><span class="mtk4">{</span><span class="mtk12">student</span><span class="mtk1">.</span><span class="mtk12">grade</span><span class="mtk4">}</span><span class="mtk17">&lt;/</span><span class="mtk4">td</span><span class="mtk17">&gt;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1">       </span><span class="mtk17">&lt;</span><span class="mtk4">td</span><span class="mtk17">&gt;</span><span class="mtk4">{</span><span class="mtk12">student</span><span class="mtk1">.</span><span class="mtk12">attendance</span><span class="mtk4">}</span><span class="mtk17">&lt;/</span><span class="mtk4">td</span><span class="mtk17">&gt;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1">       </span><span class="mtk17">&lt;</span><span class="mtk4">td</span><span class="mtk17">&gt;</span><span class="mtk4">{</span><span class="mtk12">student</span><span class="mtk1">.</span><span class="mtk12">status</span><span class="mtk4">}</span><span class="mtk17">&lt;/</span><span class="mtk4">td</span><span class="mtk17">&gt;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1">       </span><span class="mtk17">&lt;</span><span class="mtk4">td</span><span class="mtk17">&gt;</span><span class="mtk4">{</span><span class="mtk12">student</span><span class="mtk1">.</span><span class="mtk12">remarks</span><span class="mtk4">}</span><span class="mtk17">&lt;/</span><span class="mtk4">td</span><span class="mtk17">&gt;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1">      </span><span class="mtk17">&lt;/</span><span class="mtk4">tr</span><span class="mtk17">&gt;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1">     ))</span><span class="mtk4">}</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1">    </span><span class="mtk17">&lt;/</span><span class="mtk4">tbody</span><span class="mtk17">&gt;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1">   </span><span class="mtk17">&lt;/</span><span class="mtk4">table</span><span class="mtk17">&gt;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1">  </span><span class="mtk17">&lt;/</span><span class="mtk4">div</span><span class="mtk17">&gt;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> );</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1">};</span></span></span> <span class="grvsc-line"><span class="grvsc-source"></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk15">export</span><span class="mtk1"> </span><span class="mtk15">default</span><span class="mtk1"> </span><span class="mtk12">TableComponent</span><span class="mtk1">;</span></span></span></code></pre> <pre class="grvsc-container default-dark" data-language="css" data-index="8"><code class="grvsc-code"><span class="grvsc-line"><span class="grvsc-source"><span class="mtk6">.table-container</span><span class="mtk1"> {</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">max-height</span><span class="mtk1">: </span><span class="mtk7">200px</span><span class="mtk1">;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">max-width</span><span class="mtk1">: </span><span class="mtk7">500px</span><span class="mtk1">;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">overflow</span><span class="mtk1">: </span><span class="mtk8">auto</span><span class="mtk1">;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">border</span><span class="mtk1">: </span><span class="mtk7">1px</span><span class="mtk1"> </span><span class="mtk8">solid</span><span class="mtk1"> </span><span class="mtk8">#ddd</span><span class="mtk1">;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1">}</span></span></span> <span class="grvsc-line"><span class="grvsc-source"></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk6">table</span><span class="mtk1"> {</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">width</span><span class="mtk1">: </span><span class="mtk7">100%</span><span class="mtk1">;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">border-collapse</span><span class="mtk1">: </span><span class="mtk8">collapse</span><span class="mtk1">;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">font-family</span><span class="mtk1">: </span><span class="mtk8">Arial</span><span class="mtk1">, </span><span class="mtk8">sans-serif</span><span class="mtk1">;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1">}</span></span></span> <span class="grvsc-line"><span class="grvsc-source"></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk6">th</span><span class="mtk1">,</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk6">td</span><span class="mtk1"> {</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">padding</span><span class="mtk1">: </span><span class="mtk7">8px</span><span class="mtk1">;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">text-align</span><span class="mtk1">: </span><span class="mtk8">left</span><span class="mtk1">;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">border-bottom</span><span class="mtk1">: </span><span class="mtk7">1px</span><span class="mtk1"> </span><span class="mtk8">solid</span><span class="mtk1"> </span><span class="mtk8">#ddd</span><span class="mtk1">;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">white-space</span><span class="mtk1">: </span><span class="mtk8">nowrap</span><span class="mtk1">;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1">}</span></span></span> <span class="grvsc-line"><span class="grvsc-source"></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk6">thead</span><span class="mtk1"> </span><span class="mtk6">th</span><span class="mtk1"> {</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">background-color</span><span class="mtk1">: </span><span class="mtk8">#f2f2f2</span><span class="mtk1">;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">position</span><span class="mtk1">: </span><span class="mtk8">sticky</span><span class="mtk1">;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">top</span><span class="mtk1">: </span><span class="mtk7">0</span><span class="mtk1">;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">z-index</span><span class="mtk1">: </span><span class="mtk7">1</span><span class="mtk1">;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1">}</span></span></span> <span class="grvsc-line"><span class="grvsc-source"></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk6">tr:nth-child</span><span class="mtk1">(even) {</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">background-color</span><span class="mtk1">: </span><span class="mtk8">#f2f2f2</span><span class="mtk1">;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1">}</span></span></span> <span class="grvsc-line"><span class="grvsc-source"></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk6">th:first-child</span><span class="mtk1">,</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk6">td:first-child</span><span class="mtk1"> {</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">position</span><span class="mtk1">: </span><span class="mtk8">sticky</span><span class="mtk1">;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">left</span><span class="mtk1">: </span><span class="mtk7">0</span><span class="mtk1">;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">z-index</span><span class="mtk1">: </span><span class="mtk7">2</span><span class="mtk1">;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">background-color</span><span class="mtk1">: </span><span class="mtk8">#f2f2f2</span><span class="mtk1">;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1">}</span></span></span> <span class="grvsc-line"><span class="grvsc-source"></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk6">th:nth-child</span><span class="mtk1">(</span><span class="mtk7">2</span><span class="mtk1">),</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk6">td:nth-child</span><span class="mtk1">(</span><span class="mtk7">2</span><span class="mtk1">) {</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">position</span><span class="mtk1">: </span><span class="mtk8">sticky</span><span class="mtk1">;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">left</span><span class="mtk1">: </span><span class="mtk7">32px</span><span class="mtk1">; </span><span class="mtk3">/* Adjust based on the width of the first column */</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">z-index</span><span class="mtk1">: </span><span class="mtk7">2</span><span class="mtk1">;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">background-color</span><span class="mtk1">: </span><span class="mtk8">#f2f2f2</span><span class="mtk1">;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1">}</span></span></span> <span class="grvsc-line"><span class="grvsc-source"></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk6">th:first-child</span><span class="mtk1">,</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk6">th:nth-child</span><span class="mtk1">(</span><span class="mtk7">2</span><span class="mtk1">) {</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">z-index</span><span class="mtk1">: </span><span class="mtk7">3</span><span class="mtk1">;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1">}</span></span></span> <span class="grvsc-line"><span class="grvsc-source"></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk3">/* Repeat for additional columns */</span></span></span></code></pre> <div id="StickyHeaderColumnsComponent" data-code data-height="225px" data-width="500px" style="display:flex;justify-content: center;"></div> <h2 id="conclusion" style="position:relative;"><a href="#conclusion" aria-label="conclusion permalink" class="anchor before"><svg aria-hidden="true" focusable="false" height="16" version="1.1" viewBox="0 0 16 16" width="16"><path fill-rule="evenodd" d="M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z"></path></svg></a>Conclusion</h2> <p>In this tutorial, we learned how to create a scrollable table with sticky headers and columns in React. By combining CSS <code>position: sticky</code> with specific <code>z-index</code> values, we achieved a fixed header and column effect that enhances the user experience when navigating through large datasets.</p> <p>Bye for now, and happy coding!</p> <style class="grvsc-styles"> .grvsc-container { overflow: auto; position: relative; -webkit-overflow-scrolling: touch; padding-top: 1rem; padding-top: var(--grvsc-padding-top, var(--grvsc-padding-v, 1rem)); padding-bottom: 1rem; padding-bottom: var(--grvsc-padding-bottom, var(--grvsc-padding-v, 1rem)); border-radius: 8px; border-radius: var(--grvsc-border-radius, 8px); font-feature-settings: normal; line-height: 1.4; } .grvsc-code { display: table; } .grvsc-line { display: table-row; box-sizing: border-box; width: 100%; position: relative; } .grvsc-line > * { position: relative; } .grvsc-gutter-pad { display: table-cell; padding-left: 0.75rem; padding-left: calc(var(--grvsc-padding-left, var(--grvsc-padding-h, 1.5rem)) / 2); } .grvsc-gutter { display: table-cell; -webkit-user-select: none; -moz-user-select: none; user-select: none; } .grvsc-gutter::before { content: attr(data-content); } .grvsc-source { display: table-cell; padding-left: 1.5rem; padding-left: var(--grvsc-padding-left, var(--grvsc-padding-h, 1.5rem)); padding-right: 1.5rem; padding-right: var(--grvsc-padding-right, var(--grvsc-padding-h, 1.5rem)); } .grvsc-source:empty::after { content: ' '; -webkit-user-select: none; -moz-user-select: none; user-select: none; } .grvsc-gutter + .grvsc-source { padding-left: 0.75rem; padding-left: calc(var(--grvsc-padding-left, var(--grvsc-padding-h, 1.5rem)) / 2); } /* Line transformer styles */ .grvsc-has-line-highlighting > .grvsc-code > .grvsc-line::before { content: ' '; position: absolute; width: 100%; } .grvsc-line-diff-add::before { background-color: var(--grvsc-line-diff-add-background-color, rgba(0, 255, 60, 0.2)); } .grvsc-line-diff-del::before { background-color: var(--grvsc-line-diff-del-background-color, rgba(255, 0, 20, 0.2)); } .grvsc-line-number { padding: 0 2px; text-align: right; opacity: 0.7; } .default-dark { background-color: #1E1E1E; color: #D4D4D4; } .default-dark .mtk15 { color: #C586C0; } .default-dark .mtk1 { color: #D4D4D4; } .default-dark .mtk8 { color: #CE9178; } .default-dark .mtk4 { color: #569CD6; } .default-dark .mtk12 { color: #9CDCFE; } .default-dark .mtk7 { color: #B5CEA8; } .default-dark .mtk11 { color: #DCDCAA; } .default-dark .mtk17 { color: #808080; } .default-dark .mtk6 { color: #D7BA7D; } .default-dark .mtk3 { color: #6A9955; } .default-dark .grvsc-line-highlighted::before { background-color: var(--grvsc-line-highlighted-background-color, rgba(255, 255, 255, 0.1)); box-shadow: inset var(--grvsc-line-highlighted-border-width, 4px) 0 0 0 var(--grvsc-line-highlighted-border-color, rgba(255, 255, 255, 0.5)); } </style><![CDATA[MUI Grid: Building Web Layouts Responsively]]>https://muhimasri.commui-gridhttps://muhimasri.commui-grid<p>MUI Grid is an essential component for creating flexible and responsive layouts. The core mechanism of the Grid component is based on the 12-column grid system, which allows developers to create complex layouts that adapt to different screen sizes.</p> <p>Throughout this tutorial, we’ll explore the fundamentals of the MUI Grid component and learn how to construct a simple and more complex responsive page layout.</p> <h2 id="understanding-the-12-grid-system" style="position:relative;"><a href="#understanding-the-12-grid-system" aria-label="understanding the 12 grid system permalink" class="anchor before"><svg aria-hidden="true" focusable="false" height="16" version="1.1" viewBox="0 0 16 16" width="16"><path fill-rule="evenodd" d="M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z"></path></svg></a>Understanding the 12-Grid System</h2> <p>The choice of 12 as the base number for this grid system isn’t arbitrary. It’s selected for its high divisibility, allowing for a wide range of layout patterns that can quickly adapt to different screen sizes.</p> <p>It’s important to clarify that when we refer to the 12-grid system, we’re not talking about a literal measurement in units of 12, 11, 10, etc. Instead, it’s a method of dividing the screen into column blocks, facilitating the arrangement and sizing of layout elements.</p> <p><strong>12 Grids Equal 100%:</strong> The entire screen width is considered as 100%, represented by 12 grids, allowing for a straightforward calculation of percentage widths.</p> <p><strong>Dividing the Grid:</strong> Divisions of the 12 grids provide flexibility in responsive layout design. For instance:</p> <ul> <li>6 grids represent 50% of the screen width.</li> <li>4 grids are equivalent to one-third (approximately 33.33%).</li> <li>3 grids equate to one-quarter (25%).</li> </ul> <h2 id="basic-usage-of-mui-grid" style="position:relative;"><a href="#basic-usage-of-mui-grid" aria-label="basic usage of mui grid permalink" class="anchor before"><svg aria-hidden="true" focusable="false" height="16" version="1.1" viewBox="0 0 16 16" width="16"><path fill-rule="evenodd" d="M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z"></path></svg></a>Basic Usage of MUI Grid</h2> <p>The Grid component leverages CSS Flexbox to create layouts at its core, automatically treating its children as flex items. It simplifies the process of creating responsive designs, abstracting much of the complexity behind intuitive props.</p> <p>Here’s a basic example of creating a layout with a sidenav that takes up 3 out of 12 columns and a body content section that occupies the remaining 9 columns. This setup uses the <code>xs</code> breakpoint to apply the same layout across all screen sizes.</p> <pre class="grvsc-container default-dark" data-language="jsx" data-index="0"><code class="grvsc-code"><span class="grvsc-line"><span class="grvsc-source"><span class="mtk15">import</span><span class="mtk1"> </span><span class="mtk12">React</span><span class="mtk1"> </span><span class="mtk15">from</span><span class="mtk1"> </span><span class="mtk8">&quot;react&quot;</span><span class="mtk1">;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk15">import</span><span class="mtk1"> </span><span class="mtk12">Grid</span><span class="mtk1"> </span><span class="mtk15">from</span><span class="mtk1"> </span><span class="mtk8">&quot;@mui/material/Grid&quot;</span><span class="mtk1">;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk15">import</span><span class="mtk1"> </span><span class="mtk12">Paper</span><span class="mtk1"> </span><span class="mtk15">from</span><span class="mtk1"> </span><span class="mtk8">&quot;@mui/material/Paper&quot;</span><span class="mtk1">;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk4">const</span><span class="mtk1"> </span><span class="mtk11">SimpleLayout</span><span class="mtk1"> = () </span><span class="mtk4">=&gt;</span><span class="mtk1"> {</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk15">return</span><span class="mtk1"> (</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk17">&lt;</span><span class="mtk10">Grid</span><span class="mtk1"> </span><span class="mtk12">container</span><span class="mtk1"> </span><span class="mtk12">spacing</span><span class="mtk1">=</span><span class="mtk4">{</span><span class="mtk7">2</span><span class="mtk4">}</span><span class="mtk17">&gt;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk17">&lt;</span><span class="mtk10">Grid</span><span class="mtk1"> </span><span class="mtk12">item</span><span class="mtk1"> </span><span class="mtk12">xs</span><span class="mtk1">=</span><span class="mtk4">{</span><span class="mtk7">3</span><span class="mtk4">}</span><span class="mtk17">&gt;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk17">&lt;</span><span class="mtk10">Paper</span><span class="mtk1"> </span><span class="mtk12">sx</span><span class="mtk1">=</span><span class="mtk4">{</span><span class="mtk1">{ </span><span class="mtk12">p:</span><span class="mtk1"> </span><span class="mtk7">2</span><span class="mtk1"> }</span><span class="mtk4">}</span><span class="mtk17">&gt;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk4">{</span><span class="mtk3">/* Left nav content goes here */</span><span class="mtk4">}</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> Side Nav</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk17">&lt;/</span><span class="mtk10">Paper</span><span class="mtk17">&gt;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk17">&lt;/</span><span class="mtk10">Grid</span><span class="mtk17">&gt;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk17">&lt;</span><span class="mtk10">Grid</span><span class="mtk1"> </span><span class="mtk12">item</span><span class="mtk1"> </span><span class="mtk12">xs</span><span class="mtk1">=</span><span class="mtk4">{</span><span class="mtk7">9</span><span class="mtk4">}</span><span class="mtk17">&gt;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk17">&lt;</span><span class="mtk10">Paper</span><span class="mtk1"> </span><span class="mtk12">sx</span><span class="mtk1">=</span><span class="mtk4">{</span><span class="mtk1">{ </span><span class="mtk12">p:</span><span class="mtk1"> </span><span class="mtk7">2</span><span class="mtk1"> }</span><span class="mtk4">}</span><span class="mtk17">&gt;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk4">{</span><span class="mtk3">/* Body content goes here */</span><span class="mtk4">}</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> Body Content</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk17">&lt;/</span><span class="mtk10">Paper</span><span class="mtk17">&gt;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk17">&lt;/</span><span class="mtk10">Grid</span><span class="mtk17">&gt;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk17">&lt;/</span><span class="mtk10">Grid</span><span class="mtk17">&gt;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> );</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1">};</span></span></span> <span class="grvsc-line"><span class="grvsc-source"></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk15">export</span><span class="mtk1"> </span><span class="mtk15">default</span><span class="mtk1"> </span><span class="mtk12">SimpleLayout</span><span class="mtk1">;</span></span></span></code></pre> <div id="SimpleLayout" data-code data-height="150px"></div> <p>In this example, the <code>container</code> prop on the first <code>&#x3C;Grid></code> element sets it up as a flex container, spanning the entire width of its parent by default (100%, or 12 grids). Each child <code>&#x3C;Grid item></code> specifies how many of those 12 columns it should span using the <code>xs</code> prop. Additionally, the <code>spacing</code> prop adds space between the grid items.</p> <p>Below is an example to understand how to achieve the equivalent outcome using CSS flex properties.</p> <pre class="grvsc-container default-dark" data-language="jsx" data-index="1"><code class="grvsc-code"><span class="grvsc-line"><span class="grvsc-source"><span class="mtk15">import</span><span class="mtk1"> </span><span class="mtk12">React</span><span class="mtk1"> </span><span class="mtk15">from</span><span class="mtk1"> </span><span class="mtk8">&quot;react&quot;</span><span class="mtk1">;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk15">import</span><span class="mtk1"> </span><span class="mtk12">Box</span><span class="mtk1"> </span><span class="mtk15">from</span><span class="mtk1"> </span><span class="mtk8">&quot;@mui/material/Box&quot;</span><span class="mtk1">;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk15">import</span><span class="mtk1"> </span><span class="mtk12">Paper</span><span class="mtk1"> </span><span class="mtk15">from</span><span class="mtk1"> </span><span class="mtk8">&quot;@mui/material/Paper&quot;</span><span class="mtk1">;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk4">const</span><span class="mtk1"> </span><span class="mtk11">SimpleLayoutWithBox</span><span class="mtk1"> = () </span><span class="mtk4">=&gt;</span><span class="mtk1"> {</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk15">return</span><span class="mtk1"> (</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk17">&lt;</span><span class="mtk10">Box</span><span class="mtk1"> </span><span class="mtk12">display</span><span class="mtk1">=</span><span class="mtk8">&quot;flex&quot;</span><span class="mtk1"> </span><span class="mtk12">width</span><span class="mtk1">=</span><span class="mtk8">&quot;100%&quot;</span><span class="mtk1"> </span><span class="mtk12">gap</span><span class="mtk1">=</span><span class="mtk4">{</span><span class="mtk7">2</span><span class="mtk4">}</span><span class="mtk17">&gt;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk17">&lt;</span><span class="mtk10">Box</span><span class="mtk1"> </span><span class="mtk12">width</span><span class="mtk1">=</span><span class="mtk8">&quot;25%&quot;</span><span class="mtk1"> </span><span class="mtk12">flexShrink</span><span class="mtk1">=</span><span class="mtk4">{</span><span class="mtk7">0</span><span class="mtk4">}</span><span class="mtk17">&gt;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk17">&lt;</span><span class="mtk10">Paper</span><span class="mtk1"> </span><span class="mtk12">sx</span><span class="mtk1">=</span><span class="mtk4">{</span><span class="mtk1">{ </span><span class="mtk12">p:</span><span class="mtk1"> </span><span class="mtk7">2</span><span class="mtk1"> }</span><span class="mtk4">}</span><span class="mtk17">&gt;</span><span class="mtk1">Side Nav</span><span class="mtk17">&lt;/</span><span class="mtk10">Paper</span><span class="mtk17">&gt;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk17">&lt;/</span><span class="mtk10">Box</span><span class="mtk17">&gt;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk17">&lt;</span><span class="mtk10">Box</span><span class="mtk1"> </span><span class="mtk12">width</span><span class="mtk1">=</span><span class="mtk8">&quot;75%&quot;</span><span class="mtk17">&gt;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk17">&lt;</span><span class="mtk10">Paper</span><span class="mtk1"> </span><span class="mtk12">sx</span><span class="mtk1">=</span><span class="mtk4">{</span><span class="mtk1">{ </span><span class="mtk12">p:</span><span class="mtk1"> </span><span class="mtk7">2</span><span class="mtk1"> }</span><span class="mtk4">}</span><span class="mtk17">&gt;</span><span class="mtk1">Body Content</span><span class="mtk17">&lt;/</span><span class="mtk10">Paper</span><span class="mtk17">&gt;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk17">&lt;/</span><span class="mtk10">Box</span><span class="mtk17">&gt;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk17">&lt;/</span><span class="mtk10">Box</span><span class="mtk17">&gt;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> );</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1">};</span></span></span> <span class="grvsc-line"><span class="grvsc-source"></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk15">export</span><span class="mtk1"> </span><span class="mtk15">default</span><span class="mtk1"> </span><span class="mtk12">SimpleLayoutWithBox</span><span class="mtk1">;</span></span></span></code></pre> <p>In this Box-based layout, we manually set the <code>display</code> to <code>flex</code> for the container and define the width of each child. This requires additional props such as <code>flexShrink</code> to prevent the left nav from shrinking on smaller screens, mimicking the behavior of Grid’s <code>xs</code> prop.</p> <h2 id="basic-responsive-layout" style="position:relative;"><a href="#basic-responsive-layout" aria-label="basic responsive layout permalink" class="anchor before"><svg aria-hidden="true" focusable="false" height="16" version="1.1" viewBox="0 0 16 16" width="16"><path fill-rule="evenodd" d="M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z"></path></svg></a>Basic Responsive Layout</h2> <p>The Grid component is equipped with a built-in responsive breakpoint system, allowing us to define layouts that easily adapt to different viewport sizes.</p> <ul> <li><code>xs</code>: Extra-small devices (portrait phones)</li> <li><code>sm</code>: Small devices (landscape phones)</li> <li><code>md</code>: Medium devices (tablets)</li> <li><code>lg</code>: Large devices (desktops)</li> <li><code>xl</code>: Extra-large devices (large desktops)</li> </ul> <p>Specifying a breakpoint on a Grid item means the layout will apply for that breakpoint and all larger screens unless overridden by a larger breakpoint.</p> <p>Let’s enhance our previous example by adjusting the size of the side nav and main content based on the screen size.</p> <pre class="grvsc-container default-dark" data-language="jsx" data-index="2"><code class="grvsc-code"><span class="grvsc-line"><span class="grvsc-source"><span class="mtk15">import</span><span class="mtk1"> </span><span class="mtk12">React</span><span class="mtk1"> </span><span class="mtk15">from</span><span class="mtk1"> </span><span class="mtk8">&quot;react&quot;</span><span class="mtk1">;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk15">import</span><span class="mtk1"> </span><span class="mtk12">Grid</span><span class="mtk1"> </span><span class="mtk15">from</span><span class="mtk1"> </span><span class="mtk8">&quot;@mui/material/Grid&quot;</span><span class="mtk1">;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk15">import</span><span class="mtk1"> </span><span class="mtk12">Paper</span><span class="mtk1"> </span><span class="mtk15">from</span><span class="mtk1"> </span><span class="mtk8">&quot;@mui/material/Paper&quot;</span><span class="mtk1">;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk4">const</span><span class="mtk1"> </span><span class="mtk11">ResponsiveLayout</span><span class="mtk1"> = () </span><span class="mtk4">=&gt;</span><span class="mtk1"> {</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk15">return</span><span class="mtk1"> (</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk17">&lt;</span><span class="mtk10">Grid</span><span class="mtk1"> </span><span class="mtk12">container</span><span class="mtk1"> </span><span class="mtk12">spacing</span><span class="mtk1">=</span><span class="mtk4">{</span><span class="mtk7">2</span><span class="mtk4">}</span><span class="mtk17">&gt;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk17">&lt;</span><span class="mtk10">Grid</span><span class="mtk1"> </span><span class="mtk12">item</span><span class="mtk1"> </span><span class="mtk12">xs</span><span class="mtk1">=</span><span class="mtk4">{</span><span class="mtk7">12</span><span class="mtk4">}</span><span class="mtk1"> </span><span class="mtk12">sm</span><span class="mtk1">=</span><span class="mtk4">{</span><span class="mtk7">4</span><span class="mtk4">}</span><span class="mtk1"> </span><span class="mtk12">md</span><span class="mtk1">=</span><span class="mtk4">{</span><span class="mtk7">3</span><span class="mtk4">}</span><span class="mtk1"> </span><span class="mtk12">lg</span><span class="mtk1">=</span><span class="mtk4">{</span><span class="mtk7">2</span><span class="mtk4">}</span><span class="mtk17">&gt;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk17">&lt;</span><span class="mtk10">Paper</span><span class="mtk1"> </span><span class="mtk12">sx</span><span class="mtk1">=</span><span class="mtk4">{</span><span class="mtk1">{ </span><span class="mtk12">p:</span><span class="mtk1"> </span><span class="mtk7">2</span><span class="mtk1"> }</span><span class="mtk4">}</span><span class="mtk17">&gt;</span><span class="mtk1">Side Nav</span><span class="mtk17">&lt;/</span><span class="mtk10">Paper</span><span class="mtk17">&gt;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk17">&lt;/</span><span class="mtk10">Grid</span><span class="mtk17">&gt;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk17">&lt;</span><span class="mtk10">Grid</span><span class="mtk1"> </span><span class="mtk12">item</span><span class="mtk1"> </span><span class="mtk12">xs</span><span class="mtk1">=</span><span class="mtk4">{</span><span class="mtk7">12</span><span class="mtk4">}</span><span class="mtk1"> </span><span class="mtk12">sm</span><span class="mtk1">=</span><span class="mtk4">{</span><span class="mtk7">8</span><span class="mtk4">}</span><span class="mtk1"> </span><span class="mtk12">md</span><span class="mtk1">=</span><span class="mtk4">{</span><span class="mtk7">9</span><span class="mtk4">}</span><span class="mtk1"> </span><span class="mtk12">lg</span><span class="mtk1">=</span><span class="mtk4">{</span><span class="mtk7">10</span><span class="mtk4">}</span><span class="mtk17">&gt;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk17">&lt;</span><span class="mtk10">Paper</span><span class="mtk1"> </span><span class="mtk12">sx</span><span class="mtk1">=</span><span class="mtk4">{</span><span class="mtk1">{ </span><span class="mtk12">p:</span><span class="mtk1"> </span><span class="mtk7">2</span><span class="mtk1"> }</span><span class="mtk4">}</span><span class="mtk17">&gt;</span><span class="mtk1">Main Content</span><span class="mtk17">&lt;/</span><span class="mtk10">Paper</span><span class="mtk17">&gt;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk17">&lt;/</span><span class="mtk10">Grid</span><span class="mtk17">&gt;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk17">&lt;/</span><span class="mtk10">Grid</span><span class="mtk17">&gt;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> );</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1">};</span></span></span> <span class="grvsc-line"><span class="grvsc-source"></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk15">export</span><span class="mtk1"> </span><span class="mtk15">default</span><span class="mtk1"> </span><span class="mtk12">ResponsiveLayout</span><span class="mtk1">;</span></span></span></code></pre> <div id="ResponsiveLayout" data-code data-height="150px" data-resize style="display:flex;justify-content: center;"></div> <p>In this code example:</p> <ul> <li>The side nav starts as a full-width block on extra-small devices (<code>xs={12}</code>) and gradually decreases in width relative to the screen size, moving to 4/12 on small screens (<code>sm={4}</code>), 3/12 on medium screens (<code>md={3}</code>), and 2/12 on large screens (<code>lg={2}</code>).</li> <li>Conversely, the main content area increases its share of the available screen width as the device size increases.</li> </ul> <p>This responsive design ensures that on smaller screens, the left nav and main content stack on top of each other for optimal space and readability.</p> <p>In the live example above, we can use the resize handle in the bottom right corner to see how the layout changes based on the screen size.</p> <h2 id="creating-responsive-cards" style="position:relative;"><a href="#creating-responsive-cards" aria-label="creating responsive cards permalink" class="anchor before"><svg aria-hidden="true" focusable="false" height="16" version="1.1" viewBox="0 0 16 16" width="16"><path fill-rule="evenodd" d="M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z"></path></svg></a>Creating Responsive Cards</h2> <p>Displaying content within cards is a widely used design pattern, ideal for showcasing posts, images, products, and more.</p> <p>We’ll begin by creating a <code>Container</code> with a <code>maxWidth</code> of “lg” to constrain the width on larger screens, ensuring our card layout remains aesthetically pleasing without stretching too wide on larger monitors. For a deeper understanding of the Container component, refer to <a href="https://muhimasri.com/blogs/how-to-override-material-ui-container-width/">this detailed tutorial</a>.</p> <pre class="grvsc-container default-dark" data-language="jsx" data-index="3"><code class="grvsc-code"><span class="grvsc-line"><span class="grvsc-source"><span class="mtk17">&lt;</span><span class="mtk10">Container</span><span class="mtk1"> </span><span class="mtk12">maxWidth</span><span class="mtk1">=</span><span class="mtk8">&quot;lg&quot;</span><span class="mtk17">&gt;</span><span class="mtk4">{</span><span class="mtk3">/* Cards go here */</span><span class="mtk4">}</span><span class="mtk17">&lt;/</span><span class="mtk10">Container</span><span class="mtk17">&gt;</span></span></span></code></pre> <p>Next, we’ll populate this container with a responsive grid of cards. Each card will be wrapped in a <code>Grid item</code> component that specifies the number of columns it should span on different screen sizes.</p> <pre class="grvsc-container default-dark" data-language="jsx" data-index="4"><code class="grvsc-code"><span class="grvsc-line"><span class="grvsc-source"><span class="mtk17">&lt;</span><span class="mtk10">Grid</span><span class="mtk1"> </span><span class="mtk12">item</span><span class="mtk1"> </span><span class="mtk12">key</span><span class="mtk1">=</span><span class="mtk4">{</span><span class="mtk12">index</span><span class="mtk4">}</span><span class="mtk1"> </span><span class="mtk12">xs</span><span class="mtk1">=</span><span class="mtk4">{</span><span class="mtk7">12</span><span class="mtk4">}</span><span class="mtk1"> </span><span class="mtk12">sm</span><span class="mtk1">=</span><span class="mtk4">{</span><span class="mtk7">6</span><span class="mtk4">}</span><span class="mtk1"> </span><span class="mtk12">md</span><span class="mtk1">=</span><span class="mtk4">{</span><span class="mtk7">4</span><span class="mtk4">}</span><span class="mtk1"> </span><span class="mtk12">lg</span><span class="mtk1">=</span><span class="mtk4">{</span><span class="mtk7">3</span><span class="mtk4">}</span><span class="mtk17">&gt;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk17">&lt;</span><span class="mtk10">Card</span><span class="mtk17">&gt;</span><span class="mtk4">{</span><span class="mtk3">/* Card content goes here */</span><span class="mtk4">}</span><span class="mtk17">&lt;/</span><span class="mtk10">Card</span><span class="mtk17">&gt;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk17">&lt;/</span><span class="mtk10">Grid</span><span class="mtk17">&gt;</span></span></span></code></pre> <ul> <li>Large screens (lg): 3 columns (12/3 = 4 cards per row)</li> <li>Medium screens (md): 4 columns (12/4 = 3 cards per row)</li> <li>Small screens (sm): 6 columns (12/6 = 2 cards per row)</li> <li>Extra-small screens (xs): Full width (1 card per row)</li> </ul> <p>Finally, we’ll create a list of cards by mapping over an array of card data. Each card will contain a <code>CardMedia</code> component for images, a <code>CardContent</code> component for text content, and <code>Typography</code> components for titles and descriptions.</p> <pre class="grvsc-container default-dark" data-language="jsx" data-index="5"><code class="grvsc-code"><span class="grvsc-line"><span class="grvsc-source"><span class="mtk15">import</span><span class="mtk1"> </span><span class="mtk12">React</span><span class="mtk1"> </span><span class="mtk15">from</span><span class="mtk1"> </span><span class="mtk8">&quot;react&quot;</span><span class="mtk1">;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk15">import</span><span class="mtk1"> {</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">Container</span><span class="mtk1">,</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">Grid</span><span class="mtk1">,</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">Card</span><span class="mtk1">,</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">CardMedia</span><span class="mtk1">,</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">CardContent</span><span class="mtk1">,</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">Typography</span><span class="mtk1">,</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1">} </span><span class="mtk15">from</span><span class="mtk1"> </span><span class="mtk8">&quot;@mui/material&quot;</span><span class="mtk1">;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk4">const</span><span class="mtk1"> </span><span class="mtk11">CardList</span><span class="mtk1"> = () </span><span class="mtk4">=&gt;</span><span class="mtk1"> {</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk15">return</span><span class="mtk1"> (</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk17">&lt;</span><span class="mtk10">Container</span><span class="mtk1"> </span><span class="mtk12">maxWidth</span><span class="mtk1">=</span><span class="mtk8">&quot;lg&quot;</span><span class="mtk17">&gt;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk17">&lt;</span><span class="mtk10">Grid</span><span class="mtk1"> </span><span class="mtk12">container</span><span class="mtk1"> </span><span class="mtk12">spacing</span><span class="mtk1">=</span><span class="mtk4">{</span><span class="mtk7">2</span><span class="mtk4">}</span><span class="mtk17">&gt;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk4">{</span><span class="mtk1">[</span><span class="mtk7">1</span><span class="mtk1">, </span><span class="mtk7">2</span><span class="mtk1">, </span><span class="mtk7">3</span><span class="mtk1">, </span><span class="mtk7">4</span><span class="mtk1">, </span><span class="mtk7">5</span><span class="mtk1">, </span><span class="mtk7">6</span><span class="mtk1">].</span><span class="mtk11">map</span><span class="mtk1">((</span><span class="mtk12">card</span><span class="mtk1">, </span><span class="mtk12">index</span><span class="mtk1">) </span><span class="mtk4">=&gt;</span><span class="mtk1"> (</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk17">&lt;</span><span class="mtk10">Grid</span><span class="mtk1"> </span><span class="mtk12">item</span><span class="mtk1"> </span><span class="mtk12">key</span><span class="mtk1">=</span><span class="mtk4">{</span><span class="mtk12">index</span><span class="mtk4">}</span><span class="mtk1"> </span><span class="mtk12">xs</span><span class="mtk1">=</span><span class="mtk4">{</span><span class="mtk7">12</span><span class="mtk4">}</span><span class="mtk1"> </span><span class="mtk12">sm</span><span class="mtk1">=</span><span class="mtk4">{</span><span class="mtk7">6</span><span class="mtk4">}</span><span class="mtk1"> </span><span class="mtk12">md</span><span class="mtk1">=</span><span class="mtk4">{</span><span class="mtk7">4</span><span class="mtk4">}</span><span class="mtk1"> </span><span class="mtk12">lg</span><span class="mtk1">=</span><span class="mtk4">{</span><span class="mtk7">3</span><span class="mtk4">}</span><span class="mtk17">&gt;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk17">&lt;</span><span class="mtk10">Card</span><span class="mtk17">&gt;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk17">&lt;</span><span class="mtk10">CardMedia</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">component</span><span class="mtk1">=</span><span class="mtk8">&quot;img&quot;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">height</span><span class="mtk1">=</span><span class="mtk8">&quot;140&quot;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">image</span><span class="mtk1">=</span><span class="mtk8">&quot;https://via.placeholder.com/200&quot;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">alt</span><span class="mtk1">=</span><span class="mtk4">{</span><span class="mtk8">`Card </span><span class="mtk4">${</span><span class="mtk12">index</span><span class="mtk1"> + </span><span class="mtk7">1</span><span class="mtk4">}</span><span class="mtk8">`</span><span class="mtk4">}</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk17">/&gt;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk17">&lt;</span><span class="mtk10">CardContent</span><span class="mtk17">&gt;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk17">&lt;</span><span class="mtk10">Typography</span><span class="mtk1"> </span><span class="mtk12">gutterBottom</span><span class="mtk1"> </span><span class="mtk12">variant</span><span class="mtk1">=</span><span class="mtk8">&quot;h5&quot;</span><span class="mtk1"> </span><span class="mtk12">component</span><span class="mtk1">=</span><span class="mtk8">&quot;div&quot;</span><span class="mtk17">&gt;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> Card Title </span><span class="mtk4">{</span><span class="mtk12">index</span><span class="mtk1"> + </span><span class="mtk7">1</span><span class="mtk4">}</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk17">&lt;/</span><span class="mtk10">Typography</span><span class="mtk17">&gt;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk17">&lt;</span><span class="mtk10">Typography</span><span class="mtk1"> </span><span class="mtk12">variant</span><span class="mtk1">=</span><span class="mtk8">&quot;body2&quot;</span><span class="mtk1"> </span><span class="mtk12">color</span><span class="mtk1">=</span><span class="mtk8">&quot;text.secondary&quot;</span><span class="mtk17">&gt;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> This is a media card. You can use this section to describe the</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> content.</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk17">&lt;/</span><span class="mtk10">Typography</span><span class="mtk17">&gt;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk17">&lt;/</span><span class="mtk10">CardContent</span><span class="mtk17">&gt;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk17">&lt;/</span><span class="mtk10">Card</span><span class="mtk17">&gt;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk17">&lt;/</span><span class="mtk10">Grid</span><span class="mtk17">&gt;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> ))</span><span class="mtk4">}</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk17">&lt;/</span><span class="mtk10">Grid</span><span class="mtk17">&gt;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk17">&lt;/</span><span class="mtk10">Container</span><span class="mtk17">&gt;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> );</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1">};</span></span></span> <span class="grvsc-line"><span class="grvsc-source"></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk15">export</span><span class="mtk1"> </span><span class="mtk15">default</span><span class="mtk1"> </span><span class="mtk12">CardList</span><span class="mtk1">;</span></span></span></code></pre> <div id="CardList" data-code data-height="800px" data-resize style="display:flex;justify-content: center;"></div> <p>In this example, if we resize the preview window, we can see how the number of cards per row changes based on the screen size.</p> <h2 id="creating-a-page-layout" style="position:relative;"><a href="#creating-a-page-layout" aria-label="creating a page layout permalink" class="anchor before"><svg aria-hidden="true" focusable="false" height="16" version="1.1" viewBox="0 0 16 16" width="16"><path fill-rule="evenodd" d="M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z"></path></svg></a>Creating a Page Layout</h2> <p>Creating a comprehensive page layout involves integrating various components and responsive design techniques we discussed earlier. Let’s break it down and highlight the new additions.</p> <h4 id="main-structure" style="position:relative;"><a href="#main-structure" aria-label="main structure permalink" class="anchor before"><svg aria-hidden="true" focusable="false" height="16" version="1.1" viewBox="0 0 16 16" width="16"><path fill-rule="evenodd" d="M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z"></path></svg></a>Main Structure</h4> <p>The page component is divided into four main sections: header, sidenav, main content, and footer. Each section is wrapped in a <code>Grid item</code> component that specifies the number of columns it should span on different screen sizes.</p> <pre class="grvsc-container default-dark" data-language="jsx" data-index="6"><code class="grvsc-code"><span class="grvsc-line"><span class="grvsc-source"><span class="mtk15">import</span><span class="mtk1"> </span><span class="mtk12">React</span><span class="mtk1"> </span><span class="mtk15">from</span><span class="mtk1"> </span><span class="mtk8">&quot;react&quot;</span><span class="mtk1">;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk15">import</span><span class="mtk1"> { </span><span class="mtk12">Container</span><span class="mtk1">, </span><span class="mtk12">Grid</span><span class="mtk1">, </span><span class="mtk12">Typography</span><span class="mtk1">, </span><span class="mtk12">Paper</span><span class="mtk1"> } </span><span class="mtk15">from</span><span class="mtk1"> </span><span class="mtk8">&quot;@mui/material&quot;</span><span class="mtk1">;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk4">const</span><span class="mtk1"> </span><span class="mtk11">PageLayout</span><span class="mtk1"> = () </span><span class="mtk4">=&gt;</span><span class="mtk1"> {</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk15">return</span><span class="mtk1"> (</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk17">&lt;</span><span class="mtk10">Container</span><span class="mtk1"> </span><span class="mtk12">maxWidth</span><span class="mtk1">=</span><span class="mtk8">&quot;lg&quot;</span><span class="mtk17">&gt;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk17">&lt;</span><span class="mtk10">Grid</span><span class="mtk1"> </span><span class="mtk12">container</span><span class="mtk1"> </span><span class="mtk12">spacing</span><span class="mtk1">=</span><span class="mtk4">{</span><span class="mtk7">3</span><span class="mtk4">}</span><span class="mtk17">&gt;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk4">{</span><span class="mtk3">/* Header */</span><span class="mtk4">}</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk17">&lt;</span><span class="mtk10">Grid</span><span class="mtk1"> </span><span class="mtk12">item</span><span class="mtk1"> </span><span class="mtk12">xs</span><span class="mtk1">=</span><span class="mtk4">{</span><span class="mtk7">12</span><span class="mtk4">}</span><span class="mtk17">&gt;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk17">&lt;</span><span class="mtk10">Paper</span><span class="mtk1"> </span><span class="mtk12">sx</span><span class="mtk1">=</span><span class="mtk4">{</span><span class="mtk1">{ </span><span class="mtk12">p:</span><span class="mtk1"> </span><span class="mtk7">2</span><span class="mtk1">, </span><span class="mtk12">textAlign:</span><span class="mtk1"> </span><span class="mtk8">&quot;center&quot;</span><span class="mtk1"> }</span><span class="mtk4">}</span><span class="mtk17">&gt;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk17">&lt;</span><span class="mtk10">Typography</span><span class="mtk1"> </span><span class="mtk12">variant</span><span class="mtk1">=</span><span class="mtk8">&quot;h4&quot;</span><span class="mtk17">&gt;</span><span class="mtk1">Page Header</span><span class="mtk17">&lt;/</span><span class="mtk10">Typography</span><span class="mtk17">&gt;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk17">&lt;/</span><span class="mtk10">Paper</span><span class="mtk17">&gt;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk17">&lt;/</span><span class="mtk10">Grid</span><span class="mtk17">&gt;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk4">{</span><span class="mtk3">/* sidenav */</span><span class="mtk4">}</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk17">&lt;</span><span class="mtk10">Grid</span><span class="mtk1"> </span><span class="mtk12">item</span><span class="mtk1"> </span><span class="mtk12">xs</span><span class="mtk1">=</span><span class="mtk4">{</span><span class="mtk7">12</span><span class="mtk4">}</span><span class="mtk1"> </span><span class="mtk12">sm</span><span class="mtk1">=</span><span class="mtk4">{</span><span class="mtk7">4</span><span class="mtk4">}</span><span class="mtk1"> </span><span class="mtk12">md</span><span class="mtk1">=</span><span class="mtk4">{</span><span class="mtk7">3</span><span class="mtk4">}</span><span class="mtk1"> </span><span class="mtk12">lg</span><span class="mtk1">=</span><span class="mtk4">{</span><span class="mtk7">2</span><span class="mtk4">}</span><span class="mtk17">&gt;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk17">&lt;</span><span class="mtk10">Paper</span><span class="mtk1"> </span><span class="mtk12">sx</span><span class="mtk1">=</span><span class="mtk4">{</span><span class="mtk1">{ </span><span class="mtk12">p:</span><span class="mtk1"> </span><span class="mtk7">2</span><span class="mtk1"> }</span><span class="mtk4">}</span><span class="mtk17">&gt;</span><span class="mtk1">Side Nav</span><span class="mtk17">&lt;/</span><span class="mtk10">Paper</span><span class="mtk17">&gt;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk17">&lt;/</span><span class="mtk10">Grid</span><span class="mtk17">&gt;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk4">{</span><span class="mtk3">/* Main Content */</span><span class="mtk4">}</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk17">&lt;</span><span class="mtk10">Grid</span><span class="mtk1"> </span><span class="mtk12">item</span><span class="mtk1"> </span><span class="mtk12">xs</span><span class="mtk1">=</span><span class="mtk4">{</span><span class="mtk7">12</span><span class="mtk4">}</span><span class="mtk1"> </span><span class="mtk12">sm</span><span class="mtk1">=</span><span class="mtk4">{</span><span class="mtk7">8</span><span class="mtk4">}</span><span class="mtk1"> </span><span class="mtk12">md</span><span class="mtk1">=</span><span class="mtk4">{</span><span class="mtk7">9</span><span class="mtk4">}</span><span class="mtk1"> </span><span class="mtk12">lg</span><span class="mtk1">=</span><span class="mtk4">{</span><span class="mtk7">10</span><span class="mtk4">}</span><span class="mtk17">&gt;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk17">&lt;</span><span class="mtk10">Paper</span><span class="mtk1"> </span><span class="mtk12">sx</span><span class="mtk1">=</span><span class="mtk4">{</span><span class="mtk1">{ </span><span class="mtk12">p:</span><span class="mtk1"> </span><span class="mtk7">2</span><span class="mtk1"> }</span><span class="mtk4">}</span><span class="mtk17">&gt;</span><span class="mtk1">Main Content</span><span class="mtk17">&lt;/</span><span class="mtk10">Paper</span><span class="mtk17">&gt;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk17">&lt;/</span><span class="mtk10">Grid</span><span class="mtk17">&gt;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk4">{</span><span class="mtk3">/* Footer */</span><span class="mtk4">}</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk17">&lt;</span><span class="mtk10">Grid</span><span class="mtk1"> </span><span class="mtk12">item</span><span class="mtk1"> </span><span class="mtk12">xs</span><span class="mtk1">=</span><span class="mtk4">{</span><span class="mtk7">12</span><span class="mtk4">}</span><span class="mtk17">&gt;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk17">&lt;</span><span class="mtk10">Paper</span><span class="mtk1"> </span><span class="mtk12">sx</span><span class="mtk1">=</span><span class="mtk4">{</span><span class="mtk1">{ </span><span class="mtk12">p:</span><span class="mtk1"> </span><span class="mtk7">2</span><span class="mtk1">, </span><span class="mtk12">textAlign:</span><span class="mtk1"> </span><span class="mtk8">&quot;center&quot;</span><span class="mtk1"> }</span><span class="mtk4">}</span><span class="mtk17">&gt;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk17">&lt;</span><span class="mtk10">Typography</span><span class="mtk1"> </span><span class="mtk12">variant</span><span class="mtk1">=</span><span class="mtk8">&quot;body1&quot;</span><span class="mtk17">&gt;</span><span class="mtk1">Page Footer</span><span class="mtk17">&lt;/</span><span class="mtk10">Typography</span><span class="mtk17">&gt;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk17">&lt;/</span><span class="mtk10">Paper</span><span class="mtk17">&gt;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk17">&lt;/</span><span class="mtk10">Grid</span><span class="mtk17">&gt;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk17">&lt;/</span><span class="mtk10">Grid</span><span class="mtk17">&gt;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk17">&lt;/</span><span class="mtk10">Container</span><span class="mtk17">&gt;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> );</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1">};</span></span></span> <span class="grvsc-line"><span class="grvsc-source"></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk15">export</span><span class="mtk1"> </span><span class="mtk15">default</span><span class="mtk1"> </span><span class="mtk12">PageLayout</span><span class="mtk1">;</span></span></span></code></pre> <div id="PageLayout" data-code data-height="350px" data-resize style="display:flex;justify-content: center;"></div> <p>The logic behind the layout is similar to the responsive layout example we discussed earlier. The header and footer sections span the full width of the screen, while the sidenav and main content sections adjust their width based on the screen size.</p> <h4 id="sidenav" style="position:relative;"><a href="#sidenav" aria-label="sidenav permalink" class="anchor before"><svg aria-hidden="true" focusable="false" height="16" version="1.1" viewBox="0 0 16 16" width="16"><path fill-rule="evenodd" d="M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z"></path></svg></a>Sidenav</h4> <p>The sidenav will mock a list of filters users can select to filter the cards in the main content. We will populate the sidenav with a <code>List</code> component containing <code>ListItem</code> for each filter. To save space, the layout will switch to a <code>Select</code> dropdown on smaller screens.</p> <pre class="grvsc-container default-dark" data-language="jsx" data-index="7"><code class="grvsc-code"><span class="grvsc-line"><span class="grvsc-source"><span class="mtk4">const</span><span class="mtk1"> </span><span class="mtk12">theme</span><span class="mtk1"> = </span><span class="mtk11">useTheme</span><span class="mtk1">();</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk4">const</span><span class="mtk1"> </span><span class="mtk12">isSmallScreen</span><span class="mtk1"> = </span><span class="mtk11">useMediaQuery</span><span class="mtk1">(</span><span class="mtk12">theme</span><span class="mtk1">.</span><span class="mtk12">breakpoints</span><span class="mtk1">.</span><span class="mtk11">down</span><span class="mtk1">(</span><span class="mtk8">&quot;sm&quot;</span><span class="mtk1">));</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk4">const</span><span class="mtk1"> </span><span class="mtk12">filters</span><span class="mtk1"> = [</span><span class="mtk8">&quot;Filter 1&quot;</span><span class="mtk1">, </span><span class="mtk8">&quot;Filter 2&quot;</span><span class="mtk1">, </span><span class="mtk8">&quot;Filter 3&quot;</span><span class="mtk1">];</span></span></span> <span class="grvsc-line"><span class="grvsc-source"></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk15">return</span><span class="mtk1"> (</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk17">&lt;</span><span class="mtk10">Grid</span><span class="mtk1"> </span><span class="mtk12">item</span><span class="mtk1"> </span><span class="mtk12">xs</span><span class="mtk1">=</span><span class="mtk4">{</span><span class="mtk7">12</span><span class="mtk4">}</span><span class="mtk1"> </span><span class="mtk12">sm</span><span class="mtk1">=</span><span class="mtk4">{</span><span class="mtk7">4</span><span class="mtk4">}</span><span class="mtk1"> </span><span class="mtk12">md</span><span class="mtk1">=</span><span class="mtk4">{</span><span class="mtk7">3</span><span class="mtk4">}</span><span class="mtk1"> </span><span class="mtk12">lg</span><span class="mtk1">=</span><span class="mtk4">{</span><span class="mtk7">2</span><span class="mtk4">}</span><span class="mtk17">&gt;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk17">&lt;</span><span class="mtk10">Paper</span><span class="mtk1"> </span><span class="mtk12">sx</span><span class="mtk1">=</span><span class="mtk4">{</span><span class="mtk1">{ </span><span class="mtk12">p:</span><span class="mtk1"> </span><span class="mtk7">2</span><span class="mtk1"> }</span><span class="mtk4">}</span><span class="mtk17">&gt;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk4">{</span><span class="mtk12">isSmallScreen</span><span class="mtk1"> ? (</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk17">&lt;</span><span class="mtk10">FormControl</span><span class="mtk1"> </span><span class="mtk12">fullWidth</span><span class="mtk17">&gt;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk17">&lt;</span><span class="mtk10">Select</span><span class="mtk1"> </span><span class="mtk12">value</span><span class="mtk1">=</span><span class="mtk4">{</span><span class="mtk12">selectedFilter</span><span class="mtk4">}</span><span class="mtk1"> </span><span class="mtk12">onChange</span><span class="mtk1">=</span><span class="mtk4">{</span><span class="mtk12">handleFilterChange</span><span class="mtk4">}</span><span class="mtk17">&gt;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk4">{</span><span class="mtk12">filters</span><span class="mtk1">.</span><span class="mtk11">map</span><span class="mtk1">((</span><span class="mtk12">filter</span><span class="mtk1">, </span><span class="mtk12">index</span><span class="mtk1">) </span><span class="mtk4">=&gt;</span><span class="mtk1"> (</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk17">&lt;</span><span class="mtk10">MenuItem</span><span class="mtk1"> </span><span class="mtk12">key</span><span class="mtk1">=</span><span class="mtk4">{</span><span class="mtk12">index</span><span class="mtk4">}</span><span class="mtk1"> </span><span class="mtk12">value</span><span class="mtk1">=</span><span class="mtk4">{</span><span class="mtk12">filter</span><span class="mtk4">}</span><span class="mtk17">&gt;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk4">{</span><span class="mtk12">filter</span><span class="mtk4">}</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk17">&lt;/</span><span class="mtk10">MenuItem</span><span class="mtk17">&gt;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> ))</span><span class="mtk4">}</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk17">&lt;/</span><span class="mtk10">Select</span><span class="mtk17">&gt;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk17">&lt;/</span><span class="mtk10">FormControl</span><span class="mtk17">&gt;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> ) : (</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk17">&lt;</span><span class="mtk10">List</span><span class="mtk17">&gt;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk4">{</span><span class="mtk12">filters</span><span class="mtk1">.</span><span class="mtk11">map</span><span class="mtk1">((</span><span class="mtk12">filter</span><span class="mtk1">, </span><span class="mtk12">index</span><span class="mtk1">) </span><span class="mtk4">=&gt;</span><span class="mtk1"> (</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk17">&lt;</span><span class="mtk10">ListItem</span><span class="mtk1"> </span><span class="mtk12">button</span><span class="mtk1"> </span><span class="mtk12">key</span><span class="mtk1">=</span><span class="mtk4">{</span><span class="mtk12">index</span><span class="mtk4">}</span><span class="mtk17">&gt;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk17">&lt;</span><span class="mtk10">ListItemText</span><span class="mtk1"> </span><span class="mtk12">primary</span><span class="mtk1">=</span><span class="mtk4">{</span><span class="mtk12">filter</span><span class="mtk4">}</span><span class="mtk1"> </span><span class="mtk17">/&gt;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk17">&lt;/</span><span class="mtk10">ListItem</span><span class="mtk17">&gt;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> ))</span><span class="mtk4">}</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk17">&lt;/</span><span class="mtk10">List</span><span class="mtk17">&gt;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> )</span><span class="mtk4">}</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk17">&lt;/</span><span class="mtk10">Paper</span><span class="mtk17">&gt;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk17">&lt;/</span><span class="mtk10">Grid</span><span class="mtk17">&gt;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1">);</span></span></span></code></pre> <p>In this example, we use the <code>useTheme</code> and <code>useMediaQuery</code> hooks to determine the screen size. We render a <code>Select</code> dropdown if the screen is small (down to 600px). Otherwise, we display <code>List</code>.</p> <h4 id="complete-page-layout" style="position:relative;"><a href="#complete-page-layout" aria-label="complete page layout permalink" class="anchor before"><svg aria-hidden="true" focusable="false" height="16" version="1.1" viewBox="0 0 16 16" width="16"><path fill-rule="evenodd" d="M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z"></path></svg></a>Complete Page Layout</h4> <p>Finally, let’s create the <code>PageLayout</code> component, which integrates the header, sidenav, main content (the cards we created earlier part), and footer sections into a cohesive layout.</p> <pre class="grvsc-container default-dark" data-language="jsx" data-index="8"><code class="grvsc-code"><span class="grvsc-line"><span class="grvsc-source"><span class="mtk15">import</span><span class="mtk1"> </span><span class="mtk12">React</span><span class="mtk1"> </span><span class="mtk15">from</span><span class="mtk1"> </span><span class="mtk8">&quot;react&quot;</span><span class="mtk1">;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk15">import</span><span class="mtk1"> {</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">Container</span><span class="mtk1">,</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">Grid</span><span class="mtk1">,</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">Paper</span><span class="mtk1">,</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">Typography</span><span class="mtk1">,</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">List</span><span class="mtk1">,</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">ListItem</span><span class="mtk1">,</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">ListItemText</span><span class="mtk1">,</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">FormControl</span><span class="mtk1">,</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">Select</span><span class="mtk1">,</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">MenuItem</span><span class="mtk1">,</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">Card</span><span class="mtk1">,</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">CardContent</span><span class="mtk1">,</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">CardMedia</span><span class="mtk1">,</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">useTheme</span><span class="mtk1">,</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">useMediaQuery</span><span class="mtk1">,</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1">} </span><span class="mtk15">from</span><span class="mtk1"> </span><span class="mtk8">&quot;@mui/material&quot;</span><span class="mtk1">;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk4">function</span><span class="mtk1"> </span><span class="mtk11">PageLayout</span><span class="mtk1">() {</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk4">const</span><span class="mtk1"> </span><span class="mtk12">theme</span><span class="mtk1"> = </span><span class="mtk11">useTheme</span><span class="mtk1">();</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk4">const</span><span class="mtk1"> </span><span class="mtk12">isSmallScreen</span><span class="mtk1"> = </span><span class="mtk11">useMediaQuery</span><span class="mtk1">(</span><span class="mtk12">theme</span><span class="mtk1">.</span><span class="mtk12">breakpoints</span><span class="mtk1">.</span><span class="mtk11">down</span><span class="mtk1">(</span><span class="mtk8">&quot;sm&quot;</span><span class="mtk1">));</span></span></span> <span class="grvsc-line"><span class="grvsc-source"></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk4">const</span><span class="mtk1"> </span><span class="mtk12">filters</span><span class="mtk1"> = [</span><span class="mtk8">&quot;Filter 1&quot;</span><span class="mtk1">, </span><span class="mtk8">&quot;Filter 2&quot;</span><span class="mtk1">, </span><span class="mtk8">&quot;Filter 3&quot;</span><span class="mtk1">];</span></span></span> <span class="grvsc-line"><span class="grvsc-source"></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk15">return</span><span class="mtk1"> (</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk17">&lt;</span><span class="mtk10">Container</span><span class="mtk1"> </span><span class="mtk12">maxWidth</span><span class="mtk1">=</span><span class="mtk8">&quot;lg&quot;</span><span class="mtk17">&gt;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk17">&lt;</span><span class="mtk10">Grid</span><span class="mtk1"> </span><span class="mtk12">container</span><span class="mtk1"> </span><span class="mtk12">spacing</span><span class="mtk1">=</span><span class="mtk4">{</span><span class="mtk7">3</span><span class="mtk4">}</span><span class="mtk17">&gt;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk4">{</span><span class="mtk3">/* Header */</span><span class="mtk4">}</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk17">&lt;</span><span class="mtk10">Grid</span><span class="mtk1"> </span><span class="mtk12">item</span><span class="mtk1"> </span><span class="mtk12">xs</span><span class="mtk1">=</span><span class="mtk4">{</span><span class="mtk7">12</span><span class="mtk4">}</span><span class="mtk17">&gt;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk17">&lt;</span><span class="mtk10">Paper</span><span class="mtk1"> </span><span class="mtk12">sx</span><span class="mtk1">=</span><span class="mtk4">{</span><span class="mtk1">{ </span><span class="mtk12">p:</span><span class="mtk1"> </span><span class="mtk7">2</span><span class="mtk1">, </span><span class="mtk12">textAlign:</span><span class="mtk1"> </span><span class="mtk8">&quot;center&quot;</span><span class="mtk1"> }</span><span class="mtk4">}</span><span class="mtk17">&gt;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk17">&lt;</span><span class="mtk10">Typography</span><span class="mtk1"> </span><span class="mtk12">variant</span><span class="mtk1">=</span><span class="mtk8">&quot;h4&quot;</span><span class="mtk17">&gt;</span><span class="mtk1">Page Header</span><span class="mtk17">&lt;/</span><span class="mtk10">Typography</span><span class="mtk17">&gt;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk17">&lt;/</span><span class="mtk10">Paper</span><span class="mtk17">&gt;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk17">&lt;/</span><span class="mtk10">Grid</span><span class="mtk17">&gt;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk4">{</span><span class="mtk3">/* Sidebar */</span><span class="mtk4">}</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk17">&lt;</span><span class="mtk10">Grid</span><span class="mtk1"> </span><span class="mtk12">item</span><span class="mtk1"> </span><span class="mtk12">xs</span><span class="mtk1">=</span><span class="mtk4">{</span><span class="mtk7">12</span><span class="mtk4">}</span><span class="mtk1"> </span><span class="mtk12">sm</span><span class="mtk1">=</span><span class="mtk4">{</span><span class="mtk7">4</span><span class="mtk4">}</span><span class="mtk1"> </span><span class="mtk12">md</span><span class="mtk1">=</span><span class="mtk4">{</span><span class="mtk7">3</span><span class="mtk4">}</span><span class="mtk1"> </span><span class="mtk12">lg</span><span class="mtk1">=</span><span class="mtk4">{</span><span class="mtk7">2</span><span class="mtk4">}</span><span class="mtk17">&gt;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk17">&lt;</span><span class="mtk10">Paper</span><span class="mtk1"> </span><span class="mtk12">sx</span><span class="mtk1">=</span><span class="mtk4">{</span><span class="mtk1">{ </span><span class="mtk12">p:</span><span class="mtk1"> </span><span class="mtk7">2</span><span class="mtk1"> }</span><span class="mtk4">}</span><span class="mtk17">&gt;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk4">{</span><span class="mtk12">isSmallScreen</span><span class="mtk1"> ? (</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk17">&lt;</span><span class="mtk10">FormControl</span><span class="mtk1"> </span><span class="mtk12">fullWidth</span><span class="mtk17">&gt;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk17">&lt;</span><span class="mtk10">Select</span><span class="mtk17">&gt;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk4">{</span><span class="mtk12">filters</span><span class="mtk1">.</span><span class="mtk11">map</span><span class="mtk1">((</span><span class="mtk12">filter</span><span class="mtk1">, </span><span class="mtk12">index</span><span class="mtk1">) </span><span class="mtk4">=&gt;</span><span class="mtk1"> (</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk17">&lt;</span><span class="mtk10">MenuItem</span><span class="mtk1"> </span><span class="mtk12">key</span><span class="mtk1">=</span><span class="mtk4">{</span><span class="mtk12">index</span><span class="mtk4">}</span><span class="mtk1"> </span><span class="mtk12">value</span><span class="mtk1">=</span><span class="mtk4">{</span><span class="mtk12">filter</span><span class="mtk4">}</span><span class="mtk17">&gt;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk4">{</span><span class="mtk12">filter</span><span class="mtk4">}</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk17">&lt;/</span><span class="mtk10">MenuItem</span><span class="mtk17">&gt;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> ))</span><span class="mtk4">}</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk17">&lt;/</span><span class="mtk10">Select</span><span class="mtk17">&gt;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk17">&lt;/</span><span class="mtk10">FormControl</span><span class="mtk17">&gt;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> ) : (</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk17">&lt;</span><span class="mtk10">List</span><span class="mtk17">&gt;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk4">{</span><span class="mtk12">filters</span><span class="mtk1">.</span><span class="mtk11">map</span><span class="mtk1">((</span><span class="mtk12">filter</span><span class="mtk1">, </span><span class="mtk12">index</span><span class="mtk1">) </span><span class="mtk4">=&gt;</span><span class="mtk1"> (</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk17">&lt;</span><span class="mtk10">ListItem</span><span class="mtk1"> </span><span class="mtk12">button</span><span class="mtk1"> </span><span class="mtk12">key</span><span class="mtk1">=</span><span class="mtk4">{</span><span class="mtk12">index</span><span class="mtk4">}</span><span class="mtk17">&gt;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk17">&lt;</span><span class="mtk10">ListItemText</span><span class="mtk1"> </span><span class="mtk12">primary</span><span class="mtk1">=</span><span class="mtk4">{</span><span class="mtk12">filter</span><span class="mtk4">}</span><span class="mtk1"> </span><span class="mtk17">/&gt;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk17">&lt;/</span><span class="mtk10">ListItem</span><span class="mtk17">&gt;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> ))</span><span class="mtk4">}</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk17">&lt;/</span><span class="mtk10">List</span><span class="mtk17">&gt;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> )</span><span class="mtk4">}</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk17">&lt;/</span><span class="mtk10">Paper</span><span class="mtk17">&gt;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk17">&lt;/</span><span class="mtk10">Grid</span><span class="mtk17">&gt;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk4">{</span><span class="mtk3">/* Main Content */</span><span class="mtk4">}</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk17">&lt;</span><span class="mtk10">Grid</span><span class="mtk1"> </span><span class="mtk12">item</span><span class="mtk1"> </span><span class="mtk12">xs</span><span class="mtk1">=</span><span class="mtk4">{</span><span class="mtk7">12</span><span class="mtk4">}</span><span class="mtk1"> </span><span class="mtk12">sm</span><span class="mtk1">=</span><span class="mtk4">{</span><span class="mtk7">8</span><span class="mtk4">}</span><span class="mtk1"> </span><span class="mtk12">md</span><span class="mtk1">=</span><span class="mtk4">{</span><span class="mtk7">9</span><span class="mtk4">}</span><span class="mtk1"> </span><span class="mtk12">lg</span><span class="mtk1">=</span><span class="mtk4">{</span><span class="mtk7">10</span><span class="mtk4">}</span><span class="mtk1"> </span><span class="mtk12">container</span><span class="mtk1"> </span><span class="mtk12">spacing</span><span class="mtk1">=</span><span class="mtk4">{</span><span class="mtk7">2</span><span class="mtk4">}</span><span class="mtk17">&gt;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk4">{</span><span class="mtk1">[</span><span class="mtk7">1</span><span class="mtk1">, </span><span class="mtk7">2</span><span class="mtk1">, </span><span class="mtk7">3</span><span class="mtk1">, </span><span class="mtk7">4</span><span class="mtk1">].</span><span class="mtk11">map</span><span class="mtk1">((</span><span class="mtk12">card</span><span class="mtk1">, </span><span class="mtk12">index</span><span class="mtk1">) </span><span class="mtk4">=&gt;</span><span class="mtk1"> (</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk17">&lt;</span><span class="mtk10">Grid</span><span class="mtk1"> </span><span class="mtk12">item</span><span class="mtk1"> </span><span class="mtk12">key</span><span class="mtk1">=</span><span class="mtk4">{</span><span class="mtk12">index</span><span class="mtk4">}</span><span class="mtk1"> </span><span class="mtk12">xs</span><span class="mtk1">=</span><span class="mtk4">{</span><span class="mtk7">12</span><span class="mtk4">}</span><span class="mtk1"> </span><span class="mtk12">sm</span><span class="mtk1">=</span><span class="mtk4">{</span><span class="mtk7">6</span><span class="mtk4">}</span><span class="mtk1"> </span><span class="mtk12">md</span><span class="mtk1">=</span><span class="mtk4">{</span><span class="mtk7">4</span><span class="mtk4">}</span><span class="mtk1"> </span><span class="mtk12">lg</span><span class="mtk1">=</span><span class="mtk4">{</span><span class="mtk7">3</span><span class="mtk4">}</span><span class="mtk17">&gt;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk17">&lt;</span><span class="mtk10">Card</span><span class="mtk17">&gt;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk17">&lt;</span><span class="mtk10">CardMedia</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">component</span><span class="mtk1">=</span><span class="mtk8">&quot;img&quot;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">height</span><span class="mtk1">=</span><span class="mtk8">&quot;140&quot;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">image</span><span class="mtk1">=</span><span class="mtk8">&quot;https://via.placeholder.com/200&quot;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">alt</span><span class="mtk1">=</span><span class="mtk8">&quot;placeholder&quot;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk17">/&gt;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk17">&lt;</span><span class="mtk10">CardContent</span><span class="mtk17">&gt;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk17">&lt;</span><span class="mtk10">Typography</span><span class="mtk1"> </span><span class="mtk12">gutterBottom</span><span class="mtk1"> </span><span class="mtk12">variant</span><span class="mtk1">=</span><span class="mtk8">&quot;h5&quot;</span><span class="mtk1"> </span><span class="mtk12">component</span><span class="mtk1">=</span><span class="mtk8">&quot;div&quot;</span><span class="mtk17">&gt;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> Card Title </span><span class="mtk4">{</span><span class="mtk12">index</span><span class="mtk1"> + </span><span class="mtk7">1</span><span class="mtk4">}</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk17">&lt;/</span><span class="mtk10">Typography</span><span class="mtk17">&gt;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk17">&lt;</span><span class="mtk10">Typography</span><span class="mtk1"> </span><span class="mtk12">variant</span><span class="mtk1">=</span><span class="mtk8">&quot;body2&quot;</span><span class="mtk1"> </span><span class="mtk12">color</span><span class="mtk1">=</span><span class="mtk8">&quot;text.secondary&quot;</span><span class="mtk17">&gt;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> This is a media card. You can use this section to describe</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> the content.</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk17">&lt;/</span><span class="mtk10">Typography</span><span class="mtk17">&gt;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk17">&lt;/</span><span class="mtk10">CardContent</span><span class="mtk17">&gt;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk17">&lt;/</span><span class="mtk10">Card</span><span class="mtk17">&gt;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk17">&lt;/</span><span class="mtk10">Grid</span><span class="mtk17">&gt;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> ))</span><span class="mtk4">}</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk17">&lt;/</span><span class="mtk10">Grid</span><span class="mtk17">&gt;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk4">{</span><span class="mtk3">/* Footer */</span><span class="mtk4">}</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk17">&lt;</span><span class="mtk10">Grid</span><span class="mtk1"> </span><span class="mtk12">item</span><span class="mtk1"> </span><span class="mtk12">xs</span><span class="mtk1">=</span><span class="mtk4">{</span><span class="mtk7">12</span><span class="mtk4">}</span><span class="mtk17">&gt;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk17">&lt;</span><span class="mtk10">Paper</span><span class="mtk1"> </span><span class="mtk12">sx</span><span class="mtk1">=</span><span class="mtk4">{</span><span class="mtk1">{ </span><span class="mtk12">p:</span><span class="mtk1"> </span><span class="mtk7">2</span><span class="mtk1">, </span><span class="mtk12">textAlign:</span><span class="mtk1"> </span><span class="mtk8">&quot;center&quot;</span><span class="mtk1"> }</span><span class="mtk4">}</span><span class="mtk17">&gt;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk17">&lt;</span><span class="mtk10">Typography</span><span class="mtk1"> </span><span class="mtk12">variant</span><span class="mtk1">=</span><span class="mtk8">&quot;body1&quot;</span><span class="mtk17">&gt;</span><span class="mtk1">Page Footer</span><span class="mtk17">&lt;/</span><span class="mtk10">Typography</span><span class="mtk17">&gt;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk17">&lt;/</span><span class="mtk10">Paper</span><span class="mtk17">&gt;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk17">&lt;/</span><span class="mtk10">Grid</span><span class="mtk17">&gt;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk17">&lt;/</span><span class="mtk10">Grid</span><span class="mtk17">&gt;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk17">&lt;/</span><span class="mtk10">Container</span><span class="mtk17">&gt;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> );</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1">}</span></span></span> <span class="grvsc-line"><span class="grvsc-source"></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk15">export</span><span class="mtk1"> </span><span class="mtk15">default</span><span class="mtk1"> </span><span class="mtk12">PageLayout</span><span class="mtk1">;</span></span></span></code></pre> <div id="CompletePageLayout" data-code data-height="800px" data-resize style="display:flex;justify-content: center;"></div> <p>We can see how the layout adapts to different screen sizes when adjusting the screen size. The sidenav switches from a list to a dropdown on smaller screens, and the number of cards per row changes based on the screen size.</p> <h2 id="summary" style="position:relative;"><a href="#summary" aria-label="summary permalink" class="anchor before"><svg aria-hidden="true" focusable="false" height="16" version="1.1" viewBox="0 0 16 16" width="16"><path fill-rule="evenodd" d="M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z"></path></svg></a>Summary</h2> <p>The MUI Grid component is a powerful way for creating responsive layouts in React applications. By leveraging the 12-column grid system and responsive breakpoints, we can easily design flexible, user-friendly interfaces that adapt to various screen sizes.</p> <p>Bye for now and happy coding!</p> <style class="grvsc-styles"> .grvsc-container { overflow: auto; position: relative; -webkit-overflow-scrolling: touch; padding-top: 1rem; padding-top: var(--grvsc-padding-top, var(--grvsc-padding-v, 1rem)); padding-bottom: 1rem; padding-bottom: var(--grvsc-padding-bottom, var(--grvsc-padding-v, 1rem)); border-radius: 8px; border-radius: var(--grvsc-border-radius, 8px); font-feature-settings: normal; line-height: 1.4; } .grvsc-code { display: table; } .grvsc-line { display: table-row; box-sizing: border-box; width: 100%; position: relative; } .grvsc-line > * { position: relative; } .grvsc-gutter-pad { display: table-cell; padding-left: 0.75rem; padding-left: calc(var(--grvsc-padding-left, var(--grvsc-padding-h, 1.5rem)) / 2); } .grvsc-gutter { display: table-cell; -webkit-user-select: none; -moz-user-select: none; user-select: none; } .grvsc-gutter::before { content: attr(data-content); } .grvsc-source { display: table-cell; padding-left: 1.5rem; padding-left: var(--grvsc-padding-left, var(--grvsc-padding-h, 1.5rem)); padding-right: 1.5rem; padding-right: var(--grvsc-padding-right, var(--grvsc-padding-h, 1.5rem)); } .grvsc-source:empty::after { content: ' '; -webkit-user-select: none; -moz-user-select: none; user-select: none; } .grvsc-gutter + .grvsc-source { padding-left: 0.75rem; padding-left: calc(var(--grvsc-padding-left, var(--grvsc-padding-h, 1.5rem)) / 2); } /* Line transformer styles */ .grvsc-has-line-highlighting > .grvsc-code > .grvsc-line::before { content: ' '; position: absolute; width: 100%; } .grvsc-line-diff-add::before { background-color: var(--grvsc-line-diff-add-background-color, rgba(0, 255, 60, 0.2)); } .grvsc-line-diff-del::before { background-color: var(--grvsc-line-diff-del-background-color, rgba(255, 0, 20, 0.2)); } .grvsc-line-number { padding: 0 2px; text-align: right; opacity: 0.7; } .default-dark { background-color: #1E1E1E; color: #D4D4D4; } .default-dark .mtk15 { color: #C586C0; } .default-dark .mtk1 { color: #D4D4D4; } .default-dark .mtk12 { color: #9CDCFE; } .default-dark .mtk8 { color: #CE9178; } .default-dark .mtk4 { color: #569CD6; } .default-dark .mtk11 { color: #DCDCAA; } .default-dark .mtk17 { color: #808080; } .default-dark .mtk10 { color: #4EC9B0; } .default-dark .mtk7 { color: #B5CEA8; } .default-dark .mtk3 { color: #6A9955; } .default-dark .grvsc-line-highlighted::before { background-color: var(--grvsc-line-highlighted-background-color, rgba(255, 255, 255, 0.1)); box-shadow: inset var(--grvsc-line-highlighted-border-width, 4px) 0 0 0 var(--grvsc-line-highlighted-border-color, rgba(255, 255, 255, 0.5)); } </style><![CDATA[How to Create a Responsive Table with React]]>https://muhimasri.comreact-responsive-tablehttps://muhimasri.comreact-responsive-table<p>In web development, tables are a core element for displaying tabular data, integral to numerous projects and applications. However, traditional HTML tables don’t automatically adjust to different screen sizes, which could cause usability issues in mobile and tablet environments.</p> <p>This tutorial will cover two practical approaches to creating a responsive table in React applications.</p> <ul> <li> <p><strong>Table Scroll</strong>: This approach involves adding horizontal scrolling to tables on smaller screens.</p> </li> <li> <p><strong>Altering Table Layout</strong>: This method includes hiding the table header and rearranging the table cells so that headers and cells are displayed vertically in each row.</p> </li> </ul> <video width="720" height="400" autoplay loop muted playsinline preload="none"> <source src="/097d9862042e6efcec9a995cd5ebb089/responsive-tables.mp4" type="video/mp4"> </video> <h2 id="creating-a-basic-table" style="position:relative;"><a href="#creating-a-basic-table" aria-label="creating a basic table permalink" class="anchor before"><svg aria-hidden="true" focusable="false" height="16" version="1.1" viewBox="0 0 16 16" width="16"><path fill-rule="evenodd" d="M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z"></path></svg></a>Creating a Basic Table</h2> <p>Before we dive into making our table responsive, let’s begin by constructing a bare table in React. We will create a table to display a list of student records. Each record will include the following information:</p> <ul> <li>Student ID</li> <li>Name</li> <li>Date of Birth</li> <li>Major</li> </ul> <h4 id="step-1-define-the-data" style="position:relative;"><a href="#step-1-define-the-data" aria-label="step 1 define the data permalink" class="anchor before"><svg aria-hidden="true" focusable="false" height="16" version="1.1" viewBox="0 0 16 16" width="16"><path fill-rule="evenodd" d="M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z"></path></svg></a>Step 1: Define the Data</h4> <p>First, we need to define our data. We’ll create an array of student records that we’ll use to populate the table. Each record will be an object with properties corresponding to the table’s columns.</p> <pre class="grvsc-container default-dark" data-language="jsx" data-index="0"><code class="grvsc-code"><span class="grvsc-line"><span class="grvsc-source"><span class="mtk4">const</span><span class="mtk1"> </span><span class="mtk12">students</span><span class="mtk1"> = [</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> {</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">id:</span><span class="mtk1"> </span><span class="mtk7">1</span><span class="mtk1">,</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">name:</span><span class="mtk1"> </span><span class="mtk8">&quot;Alice Johnson&quot;</span><span class="mtk1">,</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">dob:</span><span class="mtk1"> </span><span class="mtk8">&quot;2001-04-15&quot;</span><span class="mtk1">,</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">major:</span><span class="mtk1"> </span><span class="mtk8">&quot;Computer Science&quot;</span><span class="mtk1">,</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> },</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> { </span><span class="mtk12">id:</span><span class="mtk1"> </span><span class="mtk7">2</span><span class="mtk1">, </span><span class="mtk12">name:</span><span class="mtk1"> </span><span class="mtk8">&quot;Bob Smith&quot;</span><span class="mtk1">, </span><span class="mtk12">dob:</span><span class="mtk1"> </span><span class="mtk8">&quot;2000-09-08&quot;</span><span class="mtk1">, </span><span class="mtk12">major:</span><span class="mtk1"> </span><span class="mtk8">&quot;Mathematics&quot;</span><span class="mtk1"> },</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> { </span><span class="mtk12">id:</span><span class="mtk1"> </span><span class="mtk7">3</span><span class="mtk1">, </span><span class="mtk12">name:</span><span class="mtk1"> </span><span class="mtk8">&quot;Carol Williams&quot;</span><span class="mtk1">, </span><span class="mtk12">dob:</span><span class="mtk1"> </span><span class="mtk8">&quot;1999-02-23&quot;</span><span class="mtk1">, </span><span class="mtk12">major:</span><span class="mtk1"> </span><span class="mtk8">&quot;Physics&quot;</span><span class="mtk1"> },</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk3">// Add more student records as needed</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1">];</span></span></span></code></pre> <h4 id="step-2-build-the-table-component" style="position:relative;"><a href="#step-2-build-the-table-component" aria-label="step 2 build the table component permalink" class="anchor before"><svg aria-hidden="true" focusable="false" height="16" version="1.1" viewBox="0 0 16 16" width="16"><path fill-rule="evenodd" d="M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z"></path></svg></a>Step 2: Build the Table Component</h4> <p>Next, let’s create a table component that loops through this data and displays each student’s details in a row.</p> <pre class="grvsc-container default-dark" data-language="jsx" data-index="1"><code class="grvsc-code"><span class="grvsc-line"><span class="grvsc-source"><span class="mtk4">const</span><span class="mtk1"> </span><span class="mtk11">StudentTable</span><span class="mtk1"> = () </span><span class="mtk4">=&gt;</span><span class="mtk1"> {</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk15">return</span><span class="mtk1"> (</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk17">&lt;</span><span class="mtk4">table</span><span class="mtk17">&gt;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk17">&lt;</span><span class="mtk4">thead</span><span class="mtk17">&gt;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk17">&lt;</span><span class="mtk4">tr</span><span class="mtk17">&gt;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk17">&lt;</span><span class="mtk4">th</span><span class="mtk17">&gt;</span><span class="mtk1">Student ID</span><span class="mtk17">&lt;/</span><span class="mtk4">th</span><span class="mtk17">&gt;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk17">&lt;</span><span class="mtk4">th</span><span class="mtk17">&gt;</span><span class="mtk1">Name</span><span class="mtk17">&lt;/</span><span class="mtk4">th</span><span class="mtk17">&gt;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk17">&lt;</span><span class="mtk4">th</span><span class="mtk17">&gt;</span><span class="mtk1">Date of Birth</span><span class="mtk17">&lt;/</span><span class="mtk4">th</span><span class="mtk17">&gt;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk17">&lt;</span><span class="mtk4">th</span><span class="mtk17">&gt;</span><span class="mtk1">Major</span><span class="mtk17">&lt;/</span><span class="mtk4">th</span><span class="mtk17">&gt;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk17">&lt;/</span><span class="mtk4">tr</span><span class="mtk17">&gt;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk17">&lt;/</span><span class="mtk4">thead</span><span class="mtk17">&gt;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk17">&lt;</span><span class="mtk4">tbody</span><span class="mtk17">&gt;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk4">{</span><span class="mtk12">students</span><span class="mtk1">.</span><span class="mtk11">map</span><span class="mtk1">(</span><span class="mtk12">student</span><span class="mtk1"> </span><span class="mtk4">=&gt;</span><span class="mtk1"> (</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk17">&lt;</span><span class="mtk4">tr</span><span class="mtk1"> </span><span class="mtk12">key</span><span class="mtk1">=</span><span class="mtk4">{</span><span class="mtk12">student</span><span class="mtk1">.</span><span class="mtk12">id</span><span class="mtk4">}</span><span class="mtk17">&gt;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk17">&lt;</span><span class="mtk4">td</span><span class="mtk17">&gt;</span><span class="mtk4">{</span><span class="mtk12">student</span><span class="mtk1">.</span><span class="mtk12">id</span><span class="mtk4">}</span><span class="mtk17">&lt;/</span><span class="mtk4">td</span><span class="mtk17">&gt;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk17">&lt;</span><span class="mtk4">td</span><span class="mtk17">&gt;</span><span class="mtk4">{</span><span class="mtk12">student</span><span class="mtk1">.</span><span class="mtk12">name</span><span class="mtk4">}</span><span class="mtk17">&lt;/</span><span class="mtk4">td</span><span class="mtk17">&gt;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk17">&lt;</span><span class="mtk4">td</span><span class="mtk17">&gt;</span><span class="mtk4">{</span><span class="mtk12">student</span><span class="mtk1">.</span><span class="mtk12">dob</span><span class="mtk4">}</span><span class="mtk17">&lt;/</span><span class="mtk4">td</span><span class="mtk17">&gt;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk17">&lt;</span><span class="mtk4">td</span><span class="mtk17">&gt;</span><span class="mtk4">{</span><span class="mtk12">student</span><span class="mtk1">.</span><span class="mtk12">major</span><span class="mtk4">}</span><span class="mtk17">&lt;/</span><span class="mtk4">td</span><span class="mtk17">&gt;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk17">&lt;/</span><span class="mtk4">tr</span><span class="mtk17">&gt;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> ))</span><span class="mtk4">}</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk17">&lt;/</span><span class="mtk4">tbody</span><span class="mtk17">&gt;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk17">&lt;/</span><span class="mtk4">table</span><span class="mtk17">&gt;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> );</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1">};</span></span></span></code></pre> <h4 id="step-3-styling-the-table" style="position:relative;"><a href="#step-3-styling-the-table" aria-label="step 3 styling the table permalink" class="anchor before"><svg aria-hidden="true" focusable="false" height="16" version="1.1" viewBox="0 0 16 16" width="16"><path fill-rule="evenodd" d="M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z"></path></svg></a>Step 3: Styling the Table</h4> <p>To ensure our table is functional and visually appealing, we’ll add some basic CSS styling. This will include setting a font family, adding borders to the table and rows, alternating the background color of rows for better readability, and ensuring proper padding for text.</p> <pre class="grvsc-container default-dark" data-language="css" data-index="2"><code class="grvsc-code"><span class="grvsc-line"><span class="grvsc-source"><span class="mtk6">table</span><span class="mtk1"> {</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">font-family</span><span class="mtk1">: </span><span class="mtk8">Arial</span><span class="mtk1">, </span><span class="mtk8">sans-serif</span><span class="mtk1">;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">border-collapse</span><span class="mtk1">: </span><span class="mtk8">collapse</span><span class="mtk1">;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">width</span><span class="mtk1">: </span><span class="mtk7">100%</span><span class="mtk1">;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">border</span><span class="mtk1">: </span><span class="mtk7">1px</span><span class="mtk1"> </span><span class="mtk8">solid</span><span class="mtk1"> </span><span class="mtk8">#ddd</span><span class="mtk1">;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1">}</span></span></span> <span class="grvsc-line"><span class="grvsc-source"></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk6">tr</span><span class="mtk1"> {</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">border-bottom</span><span class="mtk1">: </span><span class="mtk7">1px</span><span class="mtk1"> </span><span class="mtk8">solid</span><span class="mtk1"> </span><span class="mtk8">#ccc</span><span class="mtk1">;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1">}</span></span></span> <span class="grvsc-line"><span class="grvsc-source"></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk6">th</span><span class="mtk1">,</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk6">td</span><span class="mtk1"> {</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">text-align</span><span class="mtk1">: </span><span class="mtk8">left</span><span class="mtk1">;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">padding</span><span class="mtk1">: </span><span class="mtk7">8px</span><span class="mtk1">;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1">}</span></span></span> <span class="grvsc-line"><span class="grvsc-source"></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk6">tr:nth-child</span><span class="mtk1">(even) {</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">background-color</span><span class="mtk1">: </span><span class="mtk8">#f2f2f2</span><span class="mtk1">;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1">}</span></span></span></code></pre> <div id="ResponsiveStack" data-code data-height="200px" data-resize style="display:flex;justify-content: center;"></div> <p>In this basic example, if we try to resize the window using the resize handle in the bottom right corner, the table doesn’t adjust to the smaller screen size.</p> <h2 id="creating-a-responsive-scroll-table" style="position:relative;"><a href="#creating-a-responsive-scroll-table" aria-label="creating a responsive scroll table permalink" class="anchor before"><svg aria-hidden="true" focusable="false" height="16" version="1.1" viewBox="0 0 16 16" width="16"><path fill-rule="evenodd" d="M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z"></path></svg></a>Creating a Responsive Scroll Table</h2> <p>When it comes to enhancing a responsive table on smaller screens, implementing a horizontal scroll is a straightforward and effective solution. This approach maintains the layout’s consistency and allows users to view all columns by scrolling horizontally. Let’s go through the steps to create a scrollable table container.</p> <h4 id="step-1-add-a-scrollable-container" style="position:relative;"><a href="#step-1-add-a-scrollable-container" aria-label="step 1 add a scrollable container permalink" class="anchor before"><svg aria-hidden="true" focusable="false" height="16" version="1.1" viewBox="0 0 16 16" width="16"><path fill-rule="evenodd" d="M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z"></path></svg></a>Step 1: Add a Scrollable Container</h4> <p>First, we need to wrap our table with a container because the table element itself cannot be made scrollable directly. We create a “ghost” container around the table to enable scrolling.</p> <pre class="grvsc-container default-dark" data-language="jsx" data-index="3"><code class="grvsc-code"><span class="grvsc-line"><span class="grvsc-source"><span class="mtk4">const</span><span class="mtk1"> </span><span class="mtk11">ScrollableTableContainer</span><span class="mtk1"> = () </span><span class="mtk4">=&gt;</span><span class="mtk1"> {</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk15">return</span><span class="mtk1"> (</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk17">&lt;</span><span class="mtk4">div</span><span class="mtk1"> </span><span class="mtk12">className</span><span class="mtk1">=</span><span class="mtk8">&quot;table-container&quot;</span><span class="mtk17">&gt;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk17">&lt;</span><span class="mtk10">StudentTable</span><span class="mtk1"> </span><span class="mtk17">/&gt;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk17">&lt;/</span><span class="mtk4">div</span><span class="mtk17">&gt;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> );</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1">};</span></span></span></code></pre> <h4 id="step-2-css-for-horizontal-scrolling" style="position:relative;"><a href="#step-2-css-for-horizontal-scrolling" aria-label="step 2 css for horizontal scrolling permalink" class="anchor before"><svg aria-hidden="true" focusable="false" height="16" version="1.1" viewBox="0 0 16 16" width="16"><path fill-rule="evenodd" d="M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z"></path></svg></a>Step 2: CSS for Horizontal Scrolling</h4> <p>Next, we’ll add CSS to trigger a horizontal scrollbar when the table exceeds the viewport’s width. We do this by setting the <code>overflow-x</code> property to <code>auto</code>.</p> <pre class="grvsc-container default-dark" data-language="css" data-index="4"><code class="grvsc-code"><span class="grvsc-line"><span class="grvsc-source"><span class="mtk1">... </span></span></span> <span class="grvsc-line"><span class="grvsc-source"></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk6">.table-container</span><span class="mtk1"> {</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">overflow-x</span><span class="mtk1">: </span><span class="mtk8">auto</span><span class="mtk1">;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1">}</span></span></span></code></pre> <h4 id="step-3-prevent-text-wrapping" style="position:relative;"><a href="#step-3-prevent-text-wrapping" aria-label="step 3 prevent text wrapping permalink" class="anchor before"><svg aria-hidden="true" focusable="false" height="16" version="1.1" viewBox="0 0 16 16" width="16"><path fill-rule="evenodd" d="M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z"></path></svg></a>Step 3: Prevent Text Wrapping</h4> <p>Finally, to prevent the text within each table cell from wrapping and ensure a consistent layout as the user scrolls horizontally, we’ll set <code>white-space: nowrap</code> on the table cells.</p> <pre class="grvsc-container default-dark" data-language="css" data-index="5"><code class="grvsc-code"><span class="grvsc-line"><span class="grvsc-source"><span class="mtk1">... </span></span></span> <span class="grvsc-line"><span class="grvsc-source"></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk6">th</span><span class="mtk1">,</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk6">td</span><span class="mtk1"> {</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">white-space</span><span class="mtk1">: </span><span class="mtk8">nowrap</span><span class="mtk1">;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1">}</span></span></span></code></pre> <p>Here is the complete code for the scrollable table container:</p> <pre class="grvsc-container default-dark" data-language="css" data-index="6"><code class="grvsc-code"><span class="grvsc-line"><span class="grvsc-source"><span class="mtk6">.table-container</span><span class="mtk1"> {</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">overflow-x</span><span class="mtk1">: </span><span class="mtk8">auto</span><span class="mtk1">;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1">}</span></span></span> <span class="grvsc-line"><span class="grvsc-source"></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk6">table</span><span class="mtk1"> {</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">font-family</span><span class="mtk1">: </span><span class="mtk8">Arial</span><span class="mtk1">, </span><span class="mtk8">sans-serif</span><span class="mtk1">;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">border-collapse</span><span class="mtk1">: </span><span class="mtk8">collapse</span><span class="mtk1">;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">width</span><span class="mtk1">: </span><span class="mtk7">100%</span><span class="mtk1">;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">border</span><span class="mtk1">: </span><span class="mtk7">1px</span><span class="mtk1"> </span><span class="mtk8">solid</span><span class="mtk1"> </span><span class="mtk8">#ddd</span><span class="mtk1">;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1">}</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk6">tr</span><span class="mtk1"> {</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">border-bottom</span><span class="mtk1">: </span><span class="mtk7">1px</span><span class="mtk1"> </span><span class="mtk8">solid</span><span class="mtk1"> </span><span class="mtk8">#ccc</span><span class="mtk1">;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1">}</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk6">th</span><span class="mtk1">,</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk6">td</span><span class="mtk1"> {</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">text-align</span><span class="mtk1">: </span><span class="mtk8">left</span><span class="mtk1">;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">padding</span><span class="mtk1">: </span><span class="mtk7">8px</span><span class="mtk1">;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">white-space</span><span class="mtk1">: </span><span class="mtk8">nowrap</span><span class="mtk1">;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1">}</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk6">tr:nth-child</span><span class="mtk1">(even) {</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">background-color</span><span class="mtk1">: </span><span class="mtk8">#f2f2f2</span><span class="mtk1">;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1">}</span></span></span></code></pre> <pre class="grvsc-container default-dark" data-language="jsx" data-index="7"><code class="grvsc-code"><span class="grvsc-line"><span class="grvsc-source"><span class="mtk15">import</span><span class="mtk1"> </span><span class="mtk8">&quot;./App.css&quot;</span><span class="mtk1">;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk4">const</span><span class="mtk1"> </span><span class="mtk12">students</span><span class="mtk1"> = [</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> {</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">id:</span><span class="mtk1"> </span><span class="mtk7">1</span><span class="mtk1">,</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">name:</span><span class="mtk1"> </span><span class="mtk8">&quot;Alice Johnson&quot;</span><span class="mtk1">,</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">dob:</span><span class="mtk1"> </span><span class="mtk8">&quot;2001-04-15&quot;</span><span class="mtk1">,</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">major:</span><span class="mtk1"> </span><span class="mtk8">&quot;Computer Science&quot;</span><span class="mtk1">,</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> },</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> { </span><span class="mtk12">id:</span><span class="mtk1"> </span><span class="mtk7">2</span><span class="mtk1">, </span><span class="mtk12">name:</span><span class="mtk1"> </span><span class="mtk8">&quot;Bob Smith&quot;</span><span class="mtk1">, </span><span class="mtk12">dob:</span><span class="mtk1"> </span><span class="mtk8">&quot;2000-09-08&quot;</span><span class="mtk1">, </span><span class="mtk12">major:</span><span class="mtk1"> </span><span class="mtk8">&quot;Mathematics&quot;</span><span class="mtk1"> },</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> { </span><span class="mtk12">id:</span><span class="mtk1"> </span><span class="mtk7">3</span><span class="mtk1">, </span><span class="mtk12">name:</span><span class="mtk1"> </span><span class="mtk8">&quot;Carol Williams&quot;</span><span class="mtk1">, </span><span class="mtk12">dob:</span><span class="mtk1"> </span><span class="mtk8">&quot;1999-02-23&quot;</span><span class="mtk1">, </span><span class="mtk12">major:</span><span class="mtk1"> </span><span class="mtk8">&quot;Physics&quot;</span><span class="mtk1"> },</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk3">// Add more student records as needed</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1">];</span></span></span> <span class="grvsc-line"><span class="grvsc-source"></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk4">const</span><span class="mtk1"> </span><span class="mtk11">StudentTable</span><span class="mtk1"> = () </span><span class="mtk4">=&gt;</span><span class="mtk1"> {</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk15">return</span><span class="mtk1"> (</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk17">&lt;</span><span class="mtk4">table</span><span class="mtk17">&gt;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk17">&lt;</span><span class="mtk4">thead</span><span class="mtk17">&gt;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk17">&lt;</span><span class="mtk4">tr</span><span class="mtk17">&gt;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk17">&lt;</span><span class="mtk4">th</span><span class="mtk17">&gt;</span><span class="mtk1">Student ID</span><span class="mtk17">&lt;/</span><span class="mtk4">th</span><span class="mtk17">&gt;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk17">&lt;</span><span class="mtk4">th</span><span class="mtk17">&gt;</span><span class="mtk1">Name</span><span class="mtk17">&lt;/</span><span class="mtk4">th</span><span class="mtk17">&gt;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk17">&lt;</span><span class="mtk4">th</span><span class="mtk17">&gt;</span><span class="mtk1">Date of Birth</span><span class="mtk17">&lt;/</span><span class="mtk4">th</span><span class="mtk17">&gt;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk17">&lt;</span><span class="mtk4">th</span><span class="mtk17">&gt;</span><span class="mtk1">Major</span><span class="mtk17">&lt;/</span><span class="mtk4">th</span><span class="mtk17">&gt;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk17">&lt;/</span><span class="mtk4">tr</span><span class="mtk17">&gt;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk17">&lt;/</span><span class="mtk4">thead</span><span class="mtk17">&gt;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk17">&lt;</span><span class="mtk4">tbody</span><span class="mtk17">&gt;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk4">{</span><span class="mtk12">students</span><span class="mtk1">.</span><span class="mtk11">map</span><span class="mtk1">(</span><span class="mtk12">student</span><span class="mtk1"> </span><span class="mtk4">=&gt;</span><span class="mtk1"> (</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk17">&lt;</span><span class="mtk4">tr</span><span class="mtk1"> </span><span class="mtk12">key</span><span class="mtk1">=</span><span class="mtk4">{</span><span class="mtk12">student</span><span class="mtk1">.</span><span class="mtk12">id</span><span class="mtk4">}</span><span class="mtk17">&gt;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk17">&lt;</span><span class="mtk4">td</span><span class="mtk17">&gt;</span><span class="mtk4">{</span><span class="mtk12">student</span><span class="mtk1">.</span><span class="mtk12">id</span><span class="mtk4">}</span><span class="mtk17">&lt;/</span><span class="mtk4">td</span><span class="mtk17">&gt;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk17">&lt;</span><span class="mtk4">td</span><span class="mtk17">&gt;</span><span class="mtk4">{</span><span class="mtk12">student</span><span class="mtk1">.</span><span class="mtk12">name</span><span class="mtk4">}</span><span class="mtk17">&lt;/</span><span class="mtk4">td</span><span class="mtk17">&gt;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk17">&lt;</span><span class="mtk4">td</span><span class="mtk17">&gt;</span><span class="mtk4">{</span><span class="mtk12">student</span><span class="mtk1">.</span><span class="mtk12">dob</span><span class="mtk4">}</span><span class="mtk17">&lt;/</span><span class="mtk4">td</span><span class="mtk17">&gt;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk17">&lt;</span><span class="mtk4">td</span><span class="mtk17">&gt;</span><span class="mtk4">{</span><span class="mtk12">student</span><span class="mtk1">.</span><span class="mtk12">major</span><span class="mtk4">}</span><span class="mtk17">&lt;/</span><span class="mtk4">td</span><span class="mtk17">&gt;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk17">&lt;/</span><span class="mtk4">tr</span><span class="mtk17">&gt;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> ))</span><span class="mtk4">}</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk17">&lt;/</span><span class="mtk4">tbody</span><span class="mtk17">&gt;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk17">&lt;/</span><span class="mtk4">table</span><span class="mtk17">&gt;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> );</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1">};</span></span></span> <span class="grvsc-line"><span class="grvsc-source"></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk4">const</span><span class="mtk1"> </span><span class="mtk11">ScrollableTableContainer</span><span class="mtk1"> = () </span><span class="mtk4">=&gt;</span><span class="mtk1"> {</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk15">return</span><span class="mtk1"> (</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk17">&lt;</span><span class="mtk4">div</span><span class="mtk1"> </span><span class="mtk12">className</span><span class="mtk1">=</span><span class="mtk8">&quot;table-container&quot;</span><span class="mtk17">&gt;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk17">&lt;</span><span class="mtk10">StudentTable</span><span class="mtk1"> </span><span class="mtk17">/&gt;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk17">&lt;/</span><span class="mtk4">div</span><span class="mtk17">&gt;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> );</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1">};</span></span></span> <span class="grvsc-line"><span class="grvsc-source"></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk15">export</span><span class="mtk1"> </span><span class="mtk15">default</span><span class="mtk1"> </span><span class="mtk4">function</span><span class="mtk1"> </span><span class="mtk11">App</span><span class="mtk1">() {</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk15">return</span><span class="mtk1"> </span><span class="mtk17">&lt;</span><span class="mtk10">ScrollableTableContainer</span><span class="mtk1"> </span><span class="mtk17">/&gt;</span><span class="mtk1">;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1">}</span></span></span></code></pre> <div id="ScrollableTableContainer" data-code data-height="200px" data-width="200px" data-resize style="display:flex;justify-content: center;"></div> <h2 id="altering-table-layout" style="position:relative;"><a href="#altering-table-layout" aria-label="altering table layout permalink" class="anchor before"><svg aria-hidden="true" focusable="false" height="16" version="1.1" viewBox="0 0 16 16" width="16"><path fill-rule="evenodd" d="M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z"></path></svg></a>Altering Table Layout</h2> <p>We can alter the table’s layout for a more mobile-friendly design that eliminates the need for horizontal scrolling. This approach involves hiding the table headers and changing the data cells of each row to stack vertically instead of horizontally. Let’s go through the necessary steps to achieve this:</p> <h4 id="step-1-hide-table-headers-on-small-screens" style="position:relative;"><a href="#step-1-hide-table-headers-on-small-screens" aria-label="step 1 hide table headers on small screens permalink" class="anchor before"><svg aria-hidden="true" focusable="false" height="16" version="1.1" viewBox="0 0 16 16" width="16"><path fill-rule="evenodd" d="M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z"></path></svg></a>Step 1: Hide Table Headers on Small Screens</h4> <p>First, we’ll use a CSS media query to hide the table headers when the screen size is at or below a certain width, typically that of a small tablet or a mobile phone.</p> <pre class="grvsc-container default-dark" data-language="css" data-index="8"><code class="grvsc-code"><span class="grvsc-line"><span class="grvsc-source"><span class="mtk1">...</span></span></span> <span class="grvsc-line"><span class="grvsc-source"></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk15">@media</span><span class="mtk1"> </span><span class="mtk8">screen</span><span class="mtk1"> and (</span><span class="mtk12">max-width</span><span class="mtk1">: </span><span class="mtk7">600px</span><span class="mtk1">) {</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk6">th</span><span class="mtk1"> {</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">display</span><span class="mtk1">: </span><span class="mtk8">none</span><span class="mtk1">;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> }</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1">}</span></span></span></code></pre> <h4 id="step-2-change-data-cell-display-on-small-screens" style="position:relative;"><a href="#step-2-change-data-cell-display-on-small-screens" aria-label="step 2 change data cell display on small screens permalink" class="anchor before"><svg aria-hidden="true" focusable="false" height="16" version="1.1" viewBox="0 0 16 16" width="16"><path fill-rule="evenodd" d="M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z"></path></svg></a>Step 2: Change Data Cell Display on Small Screens</h4> <p>Next, we need to adjust the display of the table cells (<code>td</code>) in the table body. On smaller screens, we’ll change their display from <code>table-cell</code> to <code>flex</code>. This change allows the data to stack on top of each other within each row, making it more readable on mobile devices.</p> <pre class="grvsc-container default-dark" data-language="css" data-index="9"><code class="grvsc-code"><span class="grvsc-line"><span class="grvsc-source"><span class="mtk1">...</span></span></span> <span class="grvsc-line"><span class="grvsc-source"></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk15">@media</span><span class="mtk1"> </span><span class="mtk8">screen</span><span class="mtk1"> and (</span><span class="mtk12">max-width</span><span class="mtk1">: </span><span class="mtk7">600px</span><span class="mtk1">) {</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> ...</span></span></span> <span class="grvsc-line"><span class="grvsc-source"></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk6">td</span><span class="mtk1"> {</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">display</span><span class="mtk1">: </span><span class="mtk8">flex</span><span class="mtk1">;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> }</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1">}</span></span></span></code></pre> <h4 id="step-3-add-header-names-to-each-cell" style="position:relative;"><a href="#step-3-add-header-names-to-each-cell" aria-label="step 3 add header names to each cell permalink" class="anchor before"><svg aria-hidden="true" focusable="false" height="16" version="1.1" viewBox="0 0 16 16" width="16"><path fill-rule="evenodd" d="M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z"></path></svg></a>Step 3: Add Header Names to Each Cell</h4> <p>Since we removed the main table headers, we’ll add a label to each cell indicating what data it represents. These labels will only be visible on small screens and act as a substitute for the table headers. Also, the styling should be updated to make the labels and data more distinguishable.</p> <pre class="grvsc-container default-dark" data-language="jsx" data-index="10"><code class="grvsc-code"><span class="grvsc-line"><span class="grvsc-source"><span class="mtk4">const</span><span class="mtk1"> </span><span class="mtk11">StudentTableResponsive</span><span class="mtk1"> = () </span><span class="mtk4">=&gt;</span><span class="mtk1"> {</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk15">return</span><span class="mtk1"> (</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk17">&lt;</span><span class="mtk4">table</span><span class="mtk17">&gt;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk17">&lt;</span><span class="mtk4">thead</span><span class="mtk17">&gt;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk17">&lt;</span><span class="mtk4">tr</span><span class="mtk17">&gt;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk17">&lt;</span><span class="mtk4">th</span><span class="mtk17">&gt;</span><span class="mtk1">Student ID</span><span class="mtk17">&lt;/</span><span class="mtk4">th</span><span class="mtk17">&gt;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk17">&lt;</span><span class="mtk4">th</span><span class="mtk17">&gt;</span><span class="mtk1">Name</span><span class="mtk17">&lt;/</span><span class="mtk4">th</span><span class="mtk17">&gt;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk17">&lt;</span><span class="mtk4">th</span><span class="mtk17">&gt;</span><span class="mtk1">Date of Birth</span><span class="mtk17">&lt;/</span><span class="mtk4">th</span><span class="mtk17">&gt;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk17">&lt;</span><span class="mtk4">th</span><span class="mtk17">&gt;</span><span class="mtk1">Major</span><span class="mtk17">&lt;/</span><span class="mtk4">th</span><span class="mtk17">&gt;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk17">&lt;/</span><span class="mtk4">tr</span><span class="mtk17">&gt;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk17">&lt;/</span><span class="mtk4">thead</span><span class="mtk17">&gt;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk17">&lt;</span><span class="mtk4">tbody</span><span class="mtk17">&gt;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk4">{</span><span class="mtk12">students</span><span class="mtk1">.</span><span class="mtk11">map</span><span class="mtk1">(</span><span class="mtk12">student</span><span class="mtk1"> </span><span class="mtk4">=&gt;</span><span class="mtk1"> (</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk17">&lt;</span><span class="mtk4">tr</span><span class="mtk1"> </span><span class="mtk12">key</span><span class="mtk1">=</span><span class="mtk4">{</span><span class="mtk12">student</span><span class="mtk1">.</span><span class="mtk12">id</span><span class="mtk4">}</span><span class="mtk17">&gt;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk17">&lt;</span><span class="mtk4">td</span><span class="mtk17">&gt;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk17">&lt;</span><span class="mtk4">span</span><span class="mtk1"> </span><span class="mtk12">className</span><span class="mtk1">=</span><span class="mtk8">&quot;cell-header&quot;</span><span class="mtk17">&gt;</span><span class="mtk1">Student ID:</span><span class="mtk17">&lt;/</span><span class="mtk4">span</span><span class="mtk17">&gt;</span><span class="mtk1"> </span><span class="mtk4">{</span><span class="mtk12">student</span><span class="mtk1">.</span><span class="mtk12">id</span><span class="mtk4">}</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk17">&lt;/</span><span class="mtk4">td</span><span class="mtk17">&gt;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk17">&lt;</span><span class="mtk4">td</span><span class="mtk17">&gt;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk17">&lt;</span><span class="mtk4">span</span><span class="mtk1"> </span><span class="mtk12">className</span><span class="mtk1">=</span><span class="mtk8">&quot;cell-header&quot;</span><span class="mtk17">&gt;</span><span class="mtk1">Name:</span><span class="mtk17">&lt;/</span><span class="mtk4">span</span><span class="mtk17">&gt;</span><span class="mtk1"> </span><span class="mtk4">{</span><span class="mtk12">student</span><span class="mtk1">.</span><span class="mtk12">name</span><span class="mtk4">}</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk17">&lt;/</span><span class="mtk4">td</span><span class="mtk17">&gt;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk17">&lt;</span><span class="mtk4">td</span><span class="mtk17">&gt;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk17">&lt;</span><span class="mtk4">span</span><span class="mtk1"> </span><span class="mtk12">className</span><span class="mtk1">=</span><span class="mtk8">&quot;cell-header&quot;</span><span class="mtk17">&gt;</span><span class="mtk1">Date of Birth:</span><span class="mtk17">&lt;/</span><span class="mtk4">span</span><span class="mtk17">&gt;</span><span class="mtk1"> </span><span class="mtk4">{</span><span class="mtk12">student</span><span class="mtk1">.</span><span class="mtk12">dob</span><span class="mtk4">}</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk17">&lt;/</span><span class="mtk4">td</span><span class="mtk17">&gt;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk17">&lt;</span><span class="mtk4">td</span><span class="mtk17">&gt;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk17">&lt;</span><span class="mtk4">span</span><span class="mtk1"> </span><span class="mtk12">className</span><span class="mtk1">=</span><span class="mtk8">&quot;cell-header&quot;</span><span class="mtk17">&gt;</span><span class="mtk1">Major:</span><span class="mtk17">&lt;/</span><span class="mtk4">span</span><span class="mtk17">&gt;</span><span class="mtk1"> </span><span class="mtk4">{</span><span class="mtk12">student</span><span class="mtk1">.</span><span class="mtk12">major</span><span class="mtk4">}</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk17">&lt;/</span><span class="mtk4">td</span><span class="mtk17">&gt;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk17">&lt;/</span><span class="mtk4">tr</span><span class="mtk17">&gt;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> ))</span><span class="mtk4">}</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk17">&lt;/</span><span class="mtk4">tbody</span><span class="mtk17">&gt;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk17">&lt;/</span><span class="mtk4">table</span><span class="mtk17">&gt;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> );</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1">};</span></span></span></code></pre> <pre class="grvsc-container grvsc-has-line-highlighting default-dark" data-language="css" data-index="11"><code class="grvsc-code"><span class="grvsc-line"><span class="grvsc-source"><span class="mtk1">... </span></span></span> <span class="grvsc-line"><span class="grvsc-source"></span></span> <span class="grvsc-line grvsc-line-highlighted"><span class="grvsc-source"><span class="mtk6">.cell-header</span><span class="mtk1"> {</span></span></span> <span class="grvsc-line grvsc-line-highlighted"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">display</span><span class="mtk1">: </span><span class="mtk8">none</span><span class="mtk1">;</span></span></span> <span class="grvsc-line grvsc-line-highlighted"><span class="grvsc-source"><span class="mtk1">}</span></span></span> <span class="grvsc-line"><span class="grvsc-source"></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk15">@media</span><span class="mtk1"> </span><span class="mtk8">screen</span><span class="mtk1"> and (</span><span class="mtk12">max-width</span><span class="mtk1">: </span><span class="mtk7">600px</span><span class="mtk1">) {</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> ... </span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span></span></span> <span class="grvsc-line grvsc-line-highlighted"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk6">.cell-header</span><span class="mtk1"> {</span></span></span> <span class="grvsc-line grvsc-line-highlighted"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">display</span><span class="mtk1">: </span><span class="mtk8">block</span><span class="mtk1">;</span></span></span> <span class="grvsc-line grvsc-line-highlighted"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">font-weight</span><span class="mtk1">: </span><span class="mtk8">bold</span><span class="mtk1">;</span></span></span> <span class="grvsc-line grvsc-line-highlighted"><span class="grvsc-source"><span class="mtk1"> }</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk6">td</span><span class="mtk1"> {</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">display</span><span class="mtk1">: </span><span class="mtk8">flex</span><span class="mtk1">;</span></span></span> <span class="grvsc-line grvsc-line-highlighted"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">justify-content</span><span class="mtk1">: </span><span class="mtk8">space-between</span><span class="mtk1">;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> }</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1">}</span></span></span></code></pre> <p>Here is the complete code for the responsive table layout:</p> <pre class="grvsc-container default-dark" data-language="css" data-index="12"><code class="grvsc-code"><span class="grvsc-line"><span class="grvsc-source"><span class="mtk6">table</span><span class="mtk1"> {</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">font-family</span><span class="mtk1">: </span><span class="mtk8">Arial</span><span class="mtk1">, </span><span class="mtk8">sans-serif</span><span class="mtk1">;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">border-collapse</span><span class="mtk1">: </span><span class="mtk8">collapse</span><span class="mtk1">;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">width</span><span class="mtk1">: </span><span class="mtk7">100%</span><span class="mtk1">;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">border</span><span class="mtk1">: </span><span class="mtk7">1px</span><span class="mtk1"> </span><span class="mtk8">solid</span><span class="mtk1"> </span><span class="mtk8">#ddd</span><span class="mtk1">;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1">}</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk6">tr</span><span class="mtk1"> {</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">border-bottom</span><span class="mtk1">: </span><span class="mtk7">1px</span><span class="mtk1"> </span><span class="mtk8">solid</span><span class="mtk1"> </span><span class="mtk8">#ccc</span><span class="mtk1">;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1">}</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk6">th</span><span class="mtk1">,</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk6">td</span><span class="mtk1"> {</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">text-align</span><span class="mtk1">: </span><span class="mtk8">left</span><span class="mtk1">;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">padding</span><span class="mtk1">: </span><span class="mtk7">8px</span><span class="mtk1">;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">white-space</span><span class="mtk1">: </span><span class="mtk8">nowrap</span><span class="mtk1">;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1">}</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk6">tr:nth-child</span><span class="mtk1">(even) {</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">background-color</span><span class="mtk1">: </span><span class="mtk8">#f2f2f2</span><span class="mtk1">;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1">}</span></span></span> <span class="grvsc-line"><span class="grvsc-source"></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk6">.cell-header</span><span class="mtk1"> {</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">display</span><span class="mtk1">: </span><span class="mtk8">none</span><span class="mtk1">;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1">}</span></span></span> <span class="grvsc-line"><span class="grvsc-source"></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk15">@media</span><span class="mtk1"> </span><span class="mtk8">screen</span><span class="mtk1"> and (</span><span class="mtk12">max-width</span><span class="mtk1">: </span><span class="mtk7">600px</span><span class="mtk1">) {</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk6">th</span><span class="mtk1"> {</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">display</span><span class="mtk1">: </span><span class="mtk8">none</span><span class="mtk1">;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> }</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk6">.cell-header</span><span class="mtk1"> {</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">display</span><span class="mtk1">: </span><span class="mtk8">block</span><span class="mtk1">;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">font-weight</span><span class="mtk1">: </span><span class="mtk8">bold</span><span class="mtk1">;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> }</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk6">td</span><span class="mtk1"> {</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">display</span><span class="mtk1">: </span><span class="mtk8">flex</span><span class="mtk1">;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">justify-content</span><span class="mtk1">: </span><span class="mtk8">space-between</span><span class="mtk1">;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> }</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1">}</span></span></span></code></pre> <pre class="grvsc-container default-dark" data-language="jsx" data-index="13"><code class="grvsc-code"><span class="grvsc-line"><span class="grvsc-source"><span class="mtk15">import</span><span class="mtk1"> </span><span class="mtk8">&#39;./App.css&#39;</span><span class="mtk1">;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk4">const</span><span class="mtk1"> </span><span class="mtk12">students</span><span class="mtk1"> = [</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> {</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">id:</span><span class="mtk1"> </span><span class="mtk7">1</span><span class="mtk1">,</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">name:</span><span class="mtk1"> </span><span class="mtk8">&#39;Alice Johnson&#39;</span><span class="mtk1">,</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">dob:</span><span class="mtk1"> </span><span class="mtk8">&#39;2001-04-15&#39;</span><span class="mtk1">,</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">major:</span><span class="mtk1"> </span><span class="mtk8">&#39;Computer Science&#39;</span><span class="mtk1">,</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> },</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> { </span><span class="mtk12">id:</span><span class="mtk1"> </span><span class="mtk7">2</span><span class="mtk1">, </span><span class="mtk12">name:</span><span class="mtk1"> </span><span class="mtk8">&#39;Bob Smith&#39;</span><span class="mtk1">, </span><span class="mtk12">dob:</span><span class="mtk1"> </span><span class="mtk8">&#39;2000-09-08&#39;</span><span class="mtk1">, </span><span class="mtk12">major:</span><span class="mtk1"> </span><span class="mtk8">&#39;Mathematics&#39;</span><span class="mtk1"> },</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> { </span><span class="mtk12">id:</span><span class="mtk1"> </span><span class="mtk7">3</span><span class="mtk1">, </span><span class="mtk12">name:</span><span class="mtk1"> </span><span class="mtk8">&#39;Carol Williams&#39;</span><span class="mtk1">, </span><span class="mtk12">dob:</span><span class="mtk1"> </span><span class="mtk8">&#39;1999-02-23&#39;</span><span class="mtk1">, </span><span class="mtk12">major:</span><span class="mtk1"> </span><span class="mtk8">&#39;Physics&#39;</span><span class="mtk1"> },</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk3">// Add more student records as needed</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1">];</span></span></span> <span class="grvsc-line"><span class="grvsc-source"></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk4">const</span><span class="mtk1"> </span><span class="mtk11">StudentTableResponsive</span><span class="mtk1"> = () </span><span class="mtk4">=&gt;</span><span class="mtk1"> {</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk15">return</span><span class="mtk1"> (</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk17">&lt;</span><span class="mtk4">table</span><span class="mtk17">&gt;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk17">&lt;</span><span class="mtk4">thead</span><span class="mtk17">&gt;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk17">&lt;</span><span class="mtk4">tr</span><span class="mtk17">&gt;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk17">&lt;</span><span class="mtk4">th</span><span class="mtk17">&gt;</span><span class="mtk1">Student ID</span><span class="mtk17">&lt;/</span><span class="mtk4">th</span><span class="mtk17">&gt;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk17">&lt;</span><span class="mtk4">th</span><span class="mtk17">&gt;</span><span class="mtk1">Name</span><span class="mtk17">&lt;/</span><span class="mtk4">th</span><span class="mtk17">&gt;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk17">&lt;</span><span class="mtk4">th</span><span class="mtk17">&gt;</span><span class="mtk1">Date of Birth</span><span class="mtk17">&lt;/</span><span class="mtk4">th</span><span class="mtk17">&gt;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk17">&lt;</span><span class="mtk4">th</span><span class="mtk17">&gt;</span><span class="mtk1">Major</span><span class="mtk17">&lt;/</span><span class="mtk4">th</span><span class="mtk17">&gt;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk17">&lt;/</span><span class="mtk4">tr</span><span class="mtk17">&gt;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk17">&lt;/</span><span class="mtk4">thead</span><span class="mtk17">&gt;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk17">&lt;</span><span class="mtk4">tbody</span><span class="mtk17">&gt;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk4">{</span><span class="mtk12">students</span><span class="mtk1">.</span><span class="mtk11">map</span><span class="mtk1">((</span><span class="mtk12">student</span><span class="mtk1">) </span><span class="mtk4">=&gt;</span><span class="mtk1"> (</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk17">&lt;</span><span class="mtk4">tr</span><span class="mtk1"> </span><span class="mtk12">key</span><span class="mtk1">=</span><span class="mtk4">{</span><span class="mtk12">student</span><span class="mtk1">.</span><span class="mtk12">id</span><span class="mtk4">}</span><span class="mtk17">&gt;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk17">&lt;</span><span class="mtk4">td</span><span class="mtk17">&gt;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk17">&lt;</span><span class="mtk4">span</span><span class="mtk1"> </span><span class="mtk12">className</span><span class="mtk1">=</span><span class="mtk8">&quot;cell-header&quot;</span><span class="mtk17">&gt;</span><span class="mtk1">Student ID:</span><span class="mtk17">&lt;/</span><span class="mtk4">span</span><span class="mtk17">&gt;</span><span class="mtk1"> </span><span class="mtk4">{</span><span class="mtk12">student</span><span class="mtk1">.</span><span class="mtk12">id</span><span class="mtk4">}</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk17">&lt;/</span><span class="mtk4">td</span><span class="mtk17">&gt;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk17">&lt;</span><span class="mtk4">td</span><span class="mtk17">&gt;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk17">&lt;</span><span class="mtk4">span</span><span class="mtk1"> </span><span class="mtk12">className</span><span class="mtk1">=</span><span class="mtk8">&quot;cell-header&quot;</span><span class="mtk17">&gt;</span><span class="mtk1">Name:</span><span class="mtk17">&lt;/</span><span class="mtk4">span</span><span class="mtk17">&gt;</span><span class="mtk1"> </span><span class="mtk4">{</span><span class="mtk12">student</span><span class="mtk1">.</span><span class="mtk12">name</span><span class="mtk4">}</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk17">&lt;/</span><span class="mtk4">td</span><span class="mtk17">&gt;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk17">&lt;</span><span class="mtk4">td</span><span class="mtk17">&gt;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk17">&lt;</span><span class="mtk4">span</span><span class="mtk1"> </span><span class="mtk12">className</span><span class="mtk1">=</span><span class="mtk8">&quot;cell-header&quot;</span><span class="mtk17">&gt;</span><span class="mtk1">Date of Birth:</span><span class="mtk17">&lt;/</span><span class="mtk4">span</span><span class="mtk17">&gt;</span><span class="mtk1"> </span><span class="mtk4">{</span><span class="mtk12">student</span><span class="mtk1">.</span><span class="mtk12">dob</span><span class="mtk4">}</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk17">&lt;/</span><span class="mtk4">td</span><span class="mtk17">&gt;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk17">&lt;</span><span class="mtk4">td</span><span class="mtk17">&gt;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk17">&lt;</span><span class="mtk4">span</span><span class="mtk1"> </span><span class="mtk12">className</span><span class="mtk1">=</span><span class="mtk8">&quot;cell-header&quot;</span><span class="mtk17">&gt;</span><span class="mtk1">Major:</span><span class="mtk17">&lt;/</span><span class="mtk4">span</span><span class="mtk17">&gt;</span><span class="mtk1"> </span><span class="mtk4">{</span><span class="mtk12">student</span><span class="mtk1">.</span><span class="mtk12">major</span><span class="mtk4">}</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk17">&lt;/</span><span class="mtk4">td</span><span class="mtk17">&gt;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk17">&lt;/</span><span class="mtk4">tr</span><span class="mtk17">&gt;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> ))</span><span class="mtk4">}</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk17">&lt;/</span><span class="mtk4">tbody</span><span class="mtk17">&gt;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk17">&lt;/</span><span class="mtk4">table</span><span class="mtk17">&gt;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> );</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1">};</span></span></span> <span class="grvsc-line"><span class="grvsc-source"></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk15">export</span><span class="mtk1"> </span><span class="mtk15">default</span><span class="mtk1"> </span><span class="mtk4">function</span><span class="mtk1"> </span><span class="mtk11">App</span><span class="mtk1">() {</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk15">return</span><span class="mtk1"> </span><span class="mtk17">&lt;</span><span class="mtk10">StudentTableResponsive</span><span class="mtk1"> </span><span class="mtk17">/&gt;</span><span class="mtk1">;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1">}</span></span></span></code></pre> <div id="StudentTableResponsive" data-code data-height="450px" data-width="300px" data-resize style="display:flex;justify-content: center;"></div> <p>With these steps, we now have a responsive table layout that is significantly more user-friendly for mobile viewers. If we resize the window using the resize handle in the bottom right corner, we can see that the table layout changes to a more mobile-friendly format when the screen size is reduced.</p> <h2 id="summary--complete-code" style="position:relative;"><a href="#summary--complete-code" aria-label="summary complete code permalink" class="anchor before"><svg aria-hidden="true" focusable="false" height="16" version="1.1" viewBox="0 0 16 16" width="16"><path fill-rule="evenodd" d="M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z"></path></svg></a>Summary &#x26; Complete Code</h2> <p>In this tutorial, we reviewed some essential techniques for creating a responsive table in React. We explored two practical approaches: implementing a scrollable table for smaller screens and altering the table layout for enhanced mobile friendliness. These strategies not only maintain data accessibility but also improve user experience across various devices.</p> <p>Here is the complete code example on StackBlitz:</p> <div data-stackblitz="react-responsive-table"> <button>Run Code</button> </div> <p>Bye for now 👋</p> <style class="grvsc-styles"> .grvsc-container { overflow: auto; position: relative; -webkit-overflow-scrolling: touch; padding-top: 1rem; padding-top: var(--grvsc-padding-top, var(--grvsc-padding-v, 1rem)); padding-bottom: 1rem; padding-bottom: var(--grvsc-padding-bottom, var(--grvsc-padding-v, 1rem)); border-radius: 8px; border-radius: var(--grvsc-border-radius, 8px); font-feature-settings: normal; line-height: 1.4; } .grvsc-code { display: table; } .grvsc-line { display: table-row; box-sizing: border-box; width: 100%; position: relative; } .grvsc-line > * { position: relative; } .grvsc-gutter-pad { display: table-cell; padding-left: 0.75rem; padding-left: calc(var(--grvsc-padding-left, var(--grvsc-padding-h, 1.5rem)) / 2); } .grvsc-gutter { display: table-cell; -webkit-user-select: none; -moz-user-select: none; user-select: none; } .grvsc-gutter::before { content: attr(data-content); } .grvsc-source { display: table-cell; padding-left: 1.5rem; padding-left: var(--grvsc-padding-left, var(--grvsc-padding-h, 1.5rem)); padding-right: 1.5rem; padding-right: var(--grvsc-padding-right, var(--grvsc-padding-h, 1.5rem)); } .grvsc-source:empty::after { content: ' '; -webkit-user-select: none; -moz-user-select: none; user-select: none; } .grvsc-gutter + .grvsc-source { padding-left: 0.75rem; padding-left: calc(var(--grvsc-padding-left, var(--grvsc-padding-h, 1.5rem)) / 2); } /* Line transformer styles */ .grvsc-has-line-highlighting > .grvsc-code > .grvsc-line::before { content: ' '; position: absolute; width: 100%; } .grvsc-line-diff-add::before { background-color: var(--grvsc-line-diff-add-background-color, rgba(0, 255, 60, 0.2)); } .grvsc-line-diff-del::before { background-color: var(--grvsc-line-diff-del-background-color, rgba(255, 0, 20, 0.2)); } .grvsc-line-number { padding: 0 2px; text-align: right; opacity: 0.7; } .default-dark { background-color: #1E1E1E; color: #D4D4D4; } .default-dark .mtk4 { color: #569CD6; } .default-dark .mtk1 { color: #D4D4D4; } .default-dark .mtk12 { color: #9CDCFE; } .default-dark .mtk7 { color: #B5CEA8; } .default-dark .mtk8 { color: #CE9178; } .default-dark .mtk3 { color: #6A9955; } .default-dark .mtk11 { color: #DCDCAA; } .default-dark .mtk15 { color: #C586C0; } .default-dark .mtk17 { color: #808080; } .default-dark .mtk6 { color: #D7BA7D; } .default-dark .mtk10 { color: #4EC9B0; } .default-dark .grvsc-line-highlighted::before { background-color: var(--grvsc-line-highlighted-background-color, rgba(255, 255, 255, 0.1)); box-shadow: inset var(--grvsc-line-highlighted-border-width, 4px) 0 0 0 var(--grvsc-line-highlighted-border-color, rgba(255, 255, 255, 0.5)); } </style><![CDATA[MUI Stack: A Comprehensive Guide to the Material UI Stack Layout Component]]>https://muhimasri.commui-stackhttps://muhimasri.commui-stack<p>The MUI Stack component is a powerful tool for creating flexible layouts in a Material UI project. The Stack simplifies arranging items in a one-dimensional layout by leveraging the core CSS flexbox properties and integrating them as props.</p> <p>MUI Stack differs from the Grid component, designed for two-dimensional layouts. The Stack component is ideal for creating one-dimensional layouts, such as lists, navigation menus, and forms.</p> <p>This tutorial will guide us through using and customizing the MUI Stack component. We will learn how to create flexible and responsive layouts, arrange items, and apply styling to the Stack component.</p> <h2 id="arranging-items" style="position:relative;"><a href="#arranging-items" aria-label="arranging items permalink" class="anchor before"><svg aria-hidden="true" focusable="false" height="16" version="1.1" viewBox="0 0 16 16" width="16"><path fill-rule="evenodd" d="M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z"></path></svg></a>Arranging Items</h2> <p>The MUI Stack component leverages several core CSS flexbox properties, making them accessible as props. This functionality simplifies the task of arranging items either horizontally or vertically. Let’s explore these properties:</p> <h3 id="direction" style="position:relative;"><a href="#direction" aria-label="direction permalink" class="anchor before"><svg aria-hidden="true" focusable="false" height="16" version="1.1" viewBox="0 0 16 16" width="16"><path fill-rule="evenodd" d="M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z"></path></svg></a>Direction</h3> <p>The <code>direction</code> prop determines the orientation of the Stack. By default, the direction is set to <code>column</code>, which arranges items vertically. To arrange items horizontally, we can set the direction to <code>row</code>.</p> <pre class="grvsc-container default-dark" data-language="jsx" data-index="0"><code class="grvsc-code"><span class="grvsc-line"><span class="grvsc-source"><span class="mtk15">import</span><span class="mtk1"> </span><span class="mtk12">React</span><span class="mtk1"> </span><span class="mtk15">from</span><span class="mtk1"> </span><span class="mtk8">&quot;react&quot;</span><span class="mtk1">;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk15">import</span><span class="mtk1"> </span><span class="mtk12">Stack</span><span class="mtk1"> </span><span class="mtk15">from</span><span class="mtk1"> </span><span class="mtk8">&quot;@mui/material/Stack&quot;</span><span class="mtk1">;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk15">import</span><span class="mtk1"> </span><span class="mtk12">Card</span><span class="mtk1"> </span><span class="mtk15">from</span><span class="mtk1"> </span><span class="mtk8">&quot;@mui/material/Card&quot;</span><span class="mtk1">;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk4">function</span><span class="mtk1"> </span><span class="mtk11">RowStack</span><span class="mtk1">() {</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk15">return</span><span class="mtk1"> (</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk17">&lt;</span><span class="mtk10">Stack</span><span class="mtk1"> </span><span class="mtk12">direction</span><span class="mtk1">=</span><span class="mtk8">&quot;row&quot;</span><span class="mtk17">&gt;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk17">&lt;</span><span class="mtk10">Card</span><span class="mtk17">&gt;</span><span class="mtk1">Item 1</span><span class="mtk17">&lt;/</span><span class="mtk10">Card</span><span class="mtk17">&gt;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk17">&lt;</span><span class="mtk10">Card</span><span class="mtk17">&gt;</span><span class="mtk1">Item 2</span><span class="mtk17">&lt;/</span><span class="mtk10">Card</span><span class="mtk17">&gt;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk17">&lt;</span><span class="mtk10">Card</span><span class="mtk17">&gt;</span><span class="mtk1">Item 3</span><span class="mtk17">&lt;/</span><span class="mtk10">Card</span><span class="mtk17">&gt;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk17">&lt;/</span><span class="mtk10">Stack</span><span class="mtk17">&gt;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> );</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1">}</span></span></span></code></pre> <div id="RowStack" data-code data-height="50px"></div> <h3 id="justify-content" style="position:relative;"><a href="#justify-content" aria-label="justify content permalink" class="anchor before"><svg aria-hidden="true" focusable="false" height="16" version="1.1" viewBox="0 0 16 16" width="16"><path fill-rule="evenodd" d="M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z"></path></svg></a>Justify Content</h3> <p>The <code>justifyContent</code> prop aligns items along the main-axis. When the direction is set to <code>column</code>, the main-axis is the y-axis, and when the direction is set to <code>row</code>, the main-axis is the x-axis. The <code>justifyContent</code> prop accepts the following values:</p> <ul> <li><code>flex-start</code>: Items are aligned to the start of the main-axis.</li> <li><code>center</code>: Items are centered along the main-axis.</li> <li><code>flex-end</code>: Items are aligned to the end of the main-axis.</li> <li><code>space-between</code>: Items are evenly distributed along the main-axis.</li> <li><code>space-around</code>: Items are evenly distributed along the main-axis, with equal space around them.</li> <li><code>space-evenly</code>: Items are evenly distributed along the main-axis, with equal space around them and at the start and end.</li> </ul> <pre class="grvsc-container default-dark" data-language="jsx" data-index="1"><code class="grvsc-code"><span class="grvsc-line"><span class="grvsc-source"><span class="mtk15">import</span><span class="mtk1"> </span><span class="mtk12">React</span><span class="mtk1"> </span><span class="mtk15">from</span><span class="mtk1"> </span><span class="mtk8">&quot;react&quot;</span><span class="mtk1">;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk15">import</span><span class="mtk1"> </span><span class="mtk12">Stack</span><span class="mtk1"> </span><span class="mtk15">from</span><span class="mtk1"> </span><span class="mtk8">&quot;@mui/material/Stack&quot;</span><span class="mtk1">;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk15">import</span><span class="mtk1"> </span><span class="mtk12">Card</span><span class="mtk1"> </span><span class="mtk15">from</span><span class="mtk1"> </span><span class="mtk8">&quot;@mui/material/Card&quot;</span><span class="mtk1">;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk4">function</span><span class="mtk1"> </span><span class="mtk11">JustifyContentStack</span><span class="mtk1">() {</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk15">return</span><span class="mtk1"> (</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk17">&lt;</span><span class="mtk10">Stack</span><span class="mtk1"> </span><span class="mtk12">direction</span><span class="mtk1">=</span><span class="mtk8">&quot;row&quot;</span><span class="mtk1"> </span><span class="mtk12">justifyContent</span><span class="mtk1">=</span><span class="mtk8">&quot;space-between&quot;</span><span class="mtk17">&gt;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk17">&lt;</span><span class="mtk10">Card</span><span class="mtk17">&gt;</span><span class="mtk1">Item 1</span><span class="mtk17">&lt;/</span><span class="mtk10">Card</span><span class="mtk17">&gt;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk17">&lt;</span><span class="mtk10">Card</span><span class="mtk17">&gt;</span><span class="mtk1">Item 2</span><span class="mtk17">&lt;/</span><span class="mtk10">Card</span><span class="mtk17">&gt;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk17">&lt;</span><span class="mtk10">Card</span><span class="mtk17">&gt;</span><span class="mtk1">Item 3</span><span class="mtk17">&lt;/</span><span class="mtk10">Card</span><span class="mtk17">&gt;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk17">&lt;/</span><span class="mtk10">Stack</span><span class="mtk17">&gt;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> );</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1">}</span></span></span></code></pre> <div id="JustifyContentStack" data-code data-height="50px"></div> <h3 id="align-items" style="position:relative;"><a href="#align-items" aria-label="align items permalink" class="anchor before"><svg aria-hidden="true" focusable="false" height="16" version="1.1" viewBox="0 0 16 16" width="16"><path fill-rule="evenodd" d="M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z"></path></svg></a>Align Items</h3> <p>The <code>alignItems</code> prop aligns items along the cross-axis. When the direction is set to <code>column</code>, the cross-axis is the x-axis, and when the direction is set to <code>row</code>, the cross-axis is the y-axis. The <code>alignItems</code> prop accepts the following values:</p> <ul> <li><code>Flex-start</code>: Items are aligned to the start of the cross-axis.</li> <li><code>center</code>: Items are centered along the cross-axis.</li> <li><code>Flex-end</code>: Items are aligned to the end of the cross-axis.</li> <li><code>stretch</code>: Items are stretched to fill the container along the cross-axis.</li> <li><code>baseline</code>: Items are aligned such that their baselines align.</li> </ul> <pre class="grvsc-container default-dark" data-language="jsx" data-index="2"><code class="grvsc-code"><span class="grvsc-line"><span class="grvsc-source"><span class="mtk15">import</span><span class="mtk1"> </span><span class="mtk12">React</span><span class="mtk1"> </span><span class="mtk15">from</span><span class="mtk1"> </span><span class="mtk8">&quot;react&quot;</span><span class="mtk1">;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk15">import</span><span class="mtk1"> </span><span class="mtk12">Stack</span><span class="mtk1"> </span><span class="mtk15">from</span><span class="mtk1"> </span><span class="mtk8">&quot;@mui/material/Stack&quot;</span><span class="mtk1">;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk15">import</span><span class="mtk1"> </span><span class="mtk12">Card</span><span class="mtk1"> </span><span class="mtk15">from</span><span class="mtk1"> </span><span class="mtk8">&quot;@mui/material/Card&quot;</span><span class="mtk1">;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk4">function</span><span class="mtk1"> </span><span class="mtk11">AlignItemsStack</span><span class="mtk1">() {</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk15">return</span><span class="mtk1"> (</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk17">&lt;</span><span class="mtk10">Stack</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">direction</span><span class="mtk1">=</span><span class="mtk8">&quot;row&quot;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">alignItems</span><span class="mtk1">=</span><span class="mtk8">&quot;center&quot;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">sx</span><span class="mtk1">=</span><span class="mtk4">{</span><span class="mtk1">{ </span><span class="mtk12">height:</span><span class="mtk1"> </span><span class="mtk8">&quot;100px&quot;</span><span class="mtk1">, </span><span class="mtk12">border:</span><span class="mtk1"> </span><span class="mtk8">&quot;1px solid&quot;</span><span class="mtk1"> }</span><span class="mtk4">}</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk17">&gt;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk17">&lt;</span><span class="mtk10">Card</span><span class="mtk17">&gt;</span><span class="mtk1">Item 1</span><span class="mtk17">&lt;/</span><span class="mtk10">Card</span><span class="mtk17">&gt;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk17">&lt;</span><span class="mtk10">Card</span><span class="mtk17">&gt;</span><span class="mtk1">Item 2</span><span class="mtk17">&lt;/</span><span class="mtk10">Card</span><span class="mtk17">&gt;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk17">&lt;</span><span class="mtk10">Card</span><span class="mtk17">&gt;</span><span class="mtk1">Item 3</span><span class="mtk17">&lt;/</span><span class="mtk10">Card</span><span class="mtk17">&gt;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk17">&lt;/</span><span class="mtk10">Stack</span><span class="mtk17">&gt;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> );</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1">}</span></span></span></code></pre> <div id="AlignItemsStack" data-code data-height="110px"></div> <h3 id="gap" style="position:relative;"><a href="#gap" aria-label="gap permalink" class="anchor before"><svg aria-hidden="true" focusable="false" height="16" version="1.1" viewBox="0 0 16 16" width="16"><path fill-rule="evenodd" d="M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z"></path></svg></a>Gap</h3> <p>The <code>gap</code> prop sets the space between items in the Stack. This prop accepts a numeric value multiplied by the theme’s spacing unit. For example, the value <code>1</code> corresponds to <code>8px</code>.</p> <pre class="grvsc-container default-dark" data-language="jsx" data-index="3"><code class="grvsc-code"><span class="grvsc-line"><span class="grvsc-source"><span class="mtk15">import</span><span class="mtk1"> </span><span class="mtk12">React</span><span class="mtk1"> </span><span class="mtk15">from</span><span class="mtk1"> </span><span class="mtk8">&quot;react&quot;</span><span class="mtk1">;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk15">import</span><span class="mtk1"> </span><span class="mtk12">Stack</span><span class="mtk1"> </span><span class="mtk15">from</span><span class="mtk1"> </span><span class="mtk8">&quot;@mui/material/Stack&quot;</span><span class="mtk1">;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk15">import</span><span class="mtk1"> </span><span class="mtk12">Card</span><span class="mtk1"> </span><span class="mtk15">from</span><span class="mtk1"> </span><span class="mtk8">&quot;@mui/material/Card&quot;</span><span class="mtk1">;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk4">function</span><span class="mtk1"> </span><span class="mtk11">GapStack</span><span class="mtk1">() {</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk15">return</span><span class="mtk1"> (</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk17">&lt;</span><span class="mtk10">Stack</span><span class="mtk1"> </span><span class="mtk12">direction</span><span class="mtk1">=</span><span class="mtk8">&quot;row&quot;</span><span class="mtk1"> </span><span class="mtk12">gap</span><span class="mtk1">=</span><span class="mtk4">{</span><span class="mtk7">2</span><span class="mtk4">}</span><span class="mtk17">&gt;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk17">&lt;</span><span class="mtk10">Card</span><span class="mtk17">&gt;</span><span class="mtk1">Item 1</span><span class="mtk17">&lt;/</span><span class="mtk10">Card</span><span class="mtk17">&gt;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk17">&lt;</span><span class="mtk10">Card</span><span class="mtk17">&gt;</span><span class="mtk1">Item 2</span><span class="mtk17">&lt;/</span><span class="mtk10">Card</span><span class="mtk17">&gt;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk17">&lt;</span><span class="mtk10">Card</span><span class="mtk17">&gt;</span><span class="mtk1">Item 3</span><span class="mtk17">&lt;/</span><span class="mtk10">Card</span><span class="mtk17">&gt;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk17">&lt;/</span><span class="mtk10">Stack</span><span class="mtk17">&gt;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> );</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1">}</span></span></span></code></pre> <div id="GapStack" data-code data-height="50px"></div> <h2 id="styling-and-customization" style="position:relative;"><a href="#styling-and-customization" aria-label="styling and customization permalink" class="anchor before"><svg aria-hidden="true" focusable="false" height="16" version="1.1" viewBox="0 0 16 16" width="16"><path fill-rule="evenodd" d="M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z"></path></svg></a>Styling and Customization</h2> <p>The MUI Stack component supports all system properties and provides various styling and customization options to create visually appealing layouts.</p> <h3 id="using-props-for-styling" style="position:relative;"><a href="#using-props-for-styling" aria-label="using props for styling permalink" class="anchor before"><svg aria-hidden="true" focusable="false" height="16" version="1.1" viewBox="0 0 16 16" width="16"><path fill-rule="evenodd" d="M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z"></path></svg></a>Using Props for Styling</h3> <p>We can use different props provided by MUI to style the Stack component directly. These props offer a straightforward way to apply common styles.</p> <pre class="grvsc-container default-dark" data-language="jsx" data-index="4"><code class="grvsc-code"><span class="grvsc-line"><span class="grvsc-source"><span class="mtk15">import</span><span class="mtk1"> </span><span class="mtk12">React</span><span class="mtk1"> </span><span class="mtk15">from</span><span class="mtk1"> </span><span class="mtk8">&quot;react&quot;</span><span class="mtk1">;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk15">import</span><span class="mtk1"> </span><span class="mtk12">Stack</span><span class="mtk1"> </span><span class="mtk15">from</span><span class="mtk1"> </span><span class="mtk8">&quot;@mui/material/Stack&quot;</span><span class="mtk1">;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk15">import</span><span class="mtk1"> </span><span class="mtk12">Card</span><span class="mtk1"> </span><span class="mtk15">from</span><span class="mtk1"> </span><span class="mtk8">&quot;@mui/material/Card&quot;</span><span class="mtk1">;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk4">function</span><span class="mtk1"> </span><span class="mtk11">StyledStack</span><span class="mtk1">() {</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk15">return</span><span class="mtk1"> (</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk17">&lt;</span><span class="mtk10">Stack</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">direction</span><span class="mtk1">=</span><span class="mtk8">&quot;row&quot;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">justifyContent</span><span class="mtk1">=</span><span class="mtk8">&quot;center&quot;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">alignItems</span><span class="mtk1">=</span><span class="mtk8">&quot;center&quot;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">p</span><span class="mtk1">=</span><span class="mtk4">{</span><span class="mtk7">2</span><span class="mtk4">}</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">gap</span><span class="mtk1">=</span><span class="mtk4">{</span><span class="mtk7">2</span><span class="mtk4">}</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">height</span><span class="mtk1">=</span><span class="mtk8">&quot;200px&quot;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">bgcolor</span><span class="mtk1">=</span><span class="mtk8">&quot;primary.main&quot;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">color</span><span class="mtk1">=</span><span class="mtk8">&quot;primary.contrastText&quot;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk17">&gt;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk17">&lt;</span><span class="mtk10">Card</span><span class="mtk17">&gt;</span><span class="mtk1">Item 1</span><span class="mtk17">&lt;/</span><span class="mtk10">Card</span><span class="mtk17">&gt;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk17">&lt;</span><span class="mtk10">Card</span><span class="mtk17">&gt;</span><span class="mtk1">Item 2</span><span class="mtk17">&lt;/</span><span class="mtk10">Card</span><span class="mtk17">&gt;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk17">&lt;</span><span class="mtk10">Card</span><span class="mtk17">&gt;</span><span class="mtk1">Item 3</span><span class="mtk17">&lt;/</span><span class="mtk10">Card</span><span class="mtk17">&gt;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk17">&lt;/</span><span class="mtk10">Stack</span><span class="mtk17">&gt;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> );</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1">}</span></span></span></code></pre> <div id="StyledStack" data-code data-height="210px"></div> <h3 id="using-sx-for-advanced-styling" style="position:relative;"><a href="#using-sx-for-advanced-styling" aria-label="using sx for advanced styling permalink" class="anchor before"><svg aria-hidden="true" focusable="false" height="16" version="1.1" viewBox="0 0 16 16" width="16"><path fill-rule="evenodd" d="M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z"></path></svg></a>Using <code>sx</code> for Advanced Styling</h3> <p>The <code>sx</code> prop is a powerful feature in MUI that allows for more advanced customization. It’s a superset of CSS, providing more control over the styling.</p> <pre class="grvsc-container default-dark" data-language="jsx" data-index="5"><code class="grvsc-code"><span class="grvsc-line"><span class="grvsc-source"><span class="mtk15">import</span><span class="mtk1"> </span><span class="mtk12">React</span><span class="mtk1"> </span><span class="mtk15">from</span><span class="mtk1"> </span><span class="mtk8">&quot;react&quot;</span><span class="mtk1">;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk15">import</span><span class="mtk1"> </span><span class="mtk12">Stack</span><span class="mtk1"> </span><span class="mtk15">from</span><span class="mtk1"> </span><span class="mtk8">&quot;@mui/material/Stack&quot;</span><span class="mtk1">;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk15">import</span><span class="mtk1"> </span><span class="mtk12">Card</span><span class="mtk1"> </span><span class="mtk15">from</span><span class="mtk1"> </span><span class="mtk8">&quot;@mui/material/Card&quot;</span><span class="mtk1">;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk4">function</span><span class="mtk1"> </span><span class="mtk11">AdvancedStyledStack</span><span class="mtk1">() {</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk15">return</span><span class="mtk1"> (</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk17">&lt;</span><span class="mtk10">Stack</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">direction</span><span class="mtk1">=</span><span class="mtk8">&quot;row&quot;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">justifyContent</span><span class="mtk1">=</span><span class="mtk8">&quot;center&quot;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">alignItems</span><span class="mtk1">=</span><span class="mtk8">&quot;center&quot;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">gap</span><span class="mtk1">=</span><span class="mtk4">{</span><span class="mtk7">2</span><span class="mtk4">}</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">sx</span><span class="mtk1">=</span><span class="mtk4">{</span><span class="mtk1">{</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">bgcolor:</span><span class="mtk1"> </span><span class="mtk8">&quot;primary.main&quot;</span><span class="mtk1">,</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">color:</span><span class="mtk1"> </span><span class="mtk8">&quot;primary.contrastText&quot;</span><span class="mtk1">,</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">borderRadius:</span><span class="mtk1"> </span><span class="mtk7">4</span><span class="mtk1">,</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">p:</span><span class="mtk1"> </span><span class="mtk7">2</span><span class="mtk1">,</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk8">&quot;&amp; &gt; *&quot;</span><span class="mtk12">:</span><span class="mtk1"> {</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">bgcolor:</span><span class="mtk1"> </span><span class="mtk8">&quot;secondary.main&quot;</span><span class="mtk1">,</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">color:</span><span class="mtk1"> </span><span class="mtk8">&quot;secondary.contrastText&quot;</span><span class="mtk1">,</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">p:</span><span class="mtk1"> </span><span class="mtk7">2</span><span class="mtk1">,</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">borderRadius:</span><span class="mtk1"> </span><span class="mtk7">4</span><span class="mtk1">,</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> },</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> }</span><span class="mtk4">}</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk17">&gt;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk17">&lt;</span><span class="mtk10">Card</span><span class="mtk17">&gt;</span><span class="mtk1">Item 1</span><span class="mtk17">&lt;/</span><span class="mtk10">Card</span><span class="mtk17">&gt;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk17">&lt;</span><span class="mtk10">Card</span><span class="mtk17">&gt;</span><span class="mtk1">Item 2</span><span class="mtk17">&lt;/</span><span class="mtk10">Card</span><span class="mtk17">&gt;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk17">&lt;</span><span class="mtk10">Card</span><span class="mtk17">&gt;</span><span class="mtk1">Item 3</span><span class="mtk17">&lt;/</span><span class="mtk10">Card</span><span class="mtk17">&gt;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk17">&lt;/</span><span class="mtk10">Stack</span><span class="mtk17">&gt;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> );</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1">}</span></span></span></code></pre> <div id="AdvancedStyledStack" data-code data-height="100px"></div> <p>In this example, we used the <code>sx</code> prop to define styles for the Stack and its children (using the <code>&#x26; > *</code> selector).</p> <h2 id="responsive-layouts" style="position:relative;"><a href="#responsive-layouts" aria-label="responsive layouts permalink" class="anchor before"><svg aria-hidden="true" focusable="false" height="16" version="1.1" viewBox="0 0 16 16" width="16"><path fill-rule="evenodd" d="M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z"></path></svg></a>Responsive Layouts</h2> <p>The MUI Stack component is designed to create responsive layouts that adapt to different screen sizes. We can use the <code>sx</code> prop to define responsive styles based on breakpoints.</p> <p>Let’s take the previous example and change the layout direction depending on the screen size:</p> <pre class="grvsc-container grvsc-has-line-highlighting default-dark" data-language="jsx" data-index="6"><code class="grvsc-code"><span class="grvsc-line"><span class="grvsc-source"><span class="mtk1">...</span></span></span> <span class="grvsc-line"><span class="grvsc-source"></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk4">function</span><span class="mtk1"> </span><span class="mtk11">ResponsiveStack</span><span class="mtk1">() {</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk15">return</span><span class="mtk1"> (</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk17">&lt;</span><span class="mtk10">Stack</span></span></span> <span class="grvsc-line grvsc-line-highlighted"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">direction</span><span class="mtk1">=</span><span class="mtk4">{</span><span class="mtk1">{ </span><span class="mtk12">xs:</span><span class="mtk1"> </span><span class="mtk8">&#39;column&#39;</span><span class="mtk1">, </span><span class="mtk12">sm:</span><span class="mtk1"> </span><span class="mtk8">&#39;row&#39;</span><span class="mtk1"> }</span><span class="mtk4">}</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk14">...</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk14">}}</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk17">&gt;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk17">&lt;</span><span class="mtk10">Card</span><span class="mtk17">&gt;</span><span class="mtk1">Item 1</span><span class="mtk17">&lt;/</span><span class="mtk10">Card</span><span class="mtk17">&gt;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk17">&lt;</span><span class="mtk10">Card</span><span class="mtk17">&gt;</span><span class="mtk1">Item 2</span><span class="mtk17">&lt;/</span><span class="mtk10">Card</span><span class="mtk17">&gt;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk17">&lt;</span><span class="mtk10">Card</span><span class="mtk17">&gt;</span><span class="mtk1">Item 3</span><span class="mtk17">&lt;/</span><span class="mtk10">Card</span><span class="mtk17">&gt;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk17">&lt;/</span><span class="mtk10">Stack</span><span class="mtk17">&gt;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> );</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1">}</span></span></span></code></pre> <div id="ResponsiveStack" data-code data-height="250px" data-resize style="display:flex;justify-content: center;"></div> <p>The above example is an interactive demo. When resizing the window from the bottom right corner, the Stack layout changes from vertical to horizontal based on the screen size. The direction prop is set to <code>column</code> for extra-small (xs) screens and <code>row</code> for small (sm) and larger screens.</p> <h2 id="conclusion" style="position:relative;"><a href="#conclusion" aria-label="conclusion permalink" class="anchor before"><svg aria-hidden="true" focusable="false" height="16" version="1.1" viewBox="0 0 16 16" width="16"><path fill-rule="evenodd" d="M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z"></path></svg></a>Conclusion</h2> <p>Using the MUI Stack component is an effective way to create and arrange elements efficiently. It has a specific opinionated use case, so it’s an excellent tool for creating one-dimensional layouts. In this tutorial, we learned how to use the core properties of the Stack component, apply styling, and create responsive layouts.</p> <p>Bye for now 👋</p> <style class="grvsc-styles"> .grvsc-container { overflow: auto; position: relative; -webkit-overflow-scrolling: touch; padding-top: 1rem; padding-top: var(--grvsc-padding-top, var(--grvsc-padding-v, 1rem)); padding-bottom: 1rem; padding-bottom: var(--grvsc-padding-bottom, var(--grvsc-padding-v, 1rem)); border-radius: 8px; border-radius: var(--grvsc-border-radius, 8px); font-feature-settings: normal; line-height: 1.4; } .grvsc-code { display: table; } .grvsc-line { display: table-row; box-sizing: border-box; width: 100%; position: relative; } .grvsc-line > * { position: relative; } .grvsc-gutter-pad { display: table-cell; padding-left: 0.75rem; padding-left: calc(var(--grvsc-padding-left, var(--grvsc-padding-h, 1.5rem)) / 2); } .grvsc-gutter { display: table-cell; -webkit-user-select: none; -moz-user-select: none; user-select: none; } .grvsc-gutter::before { content: attr(data-content); } .grvsc-source { display: table-cell; padding-left: 1.5rem; padding-left: var(--grvsc-padding-left, var(--grvsc-padding-h, 1.5rem)); padding-right: 1.5rem; padding-right: var(--grvsc-padding-right, var(--grvsc-padding-h, 1.5rem)); } .grvsc-source:empty::after { content: ' '; -webkit-user-select: none; -moz-user-select: none; user-select: none; } .grvsc-gutter + .grvsc-source { padding-left: 0.75rem; padding-left: calc(var(--grvsc-padding-left, var(--grvsc-padding-h, 1.5rem)) / 2); } /* Line transformer styles */ .grvsc-has-line-highlighting > .grvsc-code > .grvsc-line::before { content: ' '; position: absolute; width: 100%; } .grvsc-line-diff-add::before { background-color: var(--grvsc-line-diff-add-background-color, rgba(0, 255, 60, 0.2)); } .grvsc-line-diff-del::before { background-color: var(--grvsc-line-diff-del-background-color, rgba(255, 0, 20, 0.2)); } .grvsc-line-number { padding: 0 2px; text-align: right; opacity: 0.7; } .default-dark { background-color: #1E1E1E; color: #D4D4D4; } .default-dark .mtk15 { color: #C586C0; } .default-dark .mtk1 { color: #D4D4D4; } .default-dark .mtk12 { color: #9CDCFE; } .default-dark .mtk8 { color: #CE9178; } .default-dark .mtk4 { color: #569CD6; } .default-dark .mtk11 { color: #DCDCAA; } .default-dark .mtk17 { color: #808080; } .default-dark .mtk10 { color: #4EC9B0; } .default-dark .mtk7 { color: #B5CEA8; } .default-dark .mtk14 { color: #F44747; } .default-dark .grvsc-line-highlighted::before { background-color: var(--grvsc-line-highlighted-background-color, rgba(255, 255, 255, 0.1)); box-shadow: inset var(--grvsc-line-highlighted-border-width, 4px) 0 0 0 var(--grvsc-line-highlighted-border-color, rgba(255, 255, 255, 0.5)); } </style><![CDATA[How to Use and Customize MUI Box]]>https://muhimasri.commui-boxhttps://muhimasri.commui-box<p>The MUI Box component is a fundamental building block in the Material UI library, designed to serve as a generic container element. Unlike the Container component, which is tailored for specific layout purposes with predefined styling options, the Box component offers a more flexible approach.</p> <p>In this tutorial, we’ll explore the Box component in detail, covering its usage, customization, and best practices. We’ll also discuss how to leverage the component to create custom layout components and reusable design patterns.</p> <h2 id="customization" style="position:relative;"><a href="#customization" aria-label="customization permalink" class="anchor before"><svg aria-hidden="true" focusable="false" height="16" version="1.1" viewBox="0 0 16 16" width="16"><path fill-rule="evenodd" d="M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z"></path></svg></a>Customization</h2> <p>The versatility of the MUI Box component allows it to be used in various contexts, mirroring the functionality of standard HTML elements like <code>div</code>, <code>section</code>, and <code>article</code>.</p> <h3 id="changing-the-element" style="position:relative;"><a href="#changing-the-element" aria-label="changing the element permalink" class="anchor before"><svg aria-hidden="true" focusable="false" height="16" version="1.1" viewBox="0 0 16 16" width="16"><path fill-rule="evenodd" d="M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z"></path></svg></a>Changing the Element</h3> <p>By default, the Box component renders as a <code>div</code> element. However, we can easily change this using the <code>component</code> prop. This flexibility allows it to function as any HTML element we need, accommodating various semantic or accessibility requirements.</p> <pre class="grvsc-container default-dark" data-language="jsx" data-index="0"><code class="grvsc-code"><span class="grvsc-line"><span class="grvsc-source"><span class="mtk15">import</span><span class="mtk1"> </span><span class="mtk12">Box</span><span class="mtk1"> </span><span class="mtk15">from</span><span class="mtk1"> </span><span class="mtk8">&quot;@mui/material/Box&quot;</span><span class="mtk1">;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk4">function</span><span class="mtk1"> </span><span class="mtk11">SemanticallyCorrectComponent</span><span class="mtk1">() {</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk15">return</span><span class="mtk1"> </span><span class="mtk17">&lt;</span><span class="mtk10">Box</span><span class="mtk1"> </span><span class="mtk12">component</span><span class="mtk1">=</span><span class="mtk8">&quot;article&quot;</span><span class="mtk17">&gt;</span><span class="mtk1">This Box is now an article element.</span><span class="mtk17">&lt;/</span><span class="mtk10">Box</span><span class="mtk17">&gt;</span><span class="mtk1">;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1">}</span></span></span></code></pre> <p>In this example, we’ve changed the component to render as an <code>article</code> element. This is particularly useful when working with HTML5 semantics or improving accessibility.</p> <h3 id="using-system-properties" style="position:relative;"><a href="#using-system-properties" aria-label="using system properties permalink" class="anchor before"><svg aria-hidden="true" focusable="false" height="16" version="1.1" viewBox="0 0 16 16" width="16"><path fill-rule="evenodd" d="M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z"></path></svg></a>Using System Properties</h3> <p>The Box component leverages the MUI system properties, enabling direct styling through props. This approach simplifies the process of applying responsive styles and adheres to the Material UI theme for consistency across the application.</p> <pre class="grvsc-container default-dark" data-language="jsx" data-index="1"><code class="grvsc-code"><span class="grvsc-line"><span class="grvsc-source"><span class="mtk15">import</span><span class="mtk1"> </span><span class="mtk12">Box</span><span class="mtk1"> </span><span class="mtk15">from</span><span class="mtk1"> </span><span class="mtk8">&quot;@mui/material/Box&quot;</span><span class="mtk1">;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk4">function</span><span class="mtk1"> </span><span class="mtk11">StyledBox</span><span class="mtk1">() {</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk15">return</span><span class="mtk1"> (</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk17">&lt;</span><span class="mtk10">Box</span><span class="mtk1"> </span><span class="mtk12">p</span><span class="mtk1">=</span><span class="mtk4">{</span><span class="mtk7">2</span><span class="mtk4">}</span><span class="mtk1"> </span><span class="mtk12">bgcolor</span><span class="mtk1">=</span><span class="mtk8">&quot;primary.dark&quot;</span><span class="mtk1"> </span><span class="mtk12">display</span><span class="mtk1">=</span><span class="mtk8">&quot;flex&quot;</span><span class="mtk1"> </span><span class="mtk12">color</span><span class="mtk1">=</span><span class="mtk8">&quot;white&quot;</span><span class="mtk17">&gt;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> System properties for padding, background color, and display.</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk17">&lt;/</span><span class="mtk10">Box</span><span class="mtk17">&gt;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> );</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1">}</span></span></span></code></pre> <div id="StyledBox" data-code data-height="100px"></div> <p>In this example, we’ve used the <code>p</code>, <code>bgcolor</code>, and <code>display</code> props to apply padding, set the background color, and define the display property, respectively. This demonstrates the power of system properties, allowing us to apply styles directly without needing additional CSS.</p> <h3 id="using-sx-for-styling" style="position:relative;"><a href="#using-sx-for-styling" aria-label="using sx for styling permalink" class="anchor before"><svg aria-hidden="true" focusable="false" height="16" version="1.1" viewBox="0 0 16 16" width="16"><path fill-rule="evenodd" d="M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z"></path></svg></a>Using <code>sx</code> for Styling</h3> <p>The <code>sx</code> prop is a powerful feature that acts as a superset of CSS, offering full customization capabilities. It supports all CSS properties, including custom values from the theme, allowing for intricate styling directly on the component.</p> <pre class="grvsc-container default-dark" data-language="jsx" data-index="2"><code class="grvsc-code"><span class="grvsc-line"><span class="grvsc-source"><span class="mtk15">import</span><span class="mtk1"> </span><span class="mtk12">Box</span><span class="mtk1"> </span><span class="mtk15">from</span><span class="mtk1"> </span><span class="mtk8">&quot;@mui/material/Box&quot;</span><span class="mtk1">;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk4">function</span><span class="mtk1"> </span><span class="mtk11">CustomStyledBox</span><span class="mtk1">() {</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk15">return</span><span class="mtk1"> (</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk17">&lt;</span><span class="mtk10">Box</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">sx</span><span class="mtk1">=</span><span class="mtk4">{</span><span class="mtk1">{</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">width:</span><span class="mtk1"> </span><span class="mtk7">200</span><span class="mtk1">,</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">height:</span><span class="mtk1"> </span><span class="mtk7">200</span><span class="mtk1">,</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">bgcolor:</span><span class="mtk1"> </span><span class="mtk8">&quot;primary.dark&quot;</span><span class="mtk1">,</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk8">&quot;&amp;:hover&quot;</span><span class="mtk12">:</span><span class="mtk1"> {</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">bgcolor:</span><span class="mtk1"> </span><span class="mtk8">&quot;primary.main&quot;</span><span class="mtk1">,</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> },</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">display:</span><span class="mtk1"> </span><span class="mtk8">&quot;flex&quot;</span><span class="mtk1">,</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">justifyContent:</span><span class="mtk1"> </span><span class="mtk8">&quot;center&quot;</span><span class="mtk1">,</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">alignItems:</span><span class="mtk1"> </span><span class="mtk8">&quot;center&quot;</span><span class="mtk1">,</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">color:</span><span class="mtk1"> </span><span class="mtk8">&quot;white&quot;</span><span class="mtk1">,</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> }</span><span class="mtk4">}</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk17">&gt;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> Hover over me!</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk17">&lt;/</span><span class="mtk10">Box</span><span class="mtk17">&gt;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> );</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1">}</span></span></span></code></pre> <div id="CustomStyledBox" data-code data-height="200px"></div> <p>This example showcases the <code>sx</code> prop’s ability to directly apply a custom width, height, background color, hover effect, and flexbox layout.</p> <h3 id="using-theme-within-sx" style="position:relative;"><a href="#using-theme-within-sx" aria-label="using theme within sx permalink" class="anchor before"><svg aria-hidden="true" focusable="false" height="16" version="1.1" viewBox="0 0 16 16" width="16"><path fill-rule="evenodd" d="M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z"></path></svg></a>Using Theme within <code>sx</code></h3> <p>We can access the theme’s color palette and styling tokens within the <code>sx</code> prop to ensure our custom styles are consistent with the overall design system.</p> <pre class="grvsc-container default-dark" data-language="jsx" data-index="3"><code class="grvsc-code"><span class="grvsc-line"><span class="grvsc-source"><span class="mtk15">import</span><span class="mtk1"> </span><span class="mtk12">Box</span><span class="mtk1"> </span><span class="mtk15">from</span><span class="mtk1"> </span><span class="mtk8">&quot;@mui/material/Box&quot;</span><span class="mtk1">;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk15">import</span><span class="mtk1"> { </span><span class="mtk12">useTheme</span><span class="mtk1"> } </span><span class="mtk15">from</span><span class="mtk1"> </span><span class="mtk8">&quot;@mui/material/styles&quot;</span><span class="mtk1">;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk4">function</span><span class="mtk1"> </span><span class="mtk11">ThemeStyledBox</span><span class="mtk1">() {</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk4">const</span><span class="mtk1"> </span><span class="mtk12">theme</span><span class="mtk1"> = </span><span class="mtk11">useTheme</span><span class="mtk1">();</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk15">return</span><span class="mtk1"> (</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk17">&lt;</span><span class="mtk10">Box</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">sx</span><span class="mtk1">=</span><span class="mtk4">{</span><span class="mtk1">{</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">bgcolor:</span><span class="mtk1"> </span><span class="mtk12">theme</span><span class="mtk1">.</span><span class="mtk12">palette</span><span class="mtk1">.</span><span class="mtk12">success</span><span class="mtk1">.</span><span class="mtk12">main</span><span class="mtk1">,</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">color:</span><span class="mtk1"> </span><span class="mtk12">theme</span><span class="mtk1">.</span><span class="mtk12">palette</span><span class="mtk1">.</span><span class="mtk12">success</span><span class="mtk1">.</span><span class="mtk12">contrastText</span><span class="mtk1">,</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">p:</span><span class="mtk1"> </span><span class="mtk7">2</span><span class="mtk1">,</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> }</span><span class="mtk4">}</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk17">&gt;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> This box uses theme colors and spacing.</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk17">&lt;/</span><span class="mtk10">Box</span><span class="mtk17">&gt;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> );</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1">}</span></span></span></code></pre> <div id="ThemeStyledBox" data-code data-height="100px"></div> <p>In this example, we’ve used the <code>primary.dark</code> and <code>primary.main</code> values from the theme’s color palette to define the background color and hover effect, ensuring consistency with the application’s design system.</p> <h3 id="using-class-and-css" style="position:relative;"><a href="#using-class-and-css" aria-label="using class and css permalink" class="anchor before"><svg aria-hidden="true" focusable="false" height="16" version="1.1" viewBox="0 0 16 16" width="16"><path fill-rule="evenodd" d="M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z"></path></svg></a>Using Class and CSS</h3> <p>While leveraging MUI’s system and <code>sx</code> prop offers a simple styling approach, traditional CSS classes and stylesheets remain viable, especially for complex or reusable styles.</p> <pre class="grvsc-container default-dark" data-language="css" data-index="4"><code class="grvsc-code"><span class="grvsc-line"><span class="grvsc-source"><span class="mtk3">/* CustomStyle.css */</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk6">.customBox</span><span class="mtk1"> {</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">padding</span><span class="mtk1">: </span><span class="mtk7">16px</span><span class="mtk1">;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">background-color</span><span class="mtk1">: </span><span class="mtk8">#f0f0f0</span><span class="mtk1">;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1">}</span></span></span></code></pre> <pre class="grvsc-container default-dark" data-language="jsx" data-index="5"><code class="grvsc-code"><span class="grvsc-line"><span class="grvsc-source"><span class="mtk3">// CustomStyledBox.jsx</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk15">import</span><span class="mtk1"> </span><span class="mtk12">React</span><span class="mtk1"> </span><span class="mtk15">from</span><span class="mtk1"> </span><span class="mtk8">&quot;react&quot;</span><span class="mtk1">;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk15">import</span><span class="mtk1"> </span><span class="mtk12">Box</span><span class="mtk1"> </span><span class="mtk15">from</span><span class="mtk1"> </span><span class="mtk8">&quot;@mui/material/Box&quot;</span><span class="mtk1">;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk15">import</span><span class="mtk1"> </span><span class="mtk8">&quot;./CustomStyle.css&quot;</span><span class="mtk1">;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk4">function</span><span class="mtk1"> </span><span class="mtk11">CustomStyledBox</span><span class="mtk1">() {</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk15">return</span><span class="mtk1"> </span><span class="mtk17">&lt;</span><span class="mtk10">Box</span><span class="mtk1"> </span><span class="mtk12">className</span><span class="mtk1">=</span><span class="mtk8">&quot;customBox&quot;</span><span class="mtk17">&gt;</span><span class="mtk1">This Box uses custom CSS classes.</span><span class="mtk17">&lt;/</span><span class="mtk10">Box</span><span class="mtk17">&gt;</span><span class="mtk1">;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1">}</span></span></span></code></pre> <p>This example highlights how to apply custom CSS styles by defining them in an external stylesheet and linking them to the Box component through the <code>className</code> prop.</p> <h2 id="reusable-layout" style="position:relative;"><a href="#reusable-layout" aria-label="reusable layout permalink" class="anchor before"><svg aria-hidden="true" focusable="false" height="16" version="1.1" viewBox="0 0 16 16" width="16"><path fill-rule="evenodd" d="M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z"></path></svg></a>Reusable Layout</h2> <p>The Box component’s flexibility and customization options make it an ideal candidate for creating reusable layout components and design patterns. By encapsulating common layout structures within a custom component, we can ensure consistent styling and behavior across the application.</p> <h3 id="custom-card-component" style="position:relative;"><a href="#custom-card-component" aria-label="custom card component permalink" class="anchor before"><svg aria-hidden="true" focusable="false" height="16" version="1.1" viewBox="0 0 16 16" width="16"><path fill-rule="evenodd" d="M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z"></path></svg></a>Custom Card Component</h3> <p>A common design pattern in web applications is the card component, which typically consists of a container with a shadow, padding, and a border-radius. We can create a custom <code>Card</code> component using the Box component and customize it to fit our application’s design system.</p> <pre class="grvsc-container default-dark" data-language="jsx" data-index="6"><code class="grvsc-code"><span class="grvsc-line"><span class="grvsc-source"><span class="mtk15">import</span><span class="mtk1"> </span><span class="mtk12">Box</span><span class="mtk1"> </span><span class="mtk15">from</span><span class="mtk1"> </span><span class="mtk8">&quot;@mui/material/Box&quot;</span><span class="mtk1">;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk4">function</span><span class="mtk1"> </span><span class="mtk11">Card</span><span class="mtk1">({ </span><span class="mtk12">children</span><span class="mtk1"> }) {</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk15">return</span><span class="mtk1"> (</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk17">&lt;</span><span class="mtk10">Box</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">sx</span><span class="mtk1">=</span><span class="mtk4">{</span><span class="mtk1">{</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">p:</span><span class="mtk1"> </span><span class="mtk7">2</span><span class="mtk1">,</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">borderRadius:</span><span class="mtk1"> </span><span class="mtk7">4</span><span class="mtk1">,</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">boxShadow:</span><span class="mtk1"> </span><span class="mtk7">1</span><span class="mtk1">,</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">bgcolor:</span><span class="mtk1"> </span><span class="mtk8">&quot;background.paper&quot;</span><span class="mtk1">,</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> }</span><span class="mtk4">}</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk17">&gt;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk4">{</span><span class="mtk12">children</span><span class="mtk4">}</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk17">&lt;/</span><span class="mtk10">Box</span><span class="mtk17">&gt;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> );</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1">}</span></span></span></code></pre> <p>We can consume the custom Card component anywhere in our application, providing a consistent and reusable card structure.</p> <pre class="grvsc-container default-dark" data-language="jsx" data-index="7"><code class="grvsc-code"><span class="grvsc-line"><span class="grvsc-source"><span class="mtk17">&lt;</span><span class="mtk10">Card</span><span class="mtk17">&gt;</span><span class="mtk1">This is a custom card component.</span><span class="mtk17">&lt;/</span><span class="mtk10">Card</span><span class="mtk17">&gt;</span></span></span></code></pre> <div id="Card" data-code data-height="100px"></div> <h2 id="summary" style="position:relative;"><a href="#summary" aria-label="summary permalink" class="anchor before"><svg aria-hidden="true" focusable="false" height="16" version="1.1" viewBox="0 0 16 16" width="16"><path fill-rule="evenodd" d="M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z"></path></svg></a>Summary</h2> <p>The MUI Box component is a powerful and versatile building block that offers a wide range of customization options, making it suitable for various layout and design requirements. By leveraging system properties, the <code>sx</code> prop, and custom components, we can create reusable layout structures and design patterns that align with the Material UI design system.</p> <p>Bye for now! 👋</p> <style class="grvsc-styles"> .grvsc-container { overflow: auto; position: relative; -webkit-overflow-scrolling: touch; padding-top: 1rem; padding-top: var(--grvsc-padding-top, var(--grvsc-padding-v, 1rem)); padding-bottom: 1rem; padding-bottom: var(--grvsc-padding-bottom, var(--grvsc-padding-v, 1rem)); border-radius: 8px; border-radius: var(--grvsc-border-radius, 8px); font-feature-settings: normal; line-height: 1.4; } .grvsc-code { display: table; } .grvsc-line { display: table-row; box-sizing: border-box; width: 100%; position: relative; } .grvsc-line > * { position: relative; } .grvsc-gutter-pad { display: table-cell; padding-left: 0.75rem; padding-left: calc(var(--grvsc-padding-left, var(--grvsc-padding-h, 1.5rem)) / 2); } .grvsc-gutter { display: table-cell; -webkit-user-select: none; -moz-user-select: none; user-select: none; } .grvsc-gutter::before { content: attr(data-content); } .grvsc-source { display: table-cell; padding-left: 1.5rem; padding-left: var(--grvsc-padding-left, var(--grvsc-padding-h, 1.5rem)); padding-right: 1.5rem; padding-right: var(--grvsc-padding-right, var(--grvsc-padding-h, 1.5rem)); } .grvsc-source:empty::after { content: ' '; -webkit-user-select: none; -moz-user-select: none; user-select: none; } .grvsc-gutter + .grvsc-source { padding-left: 0.75rem; padding-left: calc(var(--grvsc-padding-left, var(--grvsc-padding-h, 1.5rem)) / 2); } /* Line transformer styles */ .grvsc-has-line-highlighting > .grvsc-code > .grvsc-line::before { content: ' '; position: absolute; width: 100%; } .grvsc-line-diff-add::before { background-color: var(--grvsc-line-diff-add-background-color, rgba(0, 255, 60, 0.2)); } .grvsc-line-diff-del::before { background-color: var(--grvsc-line-diff-del-background-color, rgba(255, 0, 20, 0.2)); } .grvsc-line-number { padding: 0 2px; text-align: right; opacity: 0.7; } .default-dark { background-color: #1E1E1E; color: #D4D4D4; } .default-dark .mtk15 { color: #C586C0; } .default-dark .mtk1 { color: #D4D4D4; } .default-dark .mtk12 { color: #9CDCFE; } .default-dark .mtk8 { color: #CE9178; } .default-dark .mtk4 { color: #569CD6; } .default-dark .mtk11 { color: #DCDCAA; } .default-dark .mtk17 { color: #808080; } .default-dark .mtk10 { color: #4EC9B0; } .default-dark .mtk7 { color: #B5CEA8; } .default-dark .mtk3 { color: #6A9955; } .default-dark .mtk6 { color: #D7BA7D; } .default-dark .grvsc-line-highlighted::before { background-color: var(--grvsc-line-highlighted-background-color, rgba(255, 255, 255, 0.1)); box-shadow: inset var(--grvsc-line-highlighted-border-width, 4px) 0 0 0 var(--grvsc-line-highlighted-border-color, rgba(255, 255, 255, 0.5)); } </style><![CDATA[MUI FormControl: Creating Dynamic and Customized Forms]]>https://muhimasri.commui-formcontrolhttps://muhimasri.commui-formcontrol<p>MUI Form Control is a component that enhances form functionality within Material UI. It provides essential context for form inputs, such as their filled, focused, error, and required states, enabling more advanced use cases. By encompassing smaller components like Label, Input, and HelperText within FormControl, developers can create fully customized TextFields, offering precise control over the form’s behavior and appearance.</p> <p>Here’s a simple code example to illustrate how to integrate smaller components within FormControl to craft a custom TextField:</p> <pre class="grvsc-container default-dark" data-language="jsx" data-index="0"><code class="grvsc-code"><span class="grvsc-line"><span class="grvsc-source"><span class="mtk15">import</span><span class="mtk1"> </span><span class="mtk12">React</span><span class="mtk1"> </span><span class="mtk15">from</span><span class="mtk1"> </span><span class="mtk8">&quot;react&quot;</span><span class="mtk1">;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk15">import</span><span class="mtk1"> </span><span class="mtk12">FormControl</span><span class="mtk1"> </span><span class="mtk15">from</span><span class="mtk1"> </span><span class="mtk8">&quot;@mui/material/FormControl&quot;</span><span class="mtk1">;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk15">import</span><span class="mtk1"> </span><span class="mtk12">InputLabel</span><span class="mtk1"> </span><span class="mtk15">from</span><span class="mtk1"> </span><span class="mtk8">&quot;@mui/material/InputLabel&quot;</span><span class="mtk1">;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk15">import</span><span class="mtk1"> </span><span class="mtk12">Input</span><span class="mtk1"> </span><span class="mtk15">from</span><span class="mtk1"> </span><span class="mtk8">&quot;@mui/material/Input&quot;</span><span class="mtk1">;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk15">import</span><span class="mtk1"> </span><span class="mtk12">FormHelperText</span><span class="mtk1"> </span><span class="mtk15">from</span><span class="mtk1"> </span><span class="mtk8">&quot;@mui/material/FormHelperText&quot;</span><span class="mtk1">;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk15">export</span><span class="mtk1"> </span><span class="mtk15">default</span><span class="mtk1"> </span><span class="mtk4">function</span><span class="mtk1"> </span><span class="mtk11">CustomTextField</span><span class="mtk1">() {</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk15">return</span><span class="mtk1"> (</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk17">&lt;</span><span class="mtk10">FormControl</span><span class="mtk17">&gt;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk17">&lt;</span><span class="mtk10">InputLabel</span><span class="mtk17">&gt;</span><span class="mtk1">Email address</span><span class="mtk17">&lt;/</span><span class="mtk10">InputLabel</span><span class="mtk17">&gt;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk17">&lt;</span><span class="mtk10">Input</span><span class="mtk1"> </span><span class="mtk17">/&gt;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk17">&lt;</span><span class="mtk10">FormHelperText</span><span class="mtk17">&gt;</span><span class="mtk1">We&#39;ll never share your email.</span><span class="mtk17">&lt;/</span><span class="mtk10">FormHelperText</span><span class="mtk17">&gt;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk17">&lt;/</span><span class="mtk10">FormControl</span><span class="mtk17">&gt;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> );</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1">}</span></span></span></code></pre> <div id="CustomTextField" data-code data-height="100px"></div> <p>This example demonstrates how <code>FormControl</code> can encapsulate an <code>InputLabel</code>, <code>Input</code>, and <code>FormHelperText</code> to create a cohesive, customized input field with a label and helper text for enhanced user guidance.</p> <p>In this tutorial, we’ll explore the various features and use cases of MUI FormControl, including its properties, customization options, and advanced form-handling techniques.</p> <h2 id="form-control-context" style="position:relative;"><a href="#form-control-context" aria-label="form control context permalink" class="anchor before"><svg aria-hidden="true" focusable="false" height="16" version="1.1" viewBox="0 0 16 16" width="16"><path fill-rule="evenodd" d="M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z"></path></svg></a>Form Control Context</h2> <p>Using the FormControl component as a wrapper provides a context for all child elements, enabling them to access various states such as error, focused, filled, and required. These states can be accessed using the <code>useFormControl</code> hook, offering a powerful way to dynamically adjust the behavior and styling of form elements based on user interaction.</p> <h3 id="error-state" style="position:relative;"><a href="#error-state" aria-label="error state permalink" class="anchor before"><svg aria-hidden="true" focusable="false" height="16" version="1.1" viewBox="0 0 16 16" width="16"><path fill-rule="evenodd" d="M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z"></path></svg></a>Error State</h3> <p>When an input event triggers an error, the FormControl reflects this state, allowing all child elements to update accordingly. For example, both the helper text and the input field can change color to indicate the error. Additionally, a custom helper text component can access the error state from the <code>useFormControl</code> hook for more advanced usage.</p> <p>The following example demonstrates how to access the error state using the <code>useFormControl</code> hook:</p> <pre class="grvsc-container default-dark" data-language="jsx" data-index="1"><code class="grvsc-code"><span class="grvsc-line"><span class="grvsc-source"><span class="mtk15">import</span><span class="mtk1"> </span><span class="mtk12">React</span><span class="mtk1"> </span><span class="mtk15">from</span><span class="mtk1"> </span><span class="mtk8">&quot;react&quot;</span><span class="mtk1">;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk15">import</span><span class="mtk1"> </span><span class="mtk12">FormHelperText</span><span class="mtk1"> </span><span class="mtk15">from</span><span class="mtk1"> </span><span class="mtk8">&quot;@mui/material/FormHelperText&quot;</span><span class="mtk1">;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk15">import</span><span class="mtk1"> </span><span class="mtk12">Input</span><span class="mtk1"> </span><span class="mtk15">from</span><span class="mtk1"> </span><span class="mtk8">&quot;@mui/material/Input&quot;</span><span class="mtk1">;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk15">import</span><span class="mtk1"> </span><span class="mtk12">FormControl</span><span class="mtk1">, { </span><span class="mtk12">useFormControl</span><span class="mtk1"> } </span><span class="mtk15">from</span><span class="mtk1"> </span><span class="mtk8">&quot;@mui/material/FormControl&quot;</span><span class="mtk1">;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk4">function</span><span class="mtk1"> </span><span class="mtk11">CustomHelperText</span><span class="mtk1">() {</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk4">const</span><span class="mtk1"> { </span><span class="mtk12">error</span><span class="mtk1"> } = </span><span class="mtk11">useFormControl</span><span class="mtk1">() || {};</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk15">return</span><span class="mtk1"> (</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk17">&lt;</span><span class="mtk10">FormHelperText</span><span class="mtk1"> </span><span class="mtk12">error</span><span class="mtk1">=</span><span class="mtk4">{</span><span class="mtk12">error</span><span class="mtk4">}</span><span class="mtk17">&gt;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk4">{</span><span class="mtk12">error</span><span class="mtk1"> ? </span><span class="mtk8">&quot;Error text&quot;</span><span class="mtk1"> : </span><span class="mtk8">&quot;Helper text&quot;</span><span class="mtk4">}</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk17">&lt;/</span><span class="mtk10">FormHelperText</span><span class="mtk17">&gt;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> );</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1">}</span></span></span> <span class="grvsc-line"><span class="grvsc-source"></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk15">export</span><span class="mtk1"> </span><span class="mtk15">default</span><span class="mtk1"> </span><span class="mtk4">function</span><span class="mtk1"> </span><span class="mtk11">InputValidation</span><span class="mtk1">() {</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk4">const</span><span class="mtk1"> [</span><span class="mtk12">error</span><span class="mtk1">, </span><span class="mtk12">setError</span><span class="mtk1">] = </span><span class="mtk12">React</span><span class="mtk1">.</span><span class="mtk11">useState</span><span class="mtk1">(</span><span class="mtk4">false</span><span class="mtk1">);</span></span></span> <span class="grvsc-line"><span class="grvsc-source"></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk4">const</span><span class="mtk1"> </span><span class="mtk11">handleChange</span><span class="mtk1"> = </span><span class="mtk12">event</span><span class="mtk1"> </span><span class="mtk4">=&gt;</span><span class="mtk1"> {</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk3">// Custom validation logic here</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk11">setError</span><span class="mtk1">(</span><span class="mtk12">event</span><span class="mtk1">.</span><span class="mtk12">target</span><span class="mtk1">.</span><span class="mtk12">value</span><span class="mtk1">.</span><span class="mtk12">length</span><span class="mtk1"> &lt; </span><span class="mtk7">3</span><span class="mtk1">);</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> };</span></span></span> <span class="grvsc-line"><span class="grvsc-source"></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk15">return</span><span class="mtk1"> (</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk17">&lt;</span><span class="mtk10">FormControl</span><span class="mtk1"> </span><span class="mtk12">error</span><span class="mtk1">=</span><span class="mtk4">{</span><span class="mtk12">error</span><span class="mtk4">}</span><span class="mtk17">&gt;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk17">&lt;</span><span class="mtk10">Input</span><span class="mtk1"> </span><span class="mtk12">onChange</span><span class="mtk1">=</span><span class="mtk4">{</span><span class="mtk12">handleChange</span><span class="mtk4">}</span><span class="mtk1"> </span><span class="mtk17">/&gt;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk17">&lt;</span><span class="mtk10">CustomHelperText</span><span class="mtk1"> </span><span class="mtk17">/&gt;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk17">&lt;/</span><span class="mtk10">FormControl</span><span class="mtk17">&gt;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> );</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1">}</span></span></span></code></pre> <div id="InputValidation" data-code data-height="100px"></div> <p>In this example, the <code>CustomHelperText</code> component accesses the error state using the <code>useFormControl</code> hook. When the input value is less than three characters, the error state is set to <code>true</code>, and the helper text changes to an error message. This demonstrates how the FormControl context can create dynamic form elements that respond to user input.</p> <h3 id="focused-state" style="position:relative;"><a href="#focused-state" aria-label="focused state permalink" class="anchor before"><svg aria-hidden="true" focusable="false" height="16" version="1.1" viewBox="0 0 16 16" width="16"><path fill-rule="evenodd" d="M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z"></path></svg></a>Focused State</h3> <p>The focused state is another important context provided by the FormControl component. When an input field is focused, the FormControl reflects this state, allowing child elements to update their appearance accordingly.</p> <p>In the following example, we’ll create a custom component that displays a message based on the focused state of the input field:</p> <pre class="grvsc-container default-dark" data-language="jsx" data-index="2"><code class="grvsc-code"><span class="grvsc-line"><span class="grvsc-source"><span class="mtk15">import</span><span class="mtk1"> </span><span class="mtk12">React</span><span class="mtk1"> </span><span class="mtk15">from</span><span class="mtk1"> </span><span class="mtk8">&quot;react&quot;</span><span class="mtk1">;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk15">import</span><span class="mtk1"> </span><span class="mtk12">Input</span><span class="mtk1"> </span><span class="mtk15">from</span><span class="mtk1"> </span><span class="mtk8">&quot;@mui/material/Input&quot;</span><span class="mtk1">;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk15">import</span><span class="mtk1"> </span><span class="mtk12">FormControl</span><span class="mtk1">, { </span><span class="mtk12">useFormControl</span><span class="mtk1"> } </span><span class="mtk15">from</span><span class="mtk1"> </span><span class="mtk8">&quot;@mui/material/FormControl&quot;</span><span class="mtk1">;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk4">function</span><span class="mtk1"> </span><span class="mtk11">FocusIndicator</span><span class="mtk1">() {</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk4">const</span><span class="mtk1"> </span><span class="mtk12">formControl</span><span class="mtk1"> = </span><span class="mtk11">useFormControl</span><span class="mtk1">();</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk4">const</span><span class="mtk1"> </span><span class="mtk12">focused</span><span class="mtk1"> = </span><span class="mtk12">formControl</span><span class="mtk1">?.</span><span class="mtk12">focused</span><span class="mtk1"> || </span><span class="mtk4">false</span><span class="mtk1">;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk15">return</span><span class="mtk1"> </span><span class="mtk17">&lt;</span><span class="mtk4">div</span><span class="mtk17">&gt;</span><span class="mtk4">{</span><span class="mtk12">focused</span><span class="mtk1"> ? </span><span class="mtk8">&quot;Input is focused&quot;</span><span class="mtk1"> : </span><span class="mtk8">&quot;Input is not focused&quot;</span><span class="mtk4">}</span><span class="mtk17">&lt;/</span><span class="mtk4">div</span><span class="mtk17">&gt;</span><span class="mtk1">;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1">}</span></span></span> <span class="grvsc-line"><span class="grvsc-source"></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk15">export</span><span class="mtk1"> </span><span class="mtk15">default</span><span class="mtk1"> </span><span class="mtk4">function</span><span class="mtk1"> </span><span class="mtk11">InputFocus</span><span class="mtk1">() {</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk15">return</span><span class="mtk1"> (</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk17">&lt;</span><span class="mtk10">FormControl</span><span class="mtk17">&gt;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk17">&lt;</span><span class="mtk10">Input</span><span class="mtk1"> </span><span class="mtk17">/&gt;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk17">&lt;</span><span class="mtk10">FocusIndicator</span><span class="mtk1"> </span><span class="mtk17">/&gt;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk17">&lt;/</span><span class="mtk10">FormControl</span><span class="mtk17">&gt;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> );</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1">}</span></span></span></code></pre> <div id="InputFocus" data-code data-height="100px"></div> <p>In this example, the <code>FocusIndicator</code> component accesses the focused state using the <code>useFormControl</code> hook. When the input field is focused, the message “Input is focused” is displayed; when it’s not, the message “Input is not focused” is displayed. This demonstrates how the FormControl context can be used to create dynamic form elements that respond to user interaction.</p> <h3 id="filled-state" style="position:relative;"><a href="#filled-state" aria-label="filled state permalink" class="anchor before"><svg aria-hidden="true" focusable="false" height="16" version="1.1" viewBox="0 0 16 16" width="16"><path fill-rule="evenodd" d="M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z"></path></svg></a>Filled State</h3> <p>The filled state indicates whether the input has a value, allowing for custom styling or behavior when an input field is not empty.</p> <p>The following example demonstrates how to access the filled state using the <code>useFormControl</code> hook:</p> <pre class="grvsc-container default-dark" data-language="jsx" data-index="3"><code class="grvsc-code"><span class="grvsc-line"><span class="grvsc-source"><span class="mtk15">import</span><span class="mtk1"> </span><span class="mtk12">React</span><span class="mtk1"> </span><span class="mtk15">from</span><span class="mtk1"> </span><span class="mtk8">&quot;react&quot;</span><span class="mtk1">;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk15">import</span><span class="mtk1"> </span><span class="mtk12">Input</span><span class="mtk1"> </span><span class="mtk15">from</span><span class="mtk1"> </span><span class="mtk8">&quot;@mui/material/Input&quot;</span><span class="mtk1">;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk15">import</span><span class="mtk1"> </span><span class="mtk12">FormHelperText</span><span class="mtk1"> </span><span class="mtk15">from</span><span class="mtk1"> </span><span class="mtk8">&quot;@mui/material/FormHelperText&quot;</span><span class="mtk1">;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk15">import</span><span class="mtk1"> </span><span class="mtk12">FormControl</span><span class="mtk1">, { </span><span class="mtk12">useFormControl</span><span class="mtk1"> } </span><span class="mtk15">from</span><span class="mtk1"> </span><span class="mtk8">&quot;@mui/material/FormControl&quot;</span><span class="mtk1">;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk4">function</span><span class="mtk1"> </span><span class="mtk11">FilledIndicator</span><span class="mtk1">() {</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk4">const</span><span class="mtk1"> </span><span class="mtk12">formControl</span><span class="mtk1"> = </span><span class="mtk11">useFormControl</span><span class="mtk1">();</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk4">const</span><span class="mtk1"> </span><span class="mtk12">filled</span><span class="mtk1"> = </span><span class="mtk12">formControl</span><span class="mtk1">?.</span><span class="mtk12">filled</span><span class="mtk1"> || </span><span class="mtk4">false</span><span class="mtk1">;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk15">return</span><span class="mtk1"> (</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk17">&lt;</span><span class="mtk10">FormHelperText</span><span class="mtk17">&gt;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk4">{</span><span class="mtk12">filled</span><span class="mtk1"> ? </span><span class="mtk8">&quot;Input has value&quot;</span><span class="mtk1"> : </span><span class="mtk8">&quot;Input is empty&quot;</span><span class="mtk4">}</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk17">&lt;/</span><span class="mtk10">FormHelperText</span><span class="mtk17">&gt;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> );</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1">}</span></span></span> <span class="grvsc-line"><span class="grvsc-source"></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk15">export</span><span class="mtk1"> </span><span class="mtk15">default</span><span class="mtk1"> </span><span class="mtk4">function</span><span class="mtk1"> </span><span class="mtk11">InputFilled</span><span class="mtk1">() {</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk15">return</span><span class="mtk1"> (</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk17">&lt;</span><span class="mtk10">FormControl</span><span class="mtk17">&gt;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk17">&lt;</span><span class="mtk10">Input</span><span class="mtk1"> </span><span class="mtk12">defaultValue</span><span class="mtk1">=</span><span class="mtk8">&quot;&quot;</span><span class="mtk1"> </span><span class="mtk17">/&gt;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk17">&lt;</span><span class="mtk10">FilledIndicator</span><span class="mtk1"> </span><span class="mtk17">/&gt;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk17">&lt;/</span><span class="mtk10">FormControl</span><span class="mtk17">&gt;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> );</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1">}</span></span></span></code></pre> <div id="InputFilled" data-code data-height="100px"></div> <p>In this example, the <code>FilledIndicator</code> component accesses the filled state using the <code>useFormControl</code> hook. When the input field has a value, the message “Input has value” is displayed, and when it’s empty, the message “Input is empty” is displayed.</p> <h3 id="required-state" style="position:relative;"><a href="#required-state" aria-label="required state permalink" class="anchor before"><svg aria-hidden="true" focusable="false" height="16" version="1.1" viewBox="0 0 16 16" width="16"><path fill-rule="evenodd" d="M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z"></path></svg></a>Required State</h3> <p>The required state can be used to indicate that an input is mandatory, providing visual cues or validations to ensure users fill out essential fields.</p> <p>The following example demonstrates how to access the required state using the <code>useFormControl</code> hook:</p> <pre class="grvsc-container default-dark" data-language="jsx" data-index="4"><code class="grvsc-code"><span class="grvsc-line"><span class="grvsc-source"><span class="mtk15">import</span><span class="mtk1"> </span><span class="mtk12">React</span><span class="mtk1"> </span><span class="mtk15">from</span><span class="mtk1"> </span><span class="mtk8">&quot;react&quot;</span><span class="mtk1">;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk15">import</span><span class="mtk1"> </span><span class="mtk12">Input</span><span class="mtk1"> </span><span class="mtk15">from</span><span class="mtk1"> </span><span class="mtk8">&quot;@mui/material/Input&quot;</span><span class="mtk1">;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk15">import</span><span class="mtk1"> </span><span class="mtk12">Stack</span><span class="mtk1"> </span><span class="mtk15">from</span><span class="mtk1"> </span><span class="mtk8">&quot;@mui/material/Stack&quot;</span><span class="mtk1">;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk15">import</span><span class="mtk1"> </span><span class="mtk12">FormHelperText</span><span class="mtk1"> </span><span class="mtk15">from</span><span class="mtk1"> </span><span class="mtk8">&quot;@mui/material/FormHelperText&quot;</span><span class="mtk1">;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk15">import</span><span class="mtk1"> </span><span class="mtk12">FormControl</span><span class="mtk1">, { </span><span class="mtk12">useFormControl</span><span class="mtk1"> } </span><span class="mtk15">from</span><span class="mtk1"> </span><span class="mtk8">&quot;@mui/material/FormControl&quot;</span><span class="mtk1">;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk4">function</span><span class="mtk1"> </span><span class="mtk11">RequiredIndicator</span><span class="mtk1">() {</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk4">const</span><span class="mtk1"> </span><span class="mtk12">formControl</span><span class="mtk1"> = </span><span class="mtk11">useFormControl</span><span class="mtk1">();</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk4">const</span><span class="mtk1"> </span><span class="mtk12">required</span><span class="mtk1"> = </span><span class="mtk12">formControl</span><span class="mtk1">?.</span><span class="mtk12">required</span><span class="mtk1"> || </span><span class="mtk4">false</span><span class="mtk1">;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk15">return</span><span class="mtk1"> (</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk17">&lt;</span><span class="mtk10">FormHelperText</span><span class="mtk17">&gt;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk4">{</span><span class="mtk12">required</span><span class="mtk1"> ? </span><span class="mtk8">&quot;This field is required&quot;</span><span class="mtk1"> : </span><span class="mtk8">&quot;This field is optional&quot;</span><span class="mtk4">}</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk17">&lt;/</span><span class="mtk10">FormHelperText</span><span class="mtk17">&gt;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> );</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1">}</span></span></span> <span class="grvsc-line"><span class="grvsc-source"></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk15">export</span><span class="mtk1"> </span><span class="mtk15">default</span><span class="mtk1"> </span><span class="mtk4">function</span><span class="mtk1"> </span><span class="mtk11">InputRequired</span><span class="mtk1">() {</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk15">return</span><span class="mtk1"> (</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk17">&lt;</span><span class="mtk10">Stack</span><span class="mtk1"> </span><span class="mtk12">sx</span><span class="mtk1">=</span><span class="mtk4">{</span><span class="mtk1">{ </span><span class="mtk12">width:</span><span class="mtk1"> </span><span class="mtk8">&quot;200px&quot;</span><span class="mtk1"> }</span><span class="mtk4">}</span><span class="mtk17">&gt;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk17">&lt;</span><span class="mtk10">FormControl</span><span class="mtk17">&gt;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk17">&lt;</span><span class="mtk10">Input</span><span class="mtk1"> </span><span class="mtk17">/&gt;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk17">&lt;</span><span class="mtk10">RequiredIndicator</span><span class="mtk1"> </span><span class="mtk17">/&gt;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk17">&lt;/</span><span class="mtk10">FormControl</span><span class="mtk17">&gt;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk17">&lt;</span><span class="mtk10">FormControl</span><span class="mtk1"> </span><span class="mtk12">required</span><span class="mtk17">&gt;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk17">&lt;</span><span class="mtk10">Input</span><span class="mtk1"> </span><span class="mtk17">/&gt;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk17">&lt;</span><span class="mtk10">RequiredIndicator</span><span class="mtk1"> </span><span class="mtk17">/&gt;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk17">&lt;/</span><span class="mtk10">FormControl</span><span class="mtk17">&gt;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk17">&lt;/</span><span class="mtk10">Stack</span><span class="mtk17">&gt;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> );</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1">}</span></span></span></code></pre> <div id="InputRequired" data-code data-height="150px"></div> <p>In this example, the <code>RequiredIndicator</code> component accesses the required state using the <code>useFormControl</code> hook. When the input field is marked as required, the message “This field is required” is displayed, and when it’s optional, the message “This field is optional” is displayed.</p> <h2 id="customizing-textfield-appearance" style="position:relative;"><a href="#customizing-textfield-appearance" aria-label="customizing textfield appearance permalink" class="anchor before"><svg aria-hidden="true" focusable="false" height="16" version="1.1" viewBox="0 0 16 16" width="16"><path fill-rule="evenodd" d="M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z"></path></svg></a>Customizing TextField Appearance</h2> <p>A <code>TextField</code> in Material UI comprises smaller components, allowing extensive customization and styling flexibility. When wrapped with a <code>FormControl</code>, these components can be individually styled and manipulated to fit any design requirement. The primary components involved are:</p> <ul> <li><code>FormLabel</code>: Provides a label for the input.</li> <li><code>FormHelperText</code>: Offers additional hints or error messages.</li> <li><code>Input</code>: The actual input field where the user types.</li> <li><code>InputLabel</code>: Acts as a label specifically for the Input component, offering more integration with Material UI’s style system.</li> </ul> <p>By customizing these components, you can achieve high styling customization. Here’s an example showcasing how to use all these components together for complete styling flexibility:</p> <pre class="grvsc-container default-dark" data-language="jsx" data-index="5"><code class="grvsc-code"><span class="grvsc-line"><span class="grvsc-source"><span class="mtk15">import</span><span class="mtk1"> </span><span class="mtk12">React</span><span class="mtk1"> </span><span class="mtk15">from</span><span class="mtk1"> </span><span class="mtk8">&quot;react&quot;</span><span class="mtk1">;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk15">import</span><span class="mtk1"> </span><span class="mtk12">FormControl</span><span class="mtk1"> </span><span class="mtk15">from</span><span class="mtk1"> </span><span class="mtk8">&quot;@mui/material/FormControl&quot;</span><span class="mtk1">;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk15">import</span><span class="mtk1"> </span><span class="mtk12">Input</span><span class="mtk1"> </span><span class="mtk15">from</span><span class="mtk1"> </span><span class="mtk8">&quot;@mui/material/Input&quot;</span><span class="mtk1">;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk15">import</span><span class="mtk1"> </span><span class="mtk12">InputLabel</span><span class="mtk1"> </span><span class="mtk15">from</span><span class="mtk1"> </span><span class="mtk8">&quot;@mui/material/InputLabel&quot;</span><span class="mtk1">;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk15">import</span><span class="mtk1"> { </span><span class="mtk12">styled</span><span class="mtk1"> } </span><span class="mtk15">from</span><span class="mtk1"> </span><span class="mtk8">&quot;@mui/material/styles&quot;</span><span class="mtk1">;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk4">const</span><span class="mtk1"> </span><span class="mtk12">CustomInput</span><span class="mtk1"> = </span><span class="mtk11">styled</span><span class="mtk1">(</span><span class="mtk12">Input</span><span class="mtk1">)({</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk8">&quot;&amp;.MuiInput-root&quot;</span><span class="mtk12">:</span><span class="mtk1"> {</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">margin:</span><span class="mtk1"> </span><span class="mtk7">0</span><span class="mtk1">,</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> },</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk8">&quot;&amp; .MuiInputBase-input&quot;</span><span class="mtk12">:</span><span class="mtk1"> {</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">borderRadius:</span><span class="mtk1"> </span><span class="mtk7">5</span><span class="mtk1">,</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">position:</span><span class="mtk1"> </span><span class="mtk8">&quot;relative&quot;</span><span class="mtk1">,</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">border:</span><span class="mtk1"> </span><span class="mtk8">&quot;1px solid #ced4da&quot;</span><span class="mtk1">,</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">padding:</span><span class="mtk1"> </span><span class="mtk8">&quot;10px 12px&quot;</span><span class="mtk1">,</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> },</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1">});</span></span></span> <span class="grvsc-line"><span class="grvsc-source"></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk4">const</span><span class="mtk1"> </span><span class="mtk12">CustomInputLabel</span><span class="mtk1"> = </span><span class="mtk11">styled</span><span class="mtk1">(</span><span class="mtk12">InputLabel</span><span class="mtk1">)({</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">position:</span><span class="mtk1"> </span><span class="mtk8">&quot;relative&quot;</span><span class="mtk1">,</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">transform:</span><span class="mtk1"> </span><span class="mtk8">&quot;none&quot;</span><span class="mtk1">,</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">marginBottom:</span><span class="mtk1"> </span><span class="mtk8">&quot;5px&quot;</span><span class="mtk1">,</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1">});</span></span></span> <span class="grvsc-line"><span class="grvsc-source"></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk15">export</span><span class="mtk1"> </span><span class="mtk15">default</span><span class="mtk1"> </span><span class="mtk4">function</span><span class="mtk1"> </span><span class="mtk11">CustomInputComponent</span><span class="mtk1">() {</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk15">return</span><span class="mtk1"> (</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk17">&lt;</span><span class="mtk10">FormControl</span><span class="mtk1"> </span><span class="mtk12">variant</span><span class="mtk1">=</span><span class="mtk8">&quot;standard&quot;</span><span class="mtk17">&gt;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk17">&lt;</span><span class="mtk10">CustomInputLabel</span><span class="mtk1"> </span><span class="mtk12">htmlFor</span><span class="mtk1">=</span><span class="mtk8">&quot;custom-input&quot;</span><span class="mtk17">&gt;</span><span class="mtk1">Email</span><span class="mtk17">&lt;/</span><span class="mtk10">CustomInputLabel</span><span class="mtk17">&gt;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk17">&lt;</span><span class="mtk10">CustomInput</span><span class="mtk1"> </span><span class="mtk12">id</span><span class="mtk1">=</span><span class="mtk8">&quot;custom-input&quot;</span><span class="mtk1"> </span><span class="mtk12">disableUnderline</span><span class="mtk1"> </span><span class="mtk17">/&gt;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk17">&lt;/</span><span class="mtk10">FormControl</span><span class="mtk17">&gt;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> );</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1">}</span></span></span></code></pre> <div id="CustomInput" data-code data-height="100px"></div> <p>In this example, we’ve used the <code>styled</code> function from Material UI to create custom styles for the <code>Input</code> and <code>InputLabel</code> components. By applying these styles, we’ve achieved a custom appearance for the input field and label, including a border radius, border color, and spacing between the label and input.</p> <h2 id="conclusion" style="position:relative;"><a href="#conclusion" aria-label="conclusion permalink" class="anchor before"><svg aria-hidden="true" focusable="false" height="16" version="1.1" viewBox="0 0 16 16" width="16"><path fill-rule="evenodd" d="M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z"></path></svg></a>Conclusion</h2> <p>Throughout this tutorial, we’ve explored the versatile nature of Material UI’s <code>FormControl</code> and its ability to provide context and enhance the functionality of form inputs. By understanding and utilizing the <code>FormControl</code> component, you can create more responsive, accessible, and styled forms.</p> <p>With a detailed explanation of its context management, through states like error, focused, filled, and required, and the ability to fully customize each part of the TextField, we’re now equipped to build complex forms that are both user-friendly and adhere to modern design standards.</p> <p>The complete <a href="https://mui.com/material-ui/api/form-control/">Material UI documentation</a> is an excellent resource for further exploration of FormControl’s props and capabilities, ensuring that our forms will be functional and seamlessly integrated into our projects.</p> <style class="grvsc-styles"> .grvsc-container { overflow: auto; position: relative; -webkit-overflow-scrolling: touch; padding-top: 1rem; padding-top: var(--grvsc-padding-top, var(--grvsc-padding-v, 1rem)); padding-bottom: 1rem; padding-bottom: var(--grvsc-padding-bottom, var(--grvsc-padding-v, 1rem)); border-radius: 8px; border-radius: var(--grvsc-border-radius, 8px); font-feature-settings: normal; line-height: 1.4; } .grvsc-code { display: table; } .grvsc-line { display: table-row; box-sizing: border-box; width: 100%; position: relative; } .grvsc-line > * { position: relative; } .grvsc-gutter-pad { display: table-cell; padding-left: 0.75rem; padding-left: calc(var(--grvsc-padding-left, var(--grvsc-padding-h, 1.5rem)) / 2); } .grvsc-gutter { display: table-cell; -webkit-user-select: none; -moz-user-select: none; user-select: none; } .grvsc-gutter::before { content: attr(data-content); } .grvsc-source { display: table-cell; padding-left: 1.5rem; padding-left: var(--grvsc-padding-left, var(--grvsc-padding-h, 1.5rem)); padding-right: 1.5rem; padding-right: var(--grvsc-padding-right, var(--grvsc-padding-h, 1.5rem)); } .grvsc-source:empty::after { content: ' '; -webkit-user-select: none; -moz-user-select: none; user-select: none; } .grvsc-gutter + .grvsc-source { padding-left: 0.75rem; padding-left: calc(var(--grvsc-padding-left, var(--grvsc-padding-h, 1.5rem)) / 2); } /* Line transformer styles */ .grvsc-has-line-highlighting > .grvsc-code > .grvsc-line::before { content: ' '; position: absolute; width: 100%; } .grvsc-line-diff-add::before { background-color: var(--grvsc-line-diff-add-background-color, rgba(0, 255, 60, 0.2)); } .grvsc-line-diff-del::before { background-color: var(--grvsc-line-diff-del-background-color, rgba(255, 0, 20, 0.2)); } .grvsc-line-number { padding: 0 2px; text-align: right; opacity: 0.7; } .default-dark { background-color: #1E1E1E; color: #D4D4D4; } .default-dark .mtk15 { color: #C586C0; } .default-dark .mtk1 { color: #D4D4D4; } .default-dark .mtk12 { color: #9CDCFE; } .default-dark .mtk8 { color: #CE9178; } .default-dark .mtk4 { color: #569CD6; } .default-dark .mtk11 { color: #DCDCAA; } .default-dark .mtk17 { color: #808080; } .default-dark .mtk10 { color: #4EC9B0; } .default-dark .mtk3 { color: #6A9955; } .default-dark .mtk7 { color: #B5CEA8; } .default-dark .grvsc-line-highlighted::before { background-color: var(--grvsc-line-highlighted-background-color, rgba(255, 255, 255, 0.1)); box-shadow: inset var(--grvsc-line-highlighted-border-width, 4px) 0 0 0 var(--grvsc-line-highlighted-border-color, rgba(255, 255, 255, 0.5)); } </style><![CDATA[MUI TextField: How to Customize Variants, Colors & Styles]]>https://muhimasri.commui-textfield-colors-styleshttps://muhimasri.commui-textfield-colors-styles<p>Customizing TextField colors is an essential part of building a beautiful UI. MUI <code>TextField</code> component is not just an input field, but it’s a wrapper that contains multiple elements like the label, input, text helper, error and more. That’s why styling it is a bit different than a regular input field. In this tutorial, we will learn how to customize the colors of the <code>TextField</code> component in Material UI (MUI) and React including the border, label, and text colors for different variants.</p> <p>The classes that we will use to customize the <code>TextField</code> styles and colors are based on the variant prop. So to find the class we need, we will have to choose the variant first. Let’s go through the different variants and see how we can customize the colors and styles for each one.</p> <h2 id="outlined-variant" style="position:relative;"><a href="#outlined-variant" aria-label="outlined variant permalink" class="anchor before"><svg aria-hidden="true" focusable="false" height="16" version="1.1" viewBox="0 0 16 16" width="16"><path fill-rule="evenodd" d="M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z"></path></svg></a>Outlined Variant</h2> <p>The <code>outlined</code> variant is the default variant for the <code>TextField</code> component. It has a border around the input field and a label that floats above the input when the user starts typing. To customize the colors of the <code>TextField</code> with the <code>outlined</code> variant, there are three main classes that we can use:</p> <ul> <li><code>MuiOutlinedInput-root</code>: The root class for the input field.</li> <li><code>MuiInputLabel-outlined</code>: The class for the label.</li> <li><code>MuiOutlinedInput-notchedOutline</code>: The class for the border.</li> </ul> <p>In the following example, we’re going to override the default colors and styles using the <code>sx</code> prop.</p> <h3 id="outlined-custom-styles" style="position:relative;"><a href="#outlined-custom-styles" aria-label="outlined custom styles permalink" class="anchor before"><svg aria-hidden="true" focusable="false" height="16" version="1.1" viewBox="0 0 16 16" width="16"><path fill-rule="evenodd" d="M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z"></path></svg></a>Outlined Custom Styles</h3> <pre class="grvsc-container default-dark" data-language="jsx" data-index="0"><code class="grvsc-code"><span class="grvsc-line"><span class="grvsc-source"><span class="mtk15">import</span><span class="mtk1"> </span><span class="mtk12">React</span><span class="mtk1"> </span><span class="mtk15">from</span><span class="mtk1"> </span><span class="mtk8">&quot;react&quot;</span><span class="mtk1">;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk15">import</span><span class="mtk1"> </span><span class="mtk12">TextField</span><span class="mtk1"> </span><span class="mtk15">from</span><span class="mtk1"> </span><span class="mtk8">&quot;@mui/material/TextField&quot;</span><span class="mtk1">;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk15">export</span><span class="mtk1"> </span><span class="mtk15">default</span><span class="mtk1"> </span><span class="mtk4">function</span><span class="mtk1"> </span><span class="mtk11">OutlinedTextField</span><span class="mtk1">() {</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk15">return</span><span class="mtk1"> (</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk17">&lt;</span><span class="mtk10">TextField</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">label</span><span class="mtk1">=</span><span class="mtk8">&quot;Outlined&quot;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">variant</span><span class="mtk1">=</span><span class="mtk8">&quot;outlined&quot;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">sx</span><span class="mtk1">=</span><span class="mtk4">{</span><span class="mtk1">{</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk3">// Root class for the input field</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk8">&quot;&amp; .MuiOutlinedInput-root&quot;</span><span class="mtk12">:</span><span class="mtk1"> {</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">color:</span><span class="mtk1"> </span><span class="mtk8">&quot;#000&quot;</span><span class="mtk1">,</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">fontFamily:</span><span class="mtk1"> </span><span class="mtk8">&quot;Arial&quot;</span><span class="mtk1">,</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">fontWeight:</span><span class="mtk1"> </span><span class="mtk8">&quot;bold&quot;</span><span class="mtk1">,</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk3">// Class for the border around the input field</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk8">&quot;&amp; .MuiOutlinedInput-notchedOutline&quot;</span><span class="mtk12">:</span><span class="mtk1"> {</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">borderColor:</span><span class="mtk1"> </span><span class="mtk8">&quot;#2e2e2e&quot;</span><span class="mtk1">,</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">borderWidth:</span><span class="mtk1"> </span><span class="mtk8">&quot;2px&quot;</span><span class="mtk1">,</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> },</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> },</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk3">// Class for the label of the input field</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk8">&quot;&amp; .MuiInputLabel-outlined&quot;</span><span class="mtk12">:</span><span class="mtk1"> {</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">color:</span><span class="mtk1"> </span><span class="mtk8">&quot;#2e2e2e&quot;</span><span class="mtk1">,</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">fontWeight:</span><span class="mtk1"> </span><span class="mtk8">&quot;bold&quot;</span><span class="mtk1">,</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> },</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> }</span><span class="mtk4">}</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk17">/&gt;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> );</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1">}</span></span></span></code></pre> <div id="OutlinedTextFieldStyle" data-code data-height="75px"></div> <h3 id="outlined-focused-state" style="position:relative;"><a href="#outlined-focused-state" aria-label="outlined focused state permalink" class="anchor before"><svg aria-hidden="true" focusable="false" height="16" version="1.1" viewBox="0 0 16 16" width="16"><path fill-rule="evenodd" d="M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z"></path></svg></a>Outlined Focused State</h3> <p>Although we can see the styles reflected properly in the example above, when focusing on the input field, the changes are not applied. The focused state has it’s own colors and styles and they are directly related to the theme colors. Meaning, if we use the <code>color</code> prop and set it to <code>secondary</code>, we will see the colors of the focused state changes.</p> <pre class="grvsc-container grvsc-has-line-highlighting default-dark" data-language="jsx" data-index="1"><code class="grvsc-code"><span class="grvsc-line"><span class="grvsc-source"><span class="mtk1">...</span></span></span> <span class="grvsc-line"><span class="grvsc-source"></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk15">export</span><span class="mtk1"> </span><span class="mtk15">default</span><span class="mtk1"> </span><span class="mtk4">function</span><span class="mtk1"> </span><span class="mtk11">OutlinedTextField</span><span class="mtk1">() {</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk15">return</span><span class="mtk1"> (</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk17">&lt;</span><span class="mtk10">TextField</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">label</span><span class="mtk1">=</span><span class="mtk8">&quot;Outlined&quot;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">variant</span><span class="mtk1">=</span><span class="mtk8">&quot;outlined&quot;</span></span></span> <span class="grvsc-line grvsc-line-highlighted"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">color</span><span class="mtk1">=</span><span class="mtk8">&quot;secondary&quot;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">sx</span><span class="mtk1">=</span><span class="mtk4">{</span><span class="mtk1">{</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> ...</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> }</span><span class="mtk4">}</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk17">/&gt;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> );</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1">}</span></span></span></code></pre> <div id="OutlinedTextFieldStyleColor" data-code data-height="75px"></div> <p>While it’s correct that the focused state should have different colors (like the primary or secondary color of the theme), we need to apply the other styles to the focused state as well. To do that, we can use the <code>&#x26;.Mui-focused</code> class to target the focused state and apply the styles we need.</p> <pre class="grvsc-container grvsc-has-line-highlighting default-dark" data-language="jsx" data-index="2"><code class="grvsc-code"><span class="grvsc-line"><span class="grvsc-source"><span class="mtk1">...</span></span></span> <span class="grvsc-line"><span class="grvsc-source"></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk15">export</span><span class="mtk1"> </span><span class="mtk15">default</span><span class="mtk1"> </span><span class="mtk4">function</span><span class="mtk1"> </span><span class="mtk11">OutlinedTextField</span><span class="mtk1">() {</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk15">return</span><span class="mtk1"> (</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk17">&lt;</span><span class="mtk10">TextField</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">label</span><span class="mtk1">=</span><span class="mtk8">&quot;Outlined&quot;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">variant</span><span class="mtk1">=</span><span class="mtk8">&quot;outlined&quot;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">color</span><span class="mtk1">=</span><span class="mtk8">&quot;secondary&quot;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">sx</span><span class="mtk1">=</span><span class="mtk4">{</span><span class="mtk1">{</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk8">&quot;&amp; .MuiOutlinedInput-root&quot;</span><span class="mtk12">:</span><span class="mtk1"> {</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">color:</span><span class="mtk1"> </span><span class="mtk8">&quot;#000&quot;</span><span class="mtk1">,</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">fontFamily:</span><span class="mtk1"> </span><span class="mtk8">&quot;Arial&quot;</span><span class="mtk1">,</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">fontWeight:</span><span class="mtk1"> </span><span class="mtk8">&quot;bold&quot;</span><span class="mtk1">,</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk8">&quot;&amp; .MuiOutlinedInput-notchedOutline&quot;</span><span class="mtk12">:</span><span class="mtk1"> {</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">borderColor:</span><span class="mtk1"> </span><span class="mtk8">&quot;#2e2e2e&quot;</span><span class="mtk1">,</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">borderWidth:</span><span class="mtk1"> </span><span class="mtk8">&quot;2px&quot;</span><span class="mtk1">,</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> },</span></span></span> <span class="grvsc-line grvsc-line-highlighted"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk8">&quot;&amp;.Mui-focused&quot;</span><span class="mtk12">:</span><span class="mtk1"> {</span></span></span> <span class="grvsc-line grvsc-line-highlighted"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk8">&quot;&amp; .MuiOutlinedInput-notchedOutline&quot;</span><span class="mtk12">:</span><span class="mtk1"> {</span></span></span> <span class="grvsc-line grvsc-line-highlighted"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">borderColor:</span><span class="mtk1"> </span><span class="mtk8">&quot;secondary.main&quot;</span><span class="mtk1">,</span></span></span> <span class="grvsc-line grvsc-line-highlighted"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">borderWidth:</span><span class="mtk1"> </span><span class="mtk8">&quot;3px&quot;</span><span class="mtk1">,</span></span></span> <span class="grvsc-line grvsc-line-highlighted"><span class="grvsc-source"><span class="mtk1"> },</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> },</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk8">&quot;&amp; .MuiInputLabel-outlined&quot;</span><span class="mtk12">:</span><span class="mtk1"> {</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">color:</span><span class="mtk1"> </span><span class="mtk8">&quot;#2e2e2e&quot;</span><span class="mtk1">,</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">fontWeight:</span><span class="mtk1"> </span><span class="mtk8">&quot;bold&quot;</span><span class="mtk1">,</span></span></span> <span class="grvsc-line grvsc-line-highlighted"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk8">&quot;&amp;.Mui-focused&quot;</span><span class="mtk12">:</span><span class="mtk1"> {</span></span></span> <span class="grvsc-line grvsc-line-highlighted"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">color:</span><span class="mtk1"> </span><span class="mtk8">&quot;secondary.main&quot;</span><span class="mtk1">,</span></span></span> <span class="grvsc-line grvsc-line-highlighted"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">fontWeight:</span><span class="mtk1"> </span><span class="mtk8">&quot;bold&quot;</span><span class="mtk1">,</span></span></span> <span class="grvsc-line grvsc-line-highlighted"><span class="grvsc-source"><span class="mtk1"> },</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> },</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> },</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> }</span><span class="mtk4">}</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk17">/&gt;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> );</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1">}</span></span></span></code></pre> <div id="OutlinedTextFieldStyleFocused" data-code data-height="75px"></div> <p>The <code>Mui-focused</code> class is at the root level and that’s why the <code>MuiOutlinedInput-notchedOutline</code> class is nested inside it. Now, when focused, the label, border color and width will change.</p> <h3 id="outlined-hover-state" style="position:relative;"><a href="#outlined-hover-state" aria-label="outlined hover state permalink" class="anchor before"><svg aria-hidden="true" focusable="false" height="16" version="1.1" viewBox="0 0 16 16" width="16"><path fill-rule="evenodd" d="M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z"></path></svg></a>Outlined Hover State</h3> <p>After applying the new styles, the default hover state can be effected. We can use the <code>&#x26;:hover</code> class to apply the styles we need for the hover state.</p> <pre class="grvsc-container grvsc-has-line-highlighting default-dark" data-language="jsx" data-index="3"><code class="grvsc-code"><span class="grvsc-line"><span class="grvsc-source"><span class="mtk1">...</span></span></span> <span class="grvsc-line"><span class="grvsc-source"></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk15">export</span><span class="mtk1"> </span><span class="mtk15">default</span><span class="mtk1"> </span><span class="mtk4">function</span><span class="mtk1"> </span><span class="mtk11">OutlinedTextField</span><span class="mtk1">() {</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk15">return</span><span class="mtk1"> (</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk17">&lt;</span><span class="mtk10">TextField</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">label</span><span class="mtk1">=</span><span class="mtk8">&quot;Outlined&quot;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">variant</span><span class="mtk1">=</span><span class="mtk8">&quot;outlined&quot;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">color</span><span class="mtk1">=</span><span class="mtk8">&quot;secondary&quot;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">sx</span><span class="mtk1">=</span><span class="mtk4">{</span><span class="mtk1">{</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk8">&quot;&amp; .MuiOutlinedInput-root&quot;</span><span class="mtk12">:</span><span class="mtk1"> {</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">color:</span><span class="mtk1"> </span><span class="mtk8">&quot;#000&quot;</span><span class="mtk1">,</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">fontFamily:</span><span class="mtk1"> </span><span class="mtk8">&quot;Arial&quot;</span><span class="mtk1">,</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">fontWeight:</span><span class="mtk1"> </span><span class="mtk8">&quot;bold&quot;</span><span class="mtk1">,</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk8">&quot;&amp; .MuiOutlinedInput-notchedOutline&quot;</span><span class="mtk12">:</span><span class="mtk1"> {</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">borderColor:</span><span class="mtk1"> </span><span class="mtk8">&quot;#2e2e2e&quot;</span><span class="mtk1">,</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">borderWidth:</span><span class="mtk1"> </span><span class="mtk8">&quot;2px&quot;</span><span class="mtk1">,</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> },</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk8">&quot;&amp;.Mui-focused&quot;</span><span class="mtk12">:</span><span class="mtk1"> {</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk8">&quot;&amp; .MuiOutlinedInput-notchedOutline&quot;</span><span class="mtk12">:</span><span class="mtk1"> {</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">borderColor:</span><span class="mtk1"> </span><span class="mtk8">&quot;secondary.main&quot;</span><span class="mtk1">,</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">borderWidth:</span><span class="mtk1"> </span><span class="mtk8">&quot;3px&quot;</span><span class="mtk1">,</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> },</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> },</span></span></span> <span class="grvsc-line grvsc-line-highlighted"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk8">&quot;&amp;:hover:not(.Mui-focused)&quot;</span><span class="mtk12">:</span><span class="mtk1"> {</span></span></span> <span class="grvsc-line grvsc-line-highlighted"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk8">&quot;&amp; .MuiOutlinedInput-notchedOutline&quot;</span><span class="mtk12">:</span><span class="mtk1"> {</span></span></span> <span class="grvsc-line grvsc-line-highlighted"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">borderColor:</span><span class="mtk1"> </span><span class="mtk8">&quot;#ccc&quot;</span><span class="mtk1">,</span></span></span> <span class="grvsc-line grvsc-line-highlighted"><span class="grvsc-source"><span class="mtk1"> },</span></span></span> <span class="grvsc-line grvsc-line-highlighted"><span class="grvsc-source"><span class="mtk1"> },</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> },</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk8">&quot;&amp; .MuiInputLabel-outlined&quot;</span><span class="mtk12">:</span><span class="mtk1"> {</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">color:</span><span class="mtk1"> </span><span class="mtk8">&quot;#2e2e2e&quot;</span><span class="mtk1">,</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">fontWeight:</span><span class="mtk1"> </span><span class="mtk8">&quot;bold&quot;</span><span class="mtk1">,</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk8">&quot;&amp;.Mui-focused&quot;</span><span class="mtk12">:</span><span class="mtk1"> {</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">color:</span><span class="mtk1"> </span><span class="mtk8">&quot;secondary.main&quot;</span><span class="mtk1">,</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">fontWeight:</span><span class="mtk1"> </span><span class="mtk8">&quot;bold&quot;</span><span class="mtk1">,</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> },</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> },</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> }</span><span class="mtk4">}</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk17">/&gt;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> );</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1">}</span></span></span></code></pre> <div id="OutlinedTextFieldStyleHover" data-code data-height="75px"></div> <p>We also added <code>:not(.Mui-focused)</code> to the hover state to make sure the hover state is not applied when the input is focused.</p> <h2 id="filled-variant" style="position:relative;"><a href="#filled-variant" aria-label="filled variant permalink" class="anchor before"><svg aria-hidden="true" focusable="false" height="16" version="1.1" viewBox="0 0 16 16" width="16"><path fill-rule="evenodd" d="M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z"></path></svg></a>Filled Variant</h2> <p>The <code>filled</code> variant has a background color, a bottom border and a label that floats within the input when the user starts typing. To customize the colors and styles, there are two main classes that we can use:</p> <ul> <li><code>MuiFilledInput-root</code>: The root class for the input field.</li> <li><code>MuiInputLabel-filled</code>: The class for the label.</li> </ul> <h3 id="filled-custom-styles" style="position:relative;"><a href="#filled-custom-styles" aria-label="filled custom styles permalink" class="anchor before"><svg aria-hidden="true" focusable="false" height="16" version="1.1" viewBox="0 0 16 16" width="16"><path fill-rule="evenodd" d="M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z"></path></svg></a>Filled Custom Styles</h3> <p>In the following example, we’re going to override the default colors and styles using the <code>sx</code> prop:</p> <pre class="grvsc-container default-dark" data-language="jsx" data-index="4"><code class="grvsc-code"><span class="grvsc-line"><span class="grvsc-source"><span class="mtk15">import</span><span class="mtk1"> </span><span class="mtk12">React</span><span class="mtk1"> </span><span class="mtk15">from</span><span class="mtk1"> </span><span class="mtk8">&quot;react&quot;</span><span class="mtk1">;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk15">import</span><span class="mtk1"> </span><span class="mtk12">TextField</span><span class="mtk1"> </span><span class="mtk15">from</span><span class="mtk1"> </span><span class="mtk8">&quot;@mui/material/TextField&quot;</span><span class="mtk1">;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk15">export</span><span class="mtk1"> </span><span class="mtk15">default</span><span class="mtk1"> </span><span class="mtk4">function</span><span class="mtk1"> </span><span class="mtk11">FilledTextField</span><span class="mtk1">() {</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk15">return</span><span class="mtk1"> (</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk17">&lt;</span><span class="mtk10">TextField</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">label</span><span class="mtk1">=</span><span class="mtk8">&quot;Filled&quot;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">variant</span><span class="mtk1">=</span><span class="mtk8">&quot;filled&quot;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">sx</span><span class="mtk1">=</span><span class="mtk4">{</span><span class="mtk1">{</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk3">// Root class for the input field</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk8">&quot;&amp; .MuiFilledInput-root&quot;</span><span class="mtk12">:</span><span class="mtk1"> {</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">color:</span><span class="mtk1"> </span><span class="mtk8">&quot;#000&quot;</span><span class="mtk1">,</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">fontFamily:</span><span class="mtk1"> </span><span class="mtk8">&quot;Arial&quot;</span><span class="mtk1">,</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">fontWeight:</span><span class="mtk1"> </span><span class="mtk8">&quot;bold&quot;</span><span class="mtk1">,</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">backgroundColor:</span><span class="mtk1"> </span><span class="mtk8">&quot;#f4f4f4&quot;</span><span class="mtk1">,</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">borderTopLeftRadius:</span><span class="mtk1"> </span><span class="mtk8">&quot;7px&quot;</span><span class="mtk1">,</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">borderTopRightRadius:</span><span class="mtk1"> </span><span class="mtk8">&quot;7px&quot;</span><span class="mtk1">,</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> },</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk3">// Class for the label of the filled input field</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk8">&quot;&amp; .MuiInputLabel-filled&quot;</span><span class="mtk12">:</span><span class="mtk1"> {</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">color:</span><span class="mtk1"> </span><span class="mtk8">&quot;#2e2e2e&quot;</span><span class="mtk1">,</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">fontWeight:</span><span class="mtk1"> </span><span class="mtk8">&quot;bold&quot;</span><span class="mtk1">,</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> },</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> }</span><span class="mtk4">}</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk17">/&gt;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> );</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1">}</span></span></span></code></pre> <div id="FilledTextFieldStyle" data-code data-height="75px"></div> <p>As seen in the code above, using the <code>MuiFilledInput-root</code> class, we can change the background color, border radius and other styles. The <code>MuiInputLabel-filled</code> class is used to change the label styles.</p> <p>The bottom border is styled separatly as it’s created using the <code>&#x26;:before</code> pseudo-element which we can use to change the border color and width.</p> <pre class="grvsc-container grvsc-has-line-highlighting default-dark" data-language="jsx" data-index="5"><code class="grvsc-code"><span class="grvsc-line"><span class="grvsc-source"><span class="mtk1">...</span></span></span> <span class="grvsc-line"><span class="grvsc-source"></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk15">export</span><span class="mtk1"> </span><span class="mtk15">default</span><span class="mtk1"> </span><span class="mtk4">function</span><span class="mtk1"> </span><span class="mtk11">FilledTextField</span><span class="mtk1">() {</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk15">return</span><span class="mtk1"> (</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk17">&lt;</span><span class="mtk10">TextField</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">label</span><span class="mtk1">=</span><span class="mtk8">&quot;Filled&quot;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">variant</span><span class="mtk1">=</span><span class="mtk8">&quot;filled&quot;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">color</span><span class="mtk1">=</span><span class="mtk8">&quot;secondary&quot;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">sx</span><span class="mtk1">=</span><span class="mtk4">{</span><span class="mtk1">{</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk8">&quot;&amp; .MuiFilledInput-root&quot;</span><span class="mtk12">:</span><span class="mtk1"> {</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">color:</span><span class="mtk1"> </span><span class="mtk8">&quot;#000&quot;</span><span class="mtk1">,</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">fontFamily:</span><span class="mtk1"> </span><span class="mtk8">&quot;Arial&quot;</span><span class="mtk1">,</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">fontWeight:</span><span class="mtk1"> </span><span class="mtk8">&quot;bold&quot;</span><span class="mtk1">,</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">backgroundColor:</span><span class="mtk1"> </span><span class="mtk8">&quot;#f4f4f4&quot;</span><span class="mtk1">,</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">borderTopLeftRadius:</span><span class="mtk1"> </span><span class="mtk8">&quot;7px&quot;</span><span class="mtk1">,</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">borderTopRightRadius:</span><span class="mtk1"> </span><span class="mtk8">&quot;7px&quot;</span><span class="mtk1">,</span></span></span> <span class="grvsc-line grvsc-line-highlighted"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk8">&quot;&amp;:before&quot;</span><span class="mtk12">:</span><span class="mtk1"> {</span></span></span> <span class="grvsc-line grvsc-line-highlighted"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">borderColor:</span><span class="mtk1"> </span><span class="mtk8">&quot;#2e2e2e&quot;</span><span class="mtk1">,</span></span></span> <span class="grvsc-line grvsc-line-highlighted"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">borderWidth:</span><span class="mtk1"> </span><span class="mtk8">&quot;2px&quot;</span><span class="mtk1">,</span></span></span> <span class="grvsc-line grvsc-line-highlighted"><span class="grvsc-source"><span class="mtk1"> },</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> },</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk8">&quot;&amp; .MuiInputLabel-filled&quot;</span><span class="mtk12">:</span><span class="mtk1"> {</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">color:</span><span class="mtk1"> </span><span class="mtk8">&quot;#2e2e2e&quot;</span><span class="mtk1">,</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">fontWeight:</span><span class="mtk1"> </span><span class="mtk8">&quot;bold&quot;</span><span class="mtk1">,</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> },</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> }</span><span class="mtk4">}</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk17">/&gt;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> );</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1">}</span></span></span></code></pre> <div id="FilledTextFieldStyleBorder" data-code data-height="75px"></div> <h3 id="filled-focused-state" style="position:relative;"><a href="#filled-focused-state" aria-label="filled focused state permalink" class="anchor before"><svg aria-hidden="true" focusable="false" height="16" version="1.1" viewBox="0 0 16 16" width="16"><path fill-rule="evenodd" d="M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z"></path></svg></a>Filled Focused State</h3> <p>For the focused state, we can use the <code>&#x26;.Mui-focused</code> class to target the focused state of the label but the bottom border is also another pseudo-element created using the <code>&#x26;:after</code> class in the root class.</p> <p>In the following example, we’re going to override the default colors and styles for the focused state:</p> <pre class="grvsc-container grvsc-has-line-highlighting default-dark" data-language="jsx" data-index="6"><code class="grvsc-code"><span class="grvsc-line"><span class="grvsc-source"><span class="mtk1">...</span></span></span> <span class="grvsc-line"><span class="grvsc-source"></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk15">export</span><span class="mtk1"> </span><span class="mtk15">default</span><span class="mtk1"> </span><span class="mtk4">function</span><span class="mtk1"> </span><span class="mtk11">FilledTextField</span><span class="mtk1">() {</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk15">return</span><span class="mtk1"> (</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk17">&lt;</span><span class="mtk10">TextField</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">label</span><span class="mtk1">=</span><span class="mtk8">&quot;Filled&quot;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">variant</span><span class="mtk1">=</span><span class="mtk8">&quot;filled&quot;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">color</span><span class="mtk1">=</span><span class="mtk8">&quot;secondary&quot;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">sx</span><span class="mtk1">=</span><span class="mtk4">{</span><span class="mtk1">{</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk8">&quot;&amp; .MuiFilledInput-root&quot;</span><span class="mtk12">:</span><span class="mtk1"> {</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">color:</span><span class="mtk1"> </span><span class="mtk8">&quot;#000&quot;</span><span class="mtk1">,</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">fontFamily:</span><span class="mtk1"> </span><span class="mtk8">&quot;Arial&quot;</span><span class="mtk1">,</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">fontWeight:</span><span class="mtk1"> </span><span class="mtk8">&quot;bold&quot;</span><span class="mtk1">,</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">backgroundColor:</span><span class="mtk1"> </span><span class="mtk8">&quot;#f4f4f4&quot;</span><span class="mtk1">,</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">borderTopLeftRadius:</span><span class="mtk1"> </span><span class="mtk8">&quot;7px&quot;</span><span class="mtk1">,</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">borderTopRightRadius:</span><span class="mtk1"> </span><span class="mtk8">&quot;7px&quot;</span><span class="mtk1">,</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk8">&quot;&amp;:before&quot;</span><span class="mtk12">:</span><span class="mtk1"> {</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">borderColor:</span><span class="mtk1"> </span><span class="mtk8">&quot;#2e2e2e&quot;</span><span class="mtk1">,</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">borderWidth:</span><span class="mtk1"> </span><span class="mtk8">&quot;2px&quot;</span><span class="mtk1">,</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> },</span></span></span> <span class="grvsc-line grvsc-line-highlighted"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk8">&quot;&amp;:after&quot;</span><span class="mtk12">:</span><span class="mtk1"> {</span></span></span> <span class="grvsc-line grvsc-line-highlighted"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">borderColor:</span><span class="mtk1"> </span><span class="mtk8">&quot;secondary.main&quot;</span><span class="mtk1">,</span></span></span> <span class="grvsc-line grvsc-line-highlighted"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">borderWidth:</span><span class="mtk1"> </span><span class="mtk8">&quot;3px&quot;</span><span class="mtk1">,</span></span></span> <span class="grvsc-line grvsc-line-highlighted"><span class="grvsc-source"><span class="mtk1"> },</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> },</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk8">&quot;&amp; .MuiInputLabel-filled&quot;</span><span class="mtk12">:</span><span class="mtk1"> {</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">color:</span><span class="mtk1"> </span><span class="mtk8">&quot;#2e2e2e&quot;</span><span class="mtk1">,</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">fontWeight:</span><span class="mtk1"> </span><span class="mtk8">&quot;bold&quot;</span><span class="mtk1">,</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk8">&quot;&amp;.Mui-focused&quot;</span><span class="mtk12">:</span><span class="mtk1"> {</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">color:</span><span class="mtk1"> </span><span class="mtk8">&quot;secondary.main&quot;</span><span class="mtk1">,</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">fontWeight:</span><span class="mtk1"> </span><span class="mtk8">&quot;bold&quot;</span><span class="mtk1">,</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> },</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> },</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> }</span><span class="mtk4">}</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk17">/&gt;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> );</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1">}</span></span></span></code></pre> <div id="FilledTextFieldStyleFocused" data-code data-height="75px"></div> <h3 id="filled-hover-state" style="position:relative;"><a href="#filled-hover-state" aria-label="filled hover state permalink" class="anchor before"><svg aria-hidden="true" focusable="false" height="16" version="1.1" viewBox="0 0 16 16" width="16"><path fill-rule="evenodd" d="M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z"></path></svg></a>Filled Hover State</h3> <p>Let’s chnage the background color and the bottom border when hovering over the input field using the <code>&#x26;:hover</code> class. Also, we need to make sure the hover state is not applied when the input is focused.</p> <pre class="grvsc-container grvsc-has-line-highlighting default-dark" data-language="jsx" data-index="7"><code class="grvsc-code"><span class="grvsc-line"><span class="grvsc-source"><span class="mtk1">...</span></span></span> <span class="grvsc-line"><span class="grvsc-source"></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk15">export</span><span class="mtk1"> </span><span class="mtk15">default</span><span class="mtk1"> </span><span class="mtk4">function</span><span class="mtk1"> </span><span class="mtk11">FilledTextField</span><span class="mtk1">() {</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk15">return</span><span class="mtk1"> (</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk17">&lt;</span><span class="mtk10">TextField</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">label</span><span class="mtk1">=</span><span class="mtk8">&quot;Outlined&quot;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">variant</span><span class="mtk1">=</span><span class="mtk8">&quot;outlined&quot;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">color</span><span class="mtk1">=</span><span class="mtk8">&quot;secondary&quot;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">sx</span><span class="mtk1">=</span><span class="mtk4">{</span><span class="mtk1">{</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk8">&quot;&amp; .MuiOutlinedInput-root&quot;</span><span class="mtk12">:</span><span class="mtk1"> {</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">color:</span><span class="mtk1"> </span><span class="mtk8">&quot;#000&quot;</span><span class="mtk1">,</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">fontFamily:</span><span class="mtk1"> </span><span class="mtk8">&quot;Arial&quot;</span><span class="mtk1">,</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">fontWeight:</span><span class="mtk1"> </span><span class="mtk8">&quot;bold&quot;</span><span class="mtk1">,</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk8">&quot;&amp; .MuiOutlinedInput-notchedOutline&quot;</span><span class="mtk12">:</span><span class="mtk1"> {</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">borderColor:</span><span class="mtk1"> </span><span class="mtk8">&quot;#2e2e2e&quot;</span><span class="mtk1">,</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">borderWidth:</span><span class="mtk1"> </span><span class="mtk8">&quot;2px&quot;</span><span class="mtk1">,</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> },</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk8">&quot;&amp;.Mui-focused&quot;</span><span class="mtk12">:</span><span class="mtk1"> {</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk8">&quot;&amp; .MuiOutlinedInput-notchedOutline&quot;</span><span class="mtk12">:</span><span class="mtk1"> {</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">borderColor:</span><span class="mtk1"> </span><span class="mtk8">&quot;secondary.main&quot;</span><span class="mtk1">,</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">borderWidth:</span><span class="mtk1"> </span><span class="mtk8">&quot;3px&quot;</span><span class="mtk1">,</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> },</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> },</span></span></span> <span class="grvsc-line grvsc-line-highlighted"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk8">&quot;&amp;:hover:not(.Mui-focused)&quot;</span><span class="mtk12">:</span><span class="mtk1"> {</span></span></span> <span class="grvsc-line grvsc-line-highlighted"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk8">&quot;&amp; .MuiOutlinedInput-notchedOutline&quot;</span><span class="mtk12">:</span><span class="mtk1"> {</span></span></span> <span class="grvsc-line grvsc-line-highlighted"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">borderColor:</span><span class="mtk1"> </span><span class="mtk8">&quot;#ccc&quot;</span><span class="mtk1">,</span></span></span> <span class="grvsc-line grvsc-line-highlighted"><span class="grvsc-source"><span class="mtk1"> },</span></span></span> <span class="grvsc-line grvsc-line-highlighted"><span class="grvsc-source"><span class="mtk1"> },</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> },</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk8">&quot;&amp; .MuiInputLabel-outlined&quot;</span><span class="mtk12">:</span><span class="mtk1"> {</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">color:</span><span class="mtk1"> </span><span class="mtk8">&quot;#2e2e2e&quot;</span><span class="mtk1">,</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">fontWeight:</span><span class="mtk1"> </span><span class="mtk8">&quot;bold&quot;</span><span class="mtk1">,</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk8">&quot;&amp;.Mui-focused&quot;</span><span class="mtk12">:</span><span class="mtk1"> {</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">color:</span><span class="mtk1"> </span><span class="mtk8">&quot;secondary.main&quot;</span><span class="mtk1">,</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">fontWeight:</span><span class="mtk1"> </span><span class="mtk8">&quot;bold&quot;</span><span class="mtk1">,</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> },</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> },</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> }</span><span class="mtk4">}</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk17">/&gt;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> );</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1">}</span></span></span></code></pre> <div id="FilledTextFieldStyleHover" data-code data-height="75px"></div> <h2 id="standard-variant" style="position:relative;"><a href="#standard-variant" aria-label="standard variant permalink" class="anchor before"><svg aria-hidden="true" focusable="false" height="16" version="1.1" viewBox="0 0 16 16" width="16"><path fill-rule="evenodd" d="M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z"></path></svg></a>Standard Variant</h2> <p>The <code>standard</code> variant is the most basic variant of the <code>TextField</code> component. It has a bottom border and a label that floats above the input when the user starts typing. To customize the colors and styles, there are two main classes that we can use:</p> <ul> <li><code>MuiInput-root</code>: The root class for the input field.</li> <li><code>MuiInputLabel-standard</code>: The class for the label.</li> </ul> <h3 id="standard-custom-styles" style="position:relative;"><a href="#standard-custom-styles" aria-label="standard custom styles permalink" class="anchor before"><svg aria-hidden="true" focusable="false" height="16" version="1.1" viewBox="0 0 16 16" width="16"><path fill-rule="evenodd" d="M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z"></path></svg></a>Standard Custom Styles</h3> <p>In the following example, we’re going to override the default colors and styles using the <code>sx</code> prop:</p> <pre class="grvsc-container default-dark" data-language="jsx" data-index="8"><code class="grvsc-code"><span class="grvsc-line"><span class="grvsc-source"><span class="mtk15">import</span><span class="mtk1"> </span><span class="mtk12">React</span><span class="mtk1"> </span><span class="mtk15">from</span><span class="mtk1"> </span><span class="mtk8">&quot;react&quot;</span><span class="mtk1">;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk15">import</span><span class="mtk1"> </span><span class="mtk12">TextField</span><span class="mtk1"> </span><span class="mtk15">from</span><span class="mtk1"> </span><span class="mtk8">&quot;@mui/material/TextField&quot;</span><span class="mtk1">;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk15">export</span><span class="mtk1"> </span><span class="mtk15">default</span><span class="mtk1"> </span><span class="mtk4">function</span><span class="mtk1"> </span><span class="mtk11">StandardTextField</span><span class="mtk1">() {</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk15">return</span><span class="mtk1"> (</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk17">&lt;</span><span class="mtk10">TextField</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">label</span><span class="mtk1">=</span><span class="mtk8">&quot;Standard&quot;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">variant</span><span class="mtk1">=</span><span class="mtk8">&quot;standard&quot;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">sx</span><span class="mtk1">=</span><span class="mtk4">{</span><span class="mtk1">{</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk8">&quot;&amp; .MuiInput-root&quot;</span><span class="mtk12">:</span><span class="mtk1"> {</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">color:</span><span class="mtk1"> </span><span class="mtk8">&quot;#000&quot;</span><span class="mtk1">,</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">fontFamily:</span><span class="mtk1"> </span><span class="mtk8">&quot;Arial&quot;</span><span class="mtk1">,</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">fontWeight:</span><span class="mtk1"> </span><span class="mtk8">&quot;bold&quot;</span><span class="mtk1">,</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk3">// Bottom border</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk8">&quot;&amp;:before&quot;</span><span class="mtk12">:</span><span class="mtk1"> {</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">borderColor:</span><span class="mtk1"> </span><span class="mtk8">&quot;#2e2e2e&quot;</span><span class="mtk1">,</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">borderWidth:</span><span class="mtk1"> </span><span class="mtk8">&quot;2px&quot;</span><span class="mtk1">,</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> },</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> },</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk3">// Label</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk8">&quot;&amp; .MuiInputLabel-standard&quot;</span><span class="mtk12">:</span><span class="mtk1"> {</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">color:</span><span class="mtk1"> </span><span class="mtk8">&quot;#2e2e2e&quot;</span><span class="mtk1">,</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">fontWeight:</span><span class="mtk1"> </span><span class="mtk8">&quot;bold&quot;</span><span class="mtk1">,</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> },</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> }</span><span class="mtk4">}</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk17">/&gt;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> );</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1">}</span></span></span></code></pre> <div id="StandardTextFieldStyle" data-code data-height="75px"></div> <p>For the focused and hover states, we will follow the same steps as the <code>filled</code> variant.</p> <h3 id="standard-focused-state" style="position:relative;"><a href="#standard-focused-state" aria-label="standard focused state permalink" class="anchor before"><svg aria-hidden="true" focusable="false" height="16" version="1.1" viewBox="0 0 16 16" width="16"><path fill-rule="evenodd" d="M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z"></path></svg></a>Standard Focused State</h3> <ul> <li>Use the <code>&#x26;.Mui-focused</code> class to target the focused state of the label</li> <li>Use the <code>:after</code> pseudo-element to target the focused state of the bottom border</li> </ul> <pre class="grvsc-container grvsc-has-line-highlighting default-dark" data-language="jsx" data-index="9"><code class="grvsc-code"><span class="grvsc-line"><span class="grvsc-source"><span class="mtk1">...</span></span></span> <span class="grvsc-line"><span class="grvsc-source"></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk15">export</span><span class="mtk1"> </span><span class="mtk15">default</span><span class="mtk1"> </span><span class="mtk4">function</span><span class="mtk1"> </span><span class="mtk11">StandardTextField</span><span class="mtk1">() {</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk15">return</span><span class="mtk1"> (</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk17">&lt;</span><span class="mtk10">TextField</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">label</span><span class="mtk1">=</span><span class="mtk8">&quot;Standard&quot;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">variant</span><span class="mtk1">=</span><span class="mtk8">&quot;standard&quot;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">color</span><span class="mtk1">=</span><span class="mtk8">&quot;secondary&quot;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">sx</span><span class="mtk1">=</span><span class="mtk4">{</span><span class="mtk1">{</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk8">&quot;&amp; .MuiInput-root&quot;</span><span class="mtk12">:</span><span class="mtk1"> {</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">color:</span><span class="mtk1"> </span><span class="mtk8">&quot;#000&quot;</span><span class="mtk1">,</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">fontFamily:</span><span class="mtk1"> </span><span class="mtk8">&quot;Arial&quot;</span><span class="mtk1">,</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">fontWeight:</span><span class="mtk1"> </span><span class="mtk8">&quot;bold&quot;</span><span class="mtk1">,</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk3">// Bottom border</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk8">&quot;&amp;:before&quot;</span><span class="mtk12">:</span><span class="mtk1"> {</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">borderColor:</span><span class="mtk1"> </span><span class="mtk8">&quot;#2e2e2e&quot;</span><span class="mtk1">,</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">borderWidth:</span><span class="mtk1"> </span><span class="mtk8">&quot;2px&quot;</span><span class="mtk1">,</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> },</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk3">// Border on focus</span></span></span> <span class="grvsc-line grvsc-line-highlighted"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk8">&quot;&amp;:after&quot;</span><span class="mtk12">:</span><span class="mtk1"> {</span></span></span> <span class="grvsc-line grvsc-line-highlighted"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">borderColor:</span><span class="mtk1"> </span><span class="mtk8">&quot;secondary.main&quot;</span><span class="mtk1">,</span></span></span> <span class="grvsc-line grvsc-line-highlighted"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">borderWidth:</span><span class="mtk1"> </span><span class="mtk8">&quot;3px&quot;</span><span class="mtk1">,</span></span></span> <span class="grvsc-line grvsc-line-highlighted"><span class="grvsc-source"><span class="mtk1"> },</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> },</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk3">// Label</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk8">&quot;&amp; .MuiInputLabel-standard&quot;</span><span class="mtk12">:</span><span class="mtk1"> {</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">color:</span><span class="mtk1"> </span><span class="mtk8">&quot;#2e2e2e&quot;</span><span class="mtk1">,</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">fontWeight:</span><span class="mtk1"> </span><span class="mtk8">&quot;bold&quot;</span><span class="mtk1">,</span></span></span> <span class="grvsc-line grvsc-line-highlighted"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk8">&quot;&amp;.Mui-focused&quot;</span><span class="mtk12">:</span><span class="mtk1"> {</span></span></span> <span class="grvsc-line grvsc-line-highlighted"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">color:</span><span class="mtk1"> </span><span class="mtk8">&quot;secondary.main&quot;</span><span class="mtk1">,</span></span></span> <span class="grvsc-line grvsc-line-highlighted"><span class="grvsc-source"><span class="mtk1"> },</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> },</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> }</span><span class="mtk4">}</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk17">/&gt;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> );</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1">}</span></span></span></code></pre> <div id="StandardTextFieldStyleFocused" data-code data-height="75px"></div> <h3 id="standard-hover-state" style="position:relative;"><a href="#standard-hover-state" aria-label="standard hover state permalink" class="anchor before"><svg aria-hidden="true" focusable="false" height="16" version="1.1" viewBox="0 0 16 16" width="16"><path fill-rule="evenodd" d="M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z"></path></svg></a>Standard Hover State</h3> <ul> <li>Use the <code>&#x26;:hover</code> selector to target the hover state of the input field</li> <li>Exclude the hover state when the input is focused using <code>:not(.Mui-focused)</code></li> </ul> <pre class="grvsc-container grvsc-has-line-highlighting default-dark" data-language="jsx" data-index="10"><code class="grvsc-code"><span class="grvsc-line"><span class="grvsc-source"><span class="mtk1">...</span></span></span> <span class="grvsc-line"><span class="grvsc-source"></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk15">export</span><span class="mtk1"> </span><span class="mtk15">default</span><span class="mtk1"> </span><span class="mtk4">function</span><span class="mtk1"> </span><span class="mtk11">StandardTextField</span><span class="mtk1">() {</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk15">return</span><span class="mtk1"> (</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk17">&lt;</span><span class="mtk10">TextField</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">label</span><span class="mtk1">=</span><span class="mtk8">&quot;Standard&quot;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">variant</span><span class="mtk1">=</span><span class="mtk8">&quot;standard&quot;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">color</span><span class="mtk1">=</span><span class="mtk8">&quot;secondary&quot;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">sx</span><span class="mtk1">=</span><span class="mtk4">{</span><span class="mtk1">{</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk8">&quot;&amp; .MuiInput-root&quot;</span><span class="mtk12">:</span><span class="mtk1"> {</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">color:</span><span class="mtk1"> </span><span class="mtk8">&quot;#000&quot;</span><span class="mtk1">,</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">fontFamily:</span><span class="mtk1"> </span><span class="mtk8">&quot;Arial&quot;</span><span class="mtk1">,</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">fontWeight:</span><span class="mtk1"> </span><span class="mtk8">&quot;bold&quot;</span><span class="mtk1">,</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk3">// Bottom border</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk8">&quot;&amp;:before&quot;</span><span class="mtk12">:</span><span class="mtk1"> {</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">borderColor:</span><span class="mtk1"> </span><span class="mtk8">&quot;#2e2e2e&quot;</span><span class="mtk1">,</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">borderWidth:</span><span class="mtk1"> </span><span class="mtk8">&quot;2px&quot;</span><span class="mtk1">,</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> },</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk3">// Border on focus</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk8">&quot;&amp;:after&quot;</span><span class="mtk12">:</span><span class="mtk1"> {</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">borderColor:</span><span class="mtk1"> </span><span class="mtk8">&quot;secondary.main&quot;</span><span class="mtk1">,</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">borderWidth:</span><span class="mtk1"> </span><span class="mtk8">&quot;3px&quot;</span><span class="mtk1">,</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> },</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk8">&quot;:hover:not(.Mui-focused)&quot;</span><span class="mtk12">:</span><span class="mtk1"> {</span></span></span> <span class="grvsc-line grvsc-line-highlighted"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk8">&quot;&amp;:before&quot;</span><span class="mtk12">:</span><span class="mtk1"> {</span></span></span> <span class="grvsc-line grvsc-line-highlighted"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">borderColor:</span><span class="mtk1"> </span><span class="mtk8">&quot;#e7e7e7&quot;</span><span class="mtk1">,</span></span></span> <span class="grvsc-line grvsc-line-highlighted"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">borderWidth:</span><span class="mtk1"> </span><span class="mtk8">&quot;2px&quot;</span><span class="mtk1">,</span></span></span> <span class="grvsc-line grvsc-line-highlighted"><span class="grvsc-source"><span class="mtk1"> },</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> },</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> },</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk3">// Label</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk8">&quot;&amp; .MuiInputLabel-standard&quot;</span><span class="mtk12">:</span><span class="mtk1"> {</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">color:</span><span class="mtk1"> </span><span class="mtk8">&quot;#2e2e2e&quot;</span><span class="mtk1">,</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">fontWeight:</span><span class="mtk1"> </span><span class="mtk8">&quot;bold&quot;</span><span class="mtk1">,</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk8">&quot;&amp;.Mui-focused&quot;</span><span class="mtk12">:</span><span class="mtk1"> {</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">color:</span><span class="mtk1"> </span><span class="mtk8">&quot;secondary.main&quot;</span><span class="mtk1">,</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> },</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> },</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> }</span><span class="mtk4">}</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk17">/&gt;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> );</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1">}</span></span></span></code></pre> <div id="StandardTextFieldStyleHover" data-code data-height="75px"></div> <h2 id="using-the-theme" style="position:relative;"><a href="#using-the-theme" aria-label="using the theme permalink" class="anchor before"><svg aria-hidden="true" focusable="false" height="16" version="1.1" viewBox="0 0 16 16" width="16"><path fill-rule="evenodd" d="M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z"></path></svg></a>Using the Theme</h2> <p>In the examples above, we used the <code>sx</code> prop to override the default colors and styles of the <code>TextField</code> component. Although this is convenient and easy to use, it won’t be the best appraoch as we want to reuse the same styles multiple times across the app. Instead, we can use the <code>theme</code> object to apply the styles globally.</p> <p>To do that, we can use the <code>createTheme</code> function to create a new theme and then use the <code>ThemeProvider</code> to wrap the app and apply the new theme.</p> <p>Let’s add styles of all the variants we did to the new theme:</p> <pre class="grvsc-container default-dark" data-language="jsx" data-index="11"><code class="grvsc-code"><span class="grvsc-line"><span class="grvsc-source"><span class="mtk15">import</span><span class="mtk1"> </span><span class="mtk12">React</span><span class="mtk1"> </span><span class="mtk15">from</span><span class="mtk1"> </span><span class="mtk8">&quot;react&quot;</span><span class="mtk1">;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk15">import</span><span class="mtk1"> </span><span class="mtk12">TextField</span><span class="mtk1"> </span><span class="mtk15">from</span><span class="mtk1"> </span><span class="mtk8">&quot;@mui/material/TextField&quot;</span><span class="mtk1">;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk15">import</span><span class="mtk1"> { </span><span class="mtk12">ThemeProvider</span><span class="mtk1">, </span><span class="mtk12">createTheme</span><span class="mtk1"> } </span><span class="mtk15">from</span><span class="mtk1"> </span><span class="mtk8">&quot;@mui/material&quot;</span><span class="mtk1">;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk4">const</span><span class="mtk1"> </span><span class="mtk12">theme</span><span class="mtk1"> = </span><span class="mtk11">createTheme</span><span class="mtk1">({</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">components:</span><span class="mtk1"> {</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">MuiTextField:</span><span class="mtk1"> {</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">styleOverrides:</span><span class="mtk1"> {</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">root:</span><span class="mtk1"> {</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk3">// Outlined</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk8">&quot;&amp; .MuiOutlinedInput-root&quot;</span><span class="mtk12">:</span><span class="mtk1"> {</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">color:</span><span class="mtk1"> </span><span class="mtk8">&quot;#000&quot;</span><span class="mtk1">,</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">fontFamily:</span><span class="mtk1"> </span><span class="mtk8">&quot;Arial&quot;</span><span class="mtk1">,</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">fontWeight:</span><span class="mtk1"> </span><span class="mtk8">&quot;bold&quot;</span><span class="mtk1">,</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk8">&quot;&amp; .MuiOutlinedInput-notchedOutline&quot;</span><span class="mtk12">:</span><span class="mtk1"> {</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">borderColor:</span><span class="mtk1"> </span><span class="mtk8">&quot;#2e2e2e&quot;</span><span class="mtk1">,</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">borderWidth:</span><span class="mtk1"> </span><span class="mtk8">&quot;2px&quot;</span><span class="mtk1">,</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> },</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk8">&quot;&amp;.Mui-focused&quot;</span><span class="mtk12">:</span><span class="mtk1"> {</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk8">&quot;&amp; .MuiOutlinedInput-notchedOutline&quot;</span><span class="mtk12">:</span><span class="mtk1"> {</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">borderColor:</span><span class="mtk1"> </span><span class="mtk8">&quot;secondary.main&quot;</span><span class="mtk1">,</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">borderWidth:</span><span class="mtk1"> </span><span class="mtk8">&quot;3px&quot;</span><span class="mtk1">,</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> },</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> },</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk8">&quot;&amp;:hover:not(.Mui-focused)&quot;</span><span class="mtk12">:</span><span class="mtk1"> {</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk8">&quot;&amp; .MuiOutlinedInput-notchedOutline&quot;</span><span class="mtk12">:</span><span class="mtk1"> {</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">borderColor:</span><span class="mtk1"> </span><span class="mtk8">&quot;#ccc&quot;</span><span class="mtk1">,</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> },</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> },</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> },</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk8">&quot;&amp; .MuiInputLabel-outlined&quot;</span><span class="mtk12">:</span><span class="mtk1"> {</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">color:</span><span class="mtk1"> </span><span class="mtk8">&quot;#2e2e2e&quot;</span><span class="mtk1">,</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">fontWeight:</span><span class="mtk1"> </span><span class="mtk8">&quot;bold&quot;</span><span class="mtk1">,</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk8">&quot;&amp;.Mui-focused&quot;</span><span class="mtk12">:</span><span class="mtk1"> {</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">color:</span><span class="mtk1"> </span><span class="mtk8">&quot;secondary.main&quot;</span><span class="mtk1">,</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> },</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> },</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk3">// Filled</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk8">&quot;&amp; .MuiFilledInput-root&quot;</span><span class="mtk12">:</span><span class="mtk1"> {</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">color:</span><span class="mtk1"> </span><span class="mtk8">&quot;#000&quot;</span><span class="mtk1">,</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">fontFamily:</span><span class="mtk1"> </span><span class="mtk8">&quot;Arial&quot;</span><span class="mtk1">,</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">fontWeight:</span><span class="mtk1"> </span><span class="mtk8">&quot;bold&quot;</span><span class="mtk1">,</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">backgroundColor:</span><span class="mtk1"> </span><span class="mtk8">&quot;#e7e7e7&quot;</span><span class="mtk1">,</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">borderTopLeftRadius:</span><span class="mtk1"> </span><span class="mtk8">&quot;7px&quot;</span><span class="mtk1">,</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">borderTopRightRadius:</span><span class="mtk1"> </span><span class="mtk8">&quot;7px&quot;</span><span class="mtk1">,</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk8">&quot;&amp;:before&quot;</span><span class="mtk12">:</span><span class="mtk1"> {</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">borderColor:</span><span class="mtk1"> </span><span class="mtk8">&quot;#2e2e2e&quot;</span><span class="mtk1">,</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">borderWidth:</span><span class="mtk1"> </span><span class="mtk8">&quot;2px&quot;</span><span class="mtk1">,</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> },</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk8">&quot;&amp;:after&quot;</span><span class="mtk12">:</span><span class="mtk1"> {</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">borderColor:</span><span class="mtk1"> </span><span class="mtk8">&quot;secondary.main&quot;</span><span class="mtk1">,</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">borderWidth:</span><span class="mtk1"> </span><span class="mtk8">&quot;3px&quot;</span><span class="mtk1">,</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> },</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk8">&quot;:hover:not(.Mui-focused)&quot;</span><span class="mtk12">:</span><span class="mtk1"> {</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk8">&quot;&amp;:before&quot;</span><span class="mtk12">:</span><span class="mtk1"> {</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">borderColor:</span><span class="mtk1"> </span><span class="mtk8">&quot;#e7e7e7&quot;</span><span class="mtk1">,</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">borderWidth:</span><span class="mtk1"> </span><span class="mtk8">&quot;2px&quot;</span><span class="mtk1">,</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> },</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">backgroundColor:</span><span class="mtk1"> </span><span class="mtk8">&quot;#f4f4f4&quot;</span><span class="mtk1">,</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> },</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> },</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk8">&quot;&amp; .MuiInputLabel-filled&quot;</span><span class="mtk12">:</span><span class="mtk1"> {</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">color:</span><span class="mtk1"> </span><span class="mtk8">&quot;#2e2e2e&quot;</span><span class="mtk1">,</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">fontWeight:</span><span class="mtk1"> </span><span class="mtk8">&quot;bold&quot;</span><span class="mtk1">,</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk8">&quot;&amp;.Mui-focused&quot;</span><span class="mtk12">:</span><span class="mtk1"> {</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">color:</span><span class="mtk1"> </span><span class="mtk8">&quot;secondary.main&quot;</span><span class="mtk1">,</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> },</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> },</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk3">// Standard</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk8">&quot;&amp; .MuiInput-root&quot;</span><span class="mtk12">:</span><span class="mtk1"> {</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">color:</span><span class="mtk1"> </span><span class="mtk8">&quot;#000&quot;</span><span class="mtk1">,</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">fontFamily:</span><span class="mtk1"> </span><span class="mtk8">&quot;Arial&quot;</span><span class="mtk1">,</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">fontWeight:</span><span class="mtk1"> </span><span class="mtk8">&quot;bold&quot;</span><span class="mtk1">,</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk8">&quot;&amp;:before&quot;</span><span class="mtk12">:</span><span class="mtk1"> {</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">borderColor:</span><span class="mtk1"> </span><span class="mtk8">&quot;#2e2e2e&quot;</span><span class="mtk1">,</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">borderWidth:</span><span class="mtk1"> </span><span class="mtk8">&quot;2px&quot;</span><span class="mtk1">,</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> },</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk8">&quot;&amp;:after&quot;</span><span class="mtk12">:</span><span class="mtk1"> {</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">borderColor:</span><span class="mtk1"> </span><span class="mtk8">&quot;secondary.main&quot;</span><span class="mtk1">,</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">borderWidth:</span><span class="mtk1"> </span><span class="mtk8">&quot;3px&quot;</span><span class="mtk1">,</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> },</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk8">&quot;:hover:not(.Mui-focused)&quot;</span><span class="mtk12">:</span><span class="mtk1"> {</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk8">&quot;&amp;:before&quot;</span><span class="mtk12">:</span><span class="mtk1"> {</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">borderColor:</span><span class="mtk1"> </span><span class="mtk8">&quot;#e7e7e7&quot;</span><span class="mtk1">,</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">borderWidth:</span><span class="mtk1"> </span><span class="mtk8">&quot;2px&quot;</span><span class="mtk1">,</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> },</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> },</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> },</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> },</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> },</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> },</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> },</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1">});</span></span></span> <span class="grvsc-line"><span class="grvsc-source"></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk15">export</span><span class="mtk1"> </span><span class="mtk15">default</span><span class="mtk1"> </span><span class="mtk4">function</span><span class="mtk1"> </span><span class="mtk11">CustomThemeTextField</span><span class="mtk1">() {</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk15">return</span><span class="mtk1"> (</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk17">&lt;</span><span class="mtk10">ThemeProvider</span><span class="mtk1"> </span><span class="mtk12">theme</span><span class="mtk1">=</span><span class="mtk4">{</span><span class="mtk12">theme</span><span class="mtk4">}</span><span class="mtk17">&gt;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk17">&lt;</span><span class="mtk10">TextField</span><span class="mtk1"> </span><span class="mtk12">label</span><span class="mtk1">=</span><span class="mtk8">&quot;Outlined&quot;</span><span class="mtk1"> </span><span class="mtk12">variant</span><span class="mtk1">=</span><span class="mtk8">&quot;outlined&quot;</span><span class="mtk1"> </span><span class="mtk12">color</span><span class="mtk1">=</span><span class="mtk8">&quot;secondary&quot;</span><span class="mtk1"> </span><span class="mtk17">/&gt;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk17">&lt;</span><span class="mtk10">TextField</span><span class="mtk1"> </span><span class="mtk12">label</span><span class="mtk1">=</span><span class="mtk8">&quot;Filled&quot;</span><span class="mtk1"> </span><span class="mtk12">variant</span><span class="mtk1">=</span><span class="mtk8">&quot;filled&quot;</span><span class="mtk1"> </span><span class="mtk12">color</span><span class="mtk1">=</span><span class="mtk8">&quot;secondary&quot;</span><span class="mtk1"> </span><span class="mtk17">/&gt;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk17">&lt;</span><span class="mtk10">TextField</span><span class="mtk1"> </span><span class="mtk12">label</span><span class="mtk1">=</span><span class="mtk8">&quot;Standard&quot;</span><span class="mtk1"> </span><span class="mtk12">variant</span><span class="mtk1">=</span><span class="mtk8">&quot;standard&quot;</span><span class="mtk1"> </span><span class="mtk12">color</span><span class="mtk1">=</span><span class="mtk8">&quot;secondary&quot;</span><span class="mtk1"> </span><span class="mtk17">/&gt;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk17">&lt;/</span><span class="mtk10">ThemeProvider</span><span class="mtk17">&gt;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> );</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1">}</span></span></span></code></pre> <div id="CustomThemeTextFieldStyle" data-code data-height="225px"></div> <p>Now, when consuming the <code>TextField</code> component anywhere in the application, the custom styles will be applied.</p> <h2 id="conclusion" style="position:relative;"><a href="#conclusion" aria-label="conclusion permalink" class="anchor before"><svg aria-hidden="true" focusable="false" height="16" version="1.1" viewBox="0 0 16 16" width="16"><path fill-rule="evenodd" d="M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z"></path></svg></a>Conclusion</h2> <p>In this tutorial, we learned how to customize the colors and styles of the <code>TextField</code> component in Material UI (MUI) and React. We went through the different variants and saw how to change the border, label, and text colors for each one. We also learned how to apply the styles globally using the <code>theme</code> object.</p> <p>Bye for now 👋</p> <h2 id="complete-code" style="position:relative;"><a href="#complete-code" aria-label="complete code permalink" class="anchor before"><svg aria-hidden="true" focusable="false" height="16" version="1.1" viewBox="0 0 16 16" width="16"><path fill-rule="evenodd" d="M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z"></path></svg></a>Complete Code</h2> <div data-stackblitz="mui-textfield-colors-styles"> <button>Run Code</button> </div> <style class="grvsc-styles"> .grvsc-container { overflow: auto; position: relative; -webkit-overflow-scrolling: touch; padding-top: 1rem; padding-top: var(--grvsc-padding-top, var(--grvsc-padding-v, 1rem)); padding-bottom: 1rem; padding-bottom: var(--grvsc-padding-bottom, var(--grvsc-padding-v, 1rem)); border-radius: 8px; border-radius: var(--grvsc-border-radius, 8px); font-feature-settings: normal; line-height: 1.4; } .grvsc-code { display: table; } .grvsc-line { display: table-row; box-sizing: border-box; width: 100%; position: relative; } .grvsc-line > * { position: relative; } .grvsc-gutter-pad { display: table-cell; padding-left: 0.75rem; padding-left: calc(var(--grvsc-padding-left, var(--grvsc-padding-h, 1.5rem)) / 2); } .grvsc-gutter { display: table-cell; -webkit-user-select: none; -moz-user-select: none; user-select: none; } .grvsc-gutter::before { content: attr(data-content); } .grvsc-source { display: table-cell; padding-left: 1.5rem; padding-left: var(--grvsc-padding-left, var(--grvsc-padding-h, 1.5rem)); padding-right: 1.5rem; padding-right: var(--grvsc-padding-right, var(--grvsc-padding-h, 1.5rem)); } .grvsc-source:empty::after { content: ' '; -webkit-user-select: none; -moz-user-select: none; user-select: none; } .grvsc-gutter + .grvsc-source { padding-left: 0.75rem; padding-left: calc(var(--grvsc-padding-left, var(--grvsc-padding-h, 1.5rem)) / 2); } /* Line transformer styles */ .grvsc-has-line-highlighting > .grvsc-code > .grvsc-line::before { content: ' '; position: absolute; width: 100%; } .grvsc-line-diff-add::before { background-color: var(--grvsc-line-diff-add-background-color, rgba(0, 255, 60, 0.2)); } .grvsc-line-diff-del::before { background-color: var(--grvsc-line-diff-del-background-color, rgba(255, 0, 20, 0.2)); } .grvsc-line-number { padding: 0 2px; text-align: right; opacity: 0.7; } .default-dark { background-color: #1E1E1E; color: #D4D4D4; } .default-dark .mtk15 { color: #C586C0; } .default-dark .mtk1 { color: #D4D4D4; } .default-dark .mtk12 { color: #9CDCFE; } .default-dark .mtk8 { color: #CE9178; } .default-dark .mtk4 { color: #569CD6; } .default-dark .mtk11 { color: #DCDCAA; } .default-dark .mtk17 { color: #808080; } .default-dark .mtk10 { color: #4EC9B0; } .default-dark .mtk3 { color: #6A9955; } .default-dark .grvsc-line-highlighted::before { background-color: var(--grvsc-line-highlighted-background-color, rgba(255, 255, 255, 0.1)); box-shadow: inset var(--grvsc-line-highlighted-border-width, 4px) 0 0 0 var(--grvsc-line-highlighted-border-color, rgba(255, 255, 255, 0.5)); } </style><![CDATA[How to Create and Style a Readonly TextField in Material UI (MUI) React]]>https://muhimasri.commui-textfield-readonlyhttps://muhimasri.commui-textfield-readonly<p>Readonly is a native HTML attribute that can be used with the input element. Its primary purpose is to prevent the user from editing the input value while still incorporating it as part of the form submission. It’s important to understand that the <code>readonly</code> behavior differs from <code>disabled</code> as we can still interact with elements like focus into and tab in and out. Meanwhile, the <code>disabled</code> input is non-interactable and can’t be submitted with the form.</p> <p>In this tutorial, we will learn how to create a Readonly TextField in Material UI (MUI) and React with customization and styling on different variants.</p> <h2 id="create-a-readonly-textfield" style="position:relative;"><a href="#create-a-readonly-textfield" aria-label="create a readonly textfield permalink" class="anchor before"><svg aria-hidden="true" focusable="false" height="16" version="1.1" viewBox="0 0 16 16" width="16"><path fill-rule="evenodd" d="M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z"></path></svg></a>Create a Readonly TextField</h2> <p>MUI has no direct prop to create a Readonly TextField. However, we can use the <code>inputProps</code> and set the <code>readOnly</code> property to <code>true</code>. The reason behind it is that the <code>TexField</code> component is a wrapper containing the <code>input</code> element along with other elements, so the <code>inputProps</code> is used to pass down the attributes to the underlying input element.</p> <pre class="grvsc-container grvsc-has-line-highlighting default-dark" data-language="jsx" data-index="0"><code class="grvsc-code"><span class="grvsc-line"><span class="grvsc-source"><span class="mtk15">import</span><span class="mtk1"> </span><span class="mtk12">React</span><span class="mtk1"> </span><span class="mtk15">from</span><span class="mtk1"> </span><span class="mtk8">&quot;react&quot;</span><span class="mtk1">;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk15">import</span><span class="mtk1"> </span><span class="mtk12">TextField</span><span class="mtk1"> </span><span class="mtk15">from</span><span class="mtk1"> </span><span class="mtk8">&quot;@mui/material/TextField&quot;</span><span class="mtk1">;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk15">export</span><span class="mtk1"> </span><span class="mtk15">default</span><span class="mtk1"> </span><span class="mtk4">function</span><span class="mtk1"> </span><span class="mtk11">App</span><span class="mtk1">() {</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk15">return</span><span class="mtk1"> (</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk17">&lt;</span><span class="mtk10">TextField</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">label</span><span class="mtk1">=</span><span class="mtk8">&quot;Readonly&quot;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">variant</span><span class="mtk1">=</span><span class="mtk8">&quot;outlined&quot;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">defaultValue</span><span class="mtk1">=</span><span class="mtk8">&quot;You Can&#39;t Edit Me&quot;</span></span></span> <span class="grvsc-line grvsc-line-highlighted"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">inputProps</span><span class="mtk1">=</span><span class="mtk4">{</span><span class="mtk1">{ </span><span class="mtk12">readOnly:</span><span class="mtk1"> </span><span class="mtk4">true</span><span class="mtk1"> }</span><span class="mtk4">}</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk17">/&gt;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> );</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1">}</span></span></span></code></pre> <div id="ReadonlyTextField" data-code data-height="75px"></div> <p>In the example above, we can select the text and focus on the input field, but we can’t edit the value. Below is a screenshot of the <code>TextField</code> component in the browser dev tool.</p> <p><span class="gatsby-resp-image-wrapper" style="position: relative; display: block; margin-left: auto; margin-right: auto; max-width: 720px; " > <a class="gatsby-resp-image-link" href="/static/772529a286b0484ff36ae2b5925121bc/3955b/dev-tool.png" style="display: block" target="_blank" rel="noopener" > <span class="gatsby-resp-image-background-image" style="padding-bottom: 37.222222222222214%; position: relative; bottom: 0; left: 0; background-image: url('data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABQAAAAHCAYAAAAIy204AAAACXBIWXMAABnWAAAZ1gEY0crtAAABWElEQVR42kVSW3KkMBDjLDMZZsAY/H5hIFNJ5TN/OcfeYK+uFd5U8qFqN6bVkqDr+x5GW3if4a2DCQlaayxiwPwNNQlihBx/+4W9+sY8PqDa8xHd5XKBFCNqCMjOIVmD1SpUp1HsgmRm1LPnuZgFuzfIrOf9RqzEOVejQ9QK3fXlhdsEYiPTCGpGJGlkPV8u0WNLASV4WKWaEiNFw+lCCtbFEBrzNKG73W7NonEJKWYUz03OYg+2Ea6eZ24v9R1h/aAaS3UGlUqj0XCE9aHZ1ZKWBVmlnLDVimNd8bYfOOqG15Kasr2URu4//yB+/cW2P/Fsd0Td8ayZcwVHDnCn5WFg0DPtbW+o64E9p/+EdUWikpxXBCrIWiCrgaoWDjJb5nrCMRp/xmQUDGt3vV4xDCO/cmRGGprkelHw3GZmgUkukMpB2QwxLXjcezz4Zwz3e8O9v/30590/a2venowrVUEAAAAASUVORK5CYII='); background-size: cover; display: block;" ></span> <img class="gatsby-resp-image-image" alt="Dev Tools" title="" src="/static/772529a286b0484ff36ae2b5925121bc/37523/dev-tool.png" srcset="/static/772529a286b0484ff36ae2b5925121bc/e9ff0/dev-tool.png 180w, /static/772529a286b0484ff36ae2b5925121bc/f21e7/dev-tool.png 360w, /static/772529a286b0484ff36ae2b5925121bc/37523/dev-tool.png 720w, /static/772529a286b0484ff36ae2b5925121bc/302a4/dev-tool.png 1080w, /static/772529a286b0484ff36ae2b5925121bc/07a9c/dev-tool.png 1440w, /static/772529a286b0484ff36ae2b5925121bc/3955b/dev-tool.png 1865w" sizes="(max-width: 720px) 100vw, 720px" style="width:100%;height:100%;margin:0;vertical-align:middle;position:absolute;top:0;left:0;" loading="lazy" decoding="async" /> </a> </span></p> <p>We can see that the <code>readonly</code> attribute is added to the input element, which is nested inside the root div element.</p> <p>Alternatively, we can create our own custom <code>TextField</code> component that extends MUI TextField and pass in a new prop called <code>readOnly</code>, which will be used to set the <code>inputProps</code> value. This approach is particularly useful when reusing it in multiple places.</p> <pre class="grvsc-container default-dark" data-language="jsx" data-index="1"><code class="grvsc-code"><span class="grvsc-line"><span class="grvsc-source"><span class="mtk15">import</span><span class="mtk1"> </span><span class="mtk12">React</span><span class="mtk1"> </span><span class="mtk15">from</span><span class="mtk1"> </span><span class="mtk8">&quot;react&quot;</span><span class="mtk1">;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk15">import</span><span class="mtk1"> </span><span class="mtk12">MuiTextField</span><span class="mtk1"> </span><span class="mtk15">from</span><span class="mtk1"> </span><span class="mtk8">&quot;@mui/material/TextField&quot;</span><span class="mtk1">;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk3">// Add to a separate file TextField.js</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk4">function</span><span class="mtk1"> </span><span class="mtk11">TextField</span><span class="mtk1">({ </span><span class="mtk12">readOnly</span><span class="mtk1">, ...</span><span class="mtk12">props</span><span class="mtk1"> }) {</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk15">return</span><span class="mtk1"> </span><span class="mtk17">&lt;</span><span class="mtk10">MuiTextField</span><span class="mtk1"> </span><span class="mtk4">{</span><span class="mtk1">...</span><span class="mtk12">props</span><span class="mtk4">}</span><span class="mtk1"> </span><span class="mtk12">inputProps</span><span class="mtk1">=</span><span class="mtk4">{</span><span class="mtk1">{ </span><span class="mtk12">readOnly</span><span class="mtk1"> }</span><span class="mtk4">}</span><span class="mtk1"> </span><span class="mtk17">/&gt;</span><span class="mtk1">;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1">}</span></span></span> <span class="grvsc-line"><span class="grvsc-source"></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk15">export</span><span class="mtk1"> </span><span class="mtk15">default</span><span class="mtk1"> </span><span class="mtk4">function</span><span class="mtk1"> </span><span class="mtk11">App</span><span class="mtk1">() {</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk15">return</span><span class="mtk1"> (</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk17">&lt;</span><span class="mtk10">TextField</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">label</span><span class="mtk1">=</span><span class="mtk8">&quot;Readonly&quot;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">variant</span><span class="mtk1">=</span><span class="mtk8">&quot;outlined&quot;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">defaultValue</span><span class="mtk1">=</span><span class="mtk8">&quot;You Can&#39;t Edit Me&quot;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">readOnly</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk17">/&gt;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> );</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1">}</span></span></span></code></pre> <div id="ReadonlyTextFieldCustom" data-code data-height="75px"></div> <p>We renamed the MUI TextField component to <code>MuiTextField</code> to avoid naming conflict with our custom component. Now we have a custom <code>TextField</code> component that can quickly turn on a <code>readonly</code> mode. Of course, extending components can also help create other features such as validation, formatting, etc.</p> <h2 id="style-a-readonly-textfield" style="position:relative;"><a href="#style-a-readonly-textfield" aria-label="style a readonly textfield permalink" class="anchor before"><svg aria-hidden="true" focusable="false" height="16" version="1.1" viewBox="0 0 16 16" width="16"><path fill-rule="evenodd" d="M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z"></path></svg></a>Style a Readonly TextField</h2> <p>Styling a Readonly TextField in MUI can be tricky. Since the component is a wrapper with different elements, changing styles will persist whether a <code>readonly</code> attribute is present or not. To get around this, we can use the CSS <code>:has</code> selector on the root element to check if it has the <code>readonly</code> prop.</p> <p>In the example below, we can change the border and label color of the TextField to <code>#cecece</code> only when triggering <code>readonly</code>.</p> <pre class="grvsc-container grvsc-has-line-highlighting default-dark" data-language="jsx" data-index="2"><code class="grvsc-code"><span class="grvsc-line"><span class="grvsc-source"><span class="mtk15">import</span><span class="mtk1"> </span><span class="mtk12">React</span><span class="mtk1"> </span><span class="mtk15">from</span><span class="mtk1"> </span><span class="mtk8">&quot;react&quot;</span><span class="mtk1">;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk15">import</span><span class="mtk1"> { </span><span class="mtk12">TextField</span><span class="mtk1"> </span><span class="mtk15">as</span><span class="mtk1"> </span><span class="mtk12">MuiTextField</span><span class="mtk1"> } </span><span class="mtk15">from</span><span class="mtk1"> </span><span class="mtk8">&quot;@mui/material&quot;</span><span class="mtk1">;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk4">function</span><span class="mtk1"> </span><span class="mtk11">TextField</span><span class="mtk1">({ </span><span class="mtk12">readOnly</span><span class="mtk1">, ...</span><span class="mtk12">props</span><span class="mtk1"> }) {</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk15">return</span><span class="mtk1"> (</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk17">&lt;</span><span class="mtk10">MuiTextField</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">inputProps</span><span class="mtk1">=</span><span class="mtk4">{</span><span class="mtk1">{ </span><span class="mtk12">readOnly</span><span class="mtk1"> }</span><span class="mtk4">}</span></span></span> <span class="grvsc-line grvsc-line-highlighted"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">sx</span><span class="mtk1">=</span><span class="mtk4">{</span><span class="mtk1">{</span></span></span> <span class="grvsc-line grvsc-line-highlighted"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk3">// change label and border color when readonly</span></span></span> <span class="grvsc-line grvsc-line-highlighted"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk8">&quot;&amp;:has([readonly]) &quot;</span><span class="mtk12">:</span><span class="mtk1"> {</span></span></span> <span class="grvsc-line grvsc-line-highlighted"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk8">&quot;&amp; .MuiInputLabel-outlined&quot;</span><span class="mtk12">:</span><span class="mtk1"> {</span></span></span> <span class="grvsc-line grvsc-line-highlighted"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">color:</span><span class="mtk1"> </span><span class="mtk8">&quot;#cecece&quot;</span><span class="mtk1">,</span></span></span> <span class="grvsc-line grvsc-line-highlighted"><span class="grvsc-source"><span class="mtk1"> },</span></span></span> <span class="grvsc-line grvsc-line-highlighted"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk8">&quot;&amp; .MuiOutlinedInput-notchedOutline&quot;</span><span class="mtk12">:</span><span class="mtk1"> {</span></span></span> <span class="grvsc-line grvsc-line-highlighted"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">borderColor:</span><span class="mtk1"> </span><span class="mtk8">&quot;#cecece&quot;</span><span class="mtk1">,</span></span></span> <span class="grvsc-line grvsc-line-highlighted"><span class="grvsc-source"><span class="mtk1"> },</span></span></span> <span class="grvsc-line grvsc-line-highlighted"><span class="grvsc-source"><span class="mtk1"> },</span></span></span> <span class="grvsc-line grvsc-line-highlighted"><span class="grvsc-source"><span class="mtk1"> }</span><span class="mtk4">}</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk4">{</span><span class="mtk1">...</span><span class="mtk12">props</span><span class="mtk4">}</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk17">/&gt;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> );</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1">}</span></span></span> <span class="grvsc-line"><span class="grvsc-source"></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk15">export</span><span class="mtk1"> </span><span class="mtk15">default</span><span class="mtk1"> </span><span class="mtk4">function</span><span class="mtk1"> </span><span class="mtk11">App</span><span class="mtk1">() {</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk15">return</span><span class="mtk1"> (</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk17">&lt;</span><span class="mtk10">TextField</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">label</span><span class="mtk1">=</span><span class="mtk8">&quot;Readonly&quot;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">variant</span><span class="mtk1">=</span><span class="mtk8">&quot;outlined&quot;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">defaultValue</span><span class="mtk1">=</span><span class="mtk8">&quot;You Can&#39;t Edit Me&quot;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">readOnly</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk17">/&gt;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> );</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1">}</span></span></span></code></pre> <div id="StyledReadonlyTextField" data-code data-height="75px"></div> <p><em>Note: thre is an active <a href="https://github.com/mui/material-ui/pull/32822">issue</a> to add a <code>Mui-readOnly</code> class to the root element. When resolved, we won’t require the <code>:has</code> selector anymore since we can directly target the class.</em></p> <p>Another approach is to change the styles dynamically based on the <code>readOnly</code> prop value. Each class object can be a function that returns the styles based on the condition.</p> <pre class="grvsc-container grvsc-has-line-highlighting default-dark" data-language="jsx" data-index="3"><code class="grvsc-code"><span class="grvsc-line"><span class="grvsc-source"><span class="mtk15">import</span><span class="mtk1"> </span><span class="mtk12">React</span><span class="mtk1"> </span><span class="mtk15">from</span><span class="mtk1"> </span><span class="mtk8">&#39;react&#39;</span><span class="mtk1">;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk15">import</span><span class="mtk1"> </span><span class="mtk12">MuiTextField</span><span class="mtk1"> </span><span class="mtk15">from</span><span class="mtk1"> </span><span class="mtk8">&#39;@mui/material/TextField&#39;</span><span class="mtk1">;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk4">function</span><span class="mtk1"> </span><span class="mtk11">TextField</span><span class="mtk1">({ </span><span class="mtk12">readOnly</span><span class="mtk1">, ...</span><span class="mtk12">props</span><span class="mtk1"> }) {</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk15">return</span><span class="mtk1"> (</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk17">&lt;</span><span class="mtk10">MuiTextField</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">inputProps</span><span class="mtk1">=</span><span class="mtk4">{</span><span class="mtk1">{ </span><span class="mtk12">readOnly</span><span class="mtk1"> }</span><span class="mtk4">}</span></span></span> <span class="grvsc-line grvsc-line-highlighted"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">sx</span><span class="mtk1">=</span><span class="mtk4">{</span><span class="mtk1">{</span></span></span> <span class="grvsc-line grvsc-line-highlighted"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk8">&#39;&amp; .MuiInputLabel-outlined&#39;</span><span class="mtk12">:</span><span class="mtk1"> () </span><span class="mtk4">=&gt;</span></span></span> <span class="grvsc-line grvsc-line-highlighted"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">readOnly</span></span></span> <span class="grvsc-line grvsc-line-highlighted"><span class="grvsc-source"><span class="mtk1"> ? {</span></span></span> <span class="grvsc-line grvsc-line-highlighted"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">color:</span><span class="mtk1"> </span><span class="mtk8">&#39;#cecece&#39;</span><span class="mtk1">,</span></span></span> <span class="grvsc-line grvsc-line-highlighted"><span class="grvsc-source"><span class="mtk1"> }</span></span></span> <span class="grvsc-line grvsc-line-highlighted"><span class="grvsc-source"><span class="mtk1"> : </span><span class="mtk4">null</span><span class="mtk1">,</span></span></span> <span class="grvsc-line grvsc-line-highlighted"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk8">&#39;&amp; .MuiOutlinedInput-notchedOutline&#39;</span><span class="mtk12">:</span><span class="mtk1"> () </span><span class="mtk4">=&gt;</span></span></span> <span class="grvsc-line grvsc-line-highlighted"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">readOnly</span></span></span> <span class="grvsc-line grvsc-line-highlighted"><span class="grvsc-source"><span class="mtk1"> ? {</span></span></span> <span class="grvsc-line grvsc-line-highlighted"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">borderColor:</span><span class="mtk1"> </span><span class="mtk8">&#39;#cecece&#39;</span><span class="mtk1">,</span></span></span> <span class="grvsc-line grvsc-line-highlighted"><span class="grvsc-source"><span class="mtk1"> }</span></span></span> <span class="grvsc-line grvsc-line-highlighted"><span class="grvsc-source"><span class="mtk1"> : </span><span class="mtk4">null</span><span class="mtk1">,</span></span></span> <span class="grvsc-line grvsc-line-highlighted"><span class="grvsc-source"><span class="mtk1"> }</span><span class="mtk4">}</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk4">{</span><span class="mtk1">...</span><span class="mtk12">props</span><span class="mtk4">}</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk17">/&gt;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> );</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1">}</span></span></span> <span class="grvsc-line"><span class="grvsc-source"></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk15">export</span><span class="mtk1"> </span><span class="mtk15">default</span><span class="mtk1"> </span><span class="mtk4">function</span><span class="mtk1"> </span><span class="mtk11">App</span><span class="mtk1">() {</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk15">return</span><span class="mtk1"> (</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk17">&lt;</span><span class="mtk10">TextField</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">label</span><span class="mtk1">=</span><span class="mtk8">&quot;Readonly&quot;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">variant</span><span class="mtk1">=</span><span class="mtk8">&quot;outlined&quot;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">defaultValue</span><span class="mtk1">=</span><span class="mtk8">&quot;You Can&#39;t Edit Me&quot;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">readOnly</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk17">/&gt;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> );</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1">}</span></span></span></code></pre> <div id="StyledReadonlyTextFieldDynamic" data-code data-height="75px"></div> <p>We are returning <code>null</code> because if <code>readOnly</code> is <code>false</code>, then we’re keeping the default style. Of course, we can change the default however we like.</p> <h2 id="styling-different-variants" style="position:relative;"><a href="#styling-different-variants" aria-label="styling different variants permalink" class="anchor before"><svg aria-hidden="true" focusable="false" height="16" version="1.1" viewBox="0 0 16 16" width="16"><path fill-rule="evenodd" d="M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z"></path></svg></a>Styling Different Variants</h2> <p>The TextField component has different variants such as <code>standard</code>, <code>outlined</code>, and <code>filled</code>. Previously, we only styled the <code>outlined</code> variant. To style the other variants, we must change the selector’s class name.</p> <p>For example, we can use the following class selector to style the border and label colors of the <code>filled</code> variant.</p> <pre class="grvsc-container grvsc-has-line-highlighting default-dark" data-language="jsx" data-index="4"><code class="grvsc-code"><span class="grvsc-line"><span class="grvsc-source"><span class="mtk15">import</span><span class="mtk1"> </span><span class="mtk12">React</span><span class="mtk1"> </span><span class="mtk15">from</span><span class="mtk1"> </span><span class="mtk8">&quot;react&quot;</span><span class="mtk1">;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk15">import</span><span class="mtk1"> </span><span class="mtk12">MuiTextField</span><span class="mtk1"> </span><span class="mtk15">from</span><span class="mtk1"> </span><span class="mtk8">&quot;@mui/material/TextField&quot;</span><span class="mtk1">;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk4">function</span><span class="mtk1"> </span><span class="mtk11">TextField</span><span class="mtk1">({ </span><span class="mtk12">readOnly</span><span class="mtk1">, ...</span><span class="mtk12">props</span><span class="mtk1"> }) {</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk15">return</span><span class="mtk1"> (</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk17">&lt;</span><span class="mtk10">MuiTextField</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">inputProps</span><span class="mtk1">=</span><span class="mtk4">{</span><span class="mtk1">{ </span><span class="mtk12">readOnly</span><span class="mtk1"> }</span><span class="mtk4">}</span></span></span> <span class="grvsc-line grvsc-line-highlighted"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">sx</span><span class="mtk1">=</span><span class="mtk4">{</span><span class="mtk1">{</span></span></span> <span class="grvsc-line grvsc-line-highlighted"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk8">&quot;&amp;:has([readonly]) &quot;</span><span class="mtk12">:</span><span class="mtk1"> {</span></span></span> <span class="grvsc-line grvsc-line-highlighted"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk8">&quot;&amp; .MuiInputLabel-filled&quot;</span><span class="mtk12">:</span><span class="mtk1"> {</span></span></span> <span class="grvsc-line grvsc-line-highlighted"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">color:</span><span class="mtk1"> </span><span class="mtk8">&quot;#cecece&quot;</span><span class="mtk1">,</span></span></span> <span class="grvsc-line grvsc-line-highlighted"><span class="grvsc-source"><span class="mtk1"> },</span></span></span> <span class="grvsc-line grvsc-line-highlighted"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk8">&quot;&amp; .MuiFilledInput-root&quot;</span><span class="mtk12">:</span><span class="mtk1"> {</span></span></span> <span class="grvsc-line grvsc-line-highlighted"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk8">&quot;&amp;:before&quot;</span><span class="mtk12">:</span><span class="mtk1"> {</span></span></span> <span class="grvsc-line grvsc-line-highlighted"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">borderBottom:</span><span class="mtk1"> </span><span class="mtk8">&quot;1px solid #cecece&quot;</span><span class="mtk1">,</span></span></span> <span class="grvsc-line grvsc-line-highlighted"><span class="grvsc-source"><span class="mtk1"> },</span></span></span> <span class="grvsc-line grvsc-line-highlighted"><span class="grvsc-source"><span class="mtk1"> },</span></span></span> <span class="grvsc-line grvsc-line-highlighted"><span class="grvsc-source"><span class="mtk1"> },</span></span></span> <span class="grvsc-line grvsc-line-highlighted"><span class="grvsc-source"><span class="mtk1"> }</span><span class="mtk4">}</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk4">{</span><span class="mtk1">...</span><span class="mtk12">props</span><span class="mtk4">}</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk17">/&gt;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> );</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1">}</span></span></span> <span class="grvsc-line"><span class="grvsc-source"></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk15">export</span><span class="mtk1"> </span><span class="mtk15">default</span><span class="mtk1"> </span><span class="mtk4">function</span><span class="mtk1"> </span><span class="mtk11">App</span><span class="mtk1">() {</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk15">return</span><span class="mtk1"> (</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk17">&lt;</span><span class="mtk10">TextField</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">label</span><span class="mtk1">=</span><span class="mtk8">&quot;Readonly&quot;</span></span></span> <span class="grvsc-line grvsc-line-highlighted"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">variant</span><span class="mtk1">=</span><span class="mtk8">&quot;filled&quot;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">defaultValue</span><span class="mtk1">=</span><span class="mtk8">&quot;You Can&#39;t Edit Me&quot;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">readOnly</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk17">/&gt;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> );</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1">}</span></span></span></code></pre> <div id="StyledReadonlyTextFieldFilled" data-code data-height="75px"></div> <p>If we want to style the <code>standard</code> variant, we can do the following.</p> <pre class="grvsc-container grvsc-has-line-highlighting default-dark" data-language="jsx" data-index="5"><code class="grvsc-code"><span class="grvsc-line"><span class="grvsc-source"><span class="mtk15">import</span><span class="mtk1"> </span><span class="mtk12">React</span><span class="mtk1"> </span><span class="mtk15">from</span><span class="mtk1"> </span><span class="mtk8">&quot;react&quot;</span><span class="mtk1">;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk15">import</span><span class="mtk1"> </span><span class="mtk12">MuiTextField</span><span class="mtk1"> </span><span class="mtk15">from</span><span class="mtk1"> </span><span class="mtk8">&quot;@mui/material/TextField&quot;</span><span class="mtk1">;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk4">function</span><span class="mtk1"> </span><span class="mtk11">TextField</span><span class="mtk1">({ </span><span class="mtk12">readOnly</span><span class="mtk1">, ...</span><span class="mtk12">props</span><span class="mtk1"> }) {</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk15">return</span><span class="mtk1"> (</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk17">&lt;</span><span class="mtk10">MuiTextField</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">inputProps</span><span class="mtk1">=</span><span class="mtk4">{</span><span class="mtk1">{ </span><span class="mtk12">readOnly</span><span class="mtk1"> }</span><span class="mtk4">}</span></span></span> <span class="grvsc-line grvsc-line-highlighted"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">sx</span><span class="mtk1">=</span><span class="mtk4">{</span><span class="mtk1">{</span></span></span> <span class="grvsc-line grvsc-line-highlighted"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk8">&quot;&amp;:has([readonly]) &quot;</span><span class="mtk12">:</span><span class="mtk1"> {</span></span></span> <span class="grvsc-line grvsc-line-highlighted"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk8">&quot;&amp; .MuiInputLabel-standard&quot;</span><span class="mtk12">:</span><span class="mtk1"> {</span></span></span> <span class="grvsc-line grvsc-line-highlighted"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">color:</span><span class="mtk1"> </span><span class="mtk8">&quot;#cecece&quot;</span><span class="mtk1">,</span></span></span> <span class="grvsc-line grvsc-line-highlighted"><span class="grvsc-source"><span class="mtk1"> },</span></span></span> <span class="grvsc-line grvsc-line-highlighted"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk8">&quot;&amp; .MuiInput-root&quot;</span><span class="mtk12">:</span><span class="mtk1"> {</span></span></span> <span class="grvsc-line grvsc-line-highlighted"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk8">&quot;&amp;:before&quot;</span><span class="mtk12">:</span><span class="mtk1"> {</span></span></span> <span class="grvsc-line grvsc-line-highlighted"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">borderBottom:</span><span class="mtk1"> </span><span class="mtk8">&quot;1px solid #cecece&quot;</span><span class="mtk1">,</span></span></span> <span class="grvsc-line grvsc-line-highlighted"><span class="grvsc-source"><span class="mtk1"> },</span></span></span> <span class="grvsc-line grvsc-line-highlighted"><span class="grvsc-source"><span class="mtk1"> },</span></span></span> <span class="grvsc-line grvsc-line-highlighted"><span class="grvsc-source"><span class="mtk1"> },</span></span></span> <span class="grvsc-line grvsc-line-highlighted"><span class="grvsc-source"><span class="mtk1"> }</span><span class="mtk4">}</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk4">{</span><span class="mtk1">...</span><span class="mtk12">props</span><span class="mtk4">}</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk17">/&gt;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> );</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1">}</span></span></span> <span class="grvsc-line"><span class="grvsc-source"></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk15">export</span><span class="mtk1"> </span><span class="mtk15">default</span><span class="mtk1"> </span><span class="mtk4">function</span><span class="mtk1"> </span><span class="mtk11">App</span><span class="mtk1">() {</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk15">return</span><span class="mtk1"> (</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk17">&lt;</span><span class="mtk10">TextField</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">label</span><span class="mtk1">=</span><span class="mtk8">&quot;Readonly&quot;</span></span></span> <span class="grvsc-line grvsc-line-highlighted"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">variant</span><span class="mtk1">=</span><span class="mtk8">&quot;standard&quot;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">defaultValue</span><span class="mtk1">=</span><span class="mtk8">&quot;You Can&#39;t Edit Me&quot;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">readOnly</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk17">/&gt;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> );</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1">}</span></span></span></code></pre> <div id="StyledReadonlyTextFieldStandard" data-code data-height="75px"></div> <h2 id="using-the-theme" style="position:relative;"><a href="#using-the-theme" aria-label="using the theme permalink" class="anchor before"><svg aria-hidden="true" focusable="false" height="16" version="1.1" viewBox="0 0 16 16" width="16"><path fill-rule="evenodd" d="M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z"></path></svg></a>Using the Theme</h2> <p>MUI provides a <code>createTheme</code> function that can be used to create a new theme and override the default styles. This is useful when we want the <code>readonly</code> styles to be applied globally.</p> <pre class="grvsc-container default-dark" data-language="jsx" data-index="6"><code class="grvsc-code"><span class="grvsc-line"><span class="grvsc-source"><span class="mtk15">import</span><span class="mtk1"> </span><span class="mtk12">React</span><span class="mtk1"> </span><span class="mtk15">from</span><span class="mtk1"> </span><span class="mtk8">&quot;react&quot;</span><span class="mtk1">;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk15">import</span><span class="mtk1"> { </span><span class="mtk12">createTheme</span><span class="mtk1">, </span><span class="mtk12">ThemeProvider</span><span class="mtk1"> } </span><span class="mtk15">from</span><span class="mtk1"> </span><span class="mtk8">&quot;@mui/material/styles&quot;</span><span class="mtk1">;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk15">import</span><span class="mtk1"> </span><span class="mtk12">TextField</span><span class="mtk1"> </span><span class="mtk15">from</span><span class="mtk1"> </span><span class="mtk8">&quot;@mui/material/TextField&quot;</span><span class="mtk1">;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk4">const</span><span class="mtk1"> </span><span class="mtk12">theme</span><span class="mtk1"> = </span><span class="mtk11">createTheme</span><span class="mtk1">({</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">components:</span><span class="mtk1"> {</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">MuiTextField:</span><span class="mtk1"> {</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">styleOverrides:</span><span class="mtk1"> {</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">root:</span><span class="mtk1"> {</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk8">&quot;&amp;:has([readonly]) &quot;</span><span class="mtk12">:</span><span class="mtk1"> {</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk8">&quot;&amp; .MuiInputLabel-outlined&quot;</span><span class="mtk12">:</span><span class="mtk1"> {</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">color:</span><span class="mtk1"> </span><span class="mtk8">&quot;#cecece&quot;</span><span class="mtk1">,</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> },</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk8">&quot;&amp; .MuiOutlinedInput-notchedOutline&quot;</span><span class="mtk12">:</span><span class="mtk1"> {</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">borderColor:</span><span class="mtk1"> </span><span class="mtk8">&quot;#cecece&quot;</span><span class="mtk1">,</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> },</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> },</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> },</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> },</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> },</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> },</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1">});</span></span></span> <span class="grvsc-line"><span class="grvsc-source"></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk15">export</span><span class="mtk1"> </span><span class="mtk15">default</span><span class="mtk1"> </span><span class="mtk4">function</span><span class="mtk1"> </span><span class="mtk11">BasicTextFields</span><span class="mtk1">() {</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk15">return</span><span class="mtk1"> (</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk17">&lt;</span><span class="mtk10">ThemeProvider</span><span class="mtk1"> </span><span class="mtk12">theme</span><span class="mtk1">=</span><span class="mtk4">{</span><span class="mtk12">theme</span><span class="mtk4">}</span><span class="mtk17">&gt;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk17">&lt;</span><span class="mtk10">TextField</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">label</span><span class="mtk1">=</span><span class="mtk8">&quot;Readonly&quot;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">variant</span><span class="mtk1">=</span><span class="mtk8">&quot;outlined&quot;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">defaultValue</span><span class="mtk1">=</span><span class="mtk8">&quot;You Can&#39;t Edit Me&quot;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">inputProps</span><span class="mtk1">=</span><span class="mtk4">{</span><span class="mtk1">{ </span><span class="mtk12">readOnly:</span><span class="mtk1"> </span><span class="mtk4">true</span><span class="mtk1"> }</span><span class="mtk4">}</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk17">/&gt;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk17">&lt;/</span><span class="mtk10">ThemeProvider</span><span class="mtk17">&gt;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> );</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1">}</span></span></span></code></pre> <div id="StyledReadonlyTextFieldTheme" data-code data-height="75px"></div> <p>Now, anywhere we use the MUI TextField component the <code>readonly</code> mode will be styled based on the custom theme.</p> <p>For more details on creating and customizing themes and colors, refer to <a href="https://muhimasri.com/blogs/how-to-customize-theme-and-colors-in-material-ui/">this in-depth guide</a>.</p> <h2 id="summary" style="position:relative;"><a href="#summary" aria-label="summary permalink" class="anchor before"><svg aria-hidden="true" focusable="false" height="16" version="1.1" viewBox="0 0 16 16" width="16"><path fill-rule="evenodd" d="M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z"></path></svg></a>Summary</h2> <p>In this tutorial, we learned how to create a Readonly TextField in Material UI (MUI) and React with customization and styling on different variants. Using the Theme, we also discovered how to style the <code>readonly</code> TextField globally.</p> <p>Bye for now 👋</p> <style class="grvsc-styles"> .grvsc-container { overflow: auto; position: relative; -webkit-overflow-scrolling: touch; padding-top: 1rem; padding-top: var(--grvsc-padding-top, var(--grvsc-padding-v, 1rem)); padding-bottom: 1rem; padding-bottom: var(--grvsc-padding-bottom, var(--grvsc-padding-v, 1rem)); border-radius: 8px; border-radius: var(--grvsc-border-radius, 8px); font-feature-settings: normal; line-height: 1.4; } .grvsc-code { display: table; } .grvsc-line { display: table-row; box-sizing: border-box; width: 100%; position: relative; } .grvsc-line > * { position: relative; } .grvsc-gutter-pad { display: table-cell; padding-left: 0.75rem; padding-left: calc(var(--grvsc-padding-left, var(--grvsc-padding-h, 1.5rem)) / 2); } .grvsc-gutter { display: table-cell; -webkit-user-select: none; -moz-user-select: none; user-select: none; } .grvsc-gutter::before { content: attr(data-content); } .grvsc-source { display: table-cell; padding-left: 1.5rem; padding-left: var(--grvsc-padding-left, var(--grvsc-padding-h, 1.5rem)); padding-right: 1.5rem; padding-right: var(--grvsc-padding-right, var(--grvsc-padding-h, 1.5rem)); } .grvsc-source:empty::after { content: ' '; -webkit-user-select: none; -moz-user-select: none; user-select: none; } .grvsc-gutter + .grvsc-source { padding-left: 0.75rem; padding-left: calc(var(--grvsc-padding-left, var(--grvsc-padding-h, 1.5rem)) / 2); } /* Line transformer styles */ .grvsc-has-line-highlighting > .grvsc-code > .grvsc-line::before { content: ' '; position: absolute; width: 100%; } .grvsc-line-diff-add::before { background-color: var(--grvsc-line-diff-add-background-color, rgba(0, 255, 60, 0.2)); } .grvsc-line-diff-del::before { background-color: var(--grvsc-line-diff-del-background-color, rgba(255, 0, 20, 0.2)); } .grvsc-line-number { padding: 0 2px; text-align: right; opacity: 0.7; } .default-dark { background-color: #1E1E1E; color: #D4D4D4; } .default-dark .mtk15 { color: #C586C0; } .default-dark .mtk1 { color: #D4D4D4; } .default-dark .mtk12 { color: #9CDCFE; } .default-dark .mtk8 { color: #CE9178; } .default-dark .mtk4 { color: #569CD6; } .default-dark .mtk11 { color: #DCDCAA; } .default-dark .mtk17 { color: #808080; } .default-dark .mtk10 { color: #4EC9B0; } .default-dark .mtk3 { color: #6A9955; } .default-dark .grvsc-line-highlighted::before { background-color: var(--grvsc-line-highlighted-background-color, rgba(255, 255, 255, 0.1)); box-shadow: inset var(--grvsc-line-highlighted-border-width, 4px) 0 0 0 var(--grvsc-line-highlighted-border-color, rgba(255, 255, 255, 0.5)); } </style><![CDATA[MUI TextField and Form Validation]]>https://muhimasri.commui-validationhttps://muhimasri.commui-validation<p>Validating TextFields and Forms is an essential aspect of web application development. This tutorial navigates through various validation techniques, emphasizing the use of React and Material UI (MUI). We will explore both the HTML built-in ‘required’ validation and the creation of custom TextField error validations, providing a robust understanding of form validation strategies.</p> <p>Here are the main topics that we will cover:</p> <ol> <li>Implementing MUI TextField Validation: This section will guide you through using HTML’s native ‘required’ and ‘pattern’ attributes.</li> <li>Creating Custom Error Validation for MUI TextFields: Add flexibility to your TextField validation by implementing custom error validation.</li> <li>MUI Form Validation Strategies: Learn to integrate multiple input fields into a cohesive MUI form validation process, ensuring overall data integrity and user-friendly interactions.</li> </ol> <h2 id="textfield-validation" style="position:relative;"><a href="#textfield-validation" aria-label="textfield validation permalink" class="anchor before"><svg aria-hidden="true" focusable="false" height="16" version="1.1" viewBox="0 0 16 16" width="16"><path fill-rule="evenodd" d="M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z"></path></svg></a>TextField Validation</h2> <p>Since we’re using MUI, the <code>TextField</code> component comes with handy props for applying styles and displaying error messages out of the box.</p> <pre class="grvsc-container default-dark" data-language="jsx" data-index="0"><code class="grvsc-code"><span class="grvsc-line"><span class="grvsc-source"><span class="mtk17">&lt;</span><span class="mtk10">TextField</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">error</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">label</span><span class="mtk1">=</span><span class="mtk8">&quot;Error&quot;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">defaultValue</span><span class="mtk1">=</span><span class="mtk8">&quot;Name 123&quot;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">helperText</span><span class="mtk1">=</span><span class="mtk8">&quot;Incorrect entry.&quot;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk17">/&gt;</span></span></span></code></pre> <div id="MuiTextFieldValidation" data-code data-height="100px"></div> <p>The <code>error</code> prop will apply default styling with a red border and label, and the <code>helperText</code> prop will display the error message below the <code>TextField</code>.</p> <p>Now, let’s see how to apply validation using both built-in HTML and custom error validation.</p> <h3 id="textfield-required-validation" style="position:relative;"><a href="#textfield-required-validation" aria-label="textfield required validation permalink" class="anchor before"><svg aria-hidden="true" focusable="false" height="16" version="1.1" viewBox="0 0 16 16" width="16"><path fill-rule="evenodd" d="M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z"></path></svg></a>TextField Required Validation</h3> <p><code>Required</code> is a built-in HTML attribute that can be used to validate an empty field. We can simply add the <code>required</code> attribute to the <code>TextField</code> component to use it.</p> <pre class="grvsc-container default-dark" data-language="jsx" data-index="1"><code class="grvsc-code"><span class="grvsc-line"><span class="grvsc-source"><span class="mtk17">&lt;</span><span class="mtk10">TextField</span><span class="mtk1"> </span><span class="mtk12">required</span><span class="mtk1"> </span><span class="mtk12">label</span><span class="mtk1">=</span><span class="mtk8">&quot;Required&quot;</span><span class="mtk1"> </span><span class="mtk17">/&gt;</span></span></span></code></pre> <p>We must create an <code>onChange</code> event handler to validate the user input and display the error message when the input field is empty.</p> <p>Since <code>required</code> is a built-in HTML validation, we can use the <code>validity.valid</code> property to check whether the input field is empty.</p> <pre class="grvsc-container default-dark" data-language="jsx" data-index="2"><code class="grvsc-code"><span class="grvsc-line"><span class="grvsc-source"><span class="mtk15">import</span><span class="mtk1"> </span><span class="mtk12">React</span><span class="mtk1">, { </span><span class="mtk12">useState</span><span class="mtk1"> } </span><span class="mtk15">from</span><span class="mtk1"> </span><span class="mtk8">&quot;react&quot;</span><span class="mtk1">;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk15">import</span><span class="mtk1"> { </span><span class="mtk12">TextField</span><span class="mtk1"> } </span><span class="mtk15">from</span><span class="mtk1"> </span><span class="mtk8">&quot;@mui/material&quot;</span><span class="mtk1">;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk15">export</span><span class="mtk1"> </span><span class="mtk15">default</span><span class="mtk1"> </span><span class="mtk4">function</span><span class="mtk1"> </span><span class="mtk11">TextFieldValidation</span><span class="mtk1">() {</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk4">const</span><span class="mtk1"> [</span><span class="mtk12">name</span><span class="mtk1">, </span><span class="mtk12">setName</span><span class="mtk1">] = </span><span class="mtk11">useState</span><span class="mtk1">(</span><span class="mtk8">&quot;&quot;</span><span class="mtk1">);</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk4">const</span><span class="mtk1"> [</span><span class="mtk12">nameError</span><span class="mtk1">, </span><span class="mtk12">setNameError</span><span class="mtk1">] = </span><span class="mtk11">useState</span><span class="mtk1">(</span><span class="mtk4">false</span><span class="mtk1">);</span></span></span> <span class="grvsc-line"><span class="grvsc-source"></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk4">const</span><span class="mtk1"> </span><span class="mtk11">handleNameChange</span><span class="mtk1"> = </span><span class="mtk12">e</span><span class="mtk1"> </span><span class="mtk4">=&gt;</span><span class="mtk1"> {</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk11">setName</span><span class="mtk1">(</span><span class="mtk12">e</span><span class="mtk1">.</span><span class="mtk12">target</span><span class="mtk1">.</span><span class="mtk12">value</span><span class="mtk1">);</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk15">if</span><span class="mtk1"> (</span><span class="mtk12">e</span><span class="mtk1">.</span><span class="mtk12">target</span><span class="mtk1">.</span><span class="mtk12">validity</span><span class="mtk1">.</span><span class="mtk12">valid</span><span class="mtk1">) {</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk11">setNameError</span><span class="mtk1">(</span><span class="mtk4">false</span><span class="mtk1">);</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> } </span><span class="mtk15">else</span><span class="mtk1"> {</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk11">setNameError</span><span class="mtk1">(</span><span class="mtk4">true</span><span class="mtk1">);</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> }</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> };</span></span></span> <span class="grvsc-line"><span class="grvsc-source"></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk15">return</span><span class="mtk1"> (</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk17">&lt;</span><span class="mtk10">TextField</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">required</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">label</span><span class="mtk1">=</span><span class="mtk8">&quot;Required&quot;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">value</span><span class="mtk1">=</span><span class="mtk4">{</span><span class="mtk12">name</span><span class="mtk4">}</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">onChange</span><span class="mtk1">=</span><span class="mtk4">{</span><span class="mtk12">handleNameChange</span><span class="mtk4">}</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">error</span><span class="mtk1">=</span><span class="mtk4">{</span><span class="mtk12">nameError</span><span class="mtk4">}</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">helperText</span><span class="mtk1">=</span><span class="mtk4">{</span><span class="mtk12">nameError</span><span class="mtk1"> ? </span><span class="mtk8">&quot;Please enter your name&quot;</span><span class="mtk1"> : </span><span class="mtk8">&quot;&quot;</span><span class="mtk4">}</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk17">/&gt;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> );</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1">}</span></span></span></code></pre> <div id="MuiTextFieldRequiredValidation" data-code data-height="100px"></div> <p>In the example above, when typing and deleting the input field, the error message will show up. We didn’t add any logic to check if the <code>TextField</code> is empty because the <code>required</code> attribute will take care of it! We only need to show the error message if it’s invalid using the <code>helperText</code> prop.</p> <h3 id="textfield-pattern-validation" style="position:relative;"><a href="#textfield-pattern-validation" aria-label="textfield pattern validation permalink" class="anchor before"><svg aria-hidden="true" focusable="false" height="16" version="1.1" viewBox="0 0 16 16" width="16"><path fill-rule="evenodd" d="M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z"></path></svg></a>TextField Pattern Validation</h3> <p><code>Pattern</code> is another built-in HTML attribute that can be used for more complex validation. For example, we can enhance the previous validation only to accept letters and spaces.</p> <pre class="grvsc-container default-dark" data-language="jsx" data-index="3"><code class="grvsc-code"><span class="grvsc-line"><span class="grvsc-source"><span class="mtk15">import</span><span class="mtk1"> </span><span class="mtk12">React</span><span class="mtk1">, { </span><span class="mtk12">useState</span><span class="mtk1"> } </span><span class="mtk15">from</span><span class="mtk1"> </span><span class="mtk8">&quot;react&quot;</span><span class="mtk1">;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk15">import</span><span class="mtk1"> { </span><span class="mtk12">TextField</span><span class="mtk1"> } </span><span class="mtk15">from</span><span class="mtk1"> </span><span class="mtk8">&quot;@mui/material&quot;</span><span class="mtk1">;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk15">export</span><span class="mtk1"> </span><span class="mtk15">default</span><span class="mtk1"> </span><span class="mtk4">function</span><span class="mtk1"> </span><span class="mtk11">TextFieldValidation</span><span class="mtk1">() {</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk4">const</span><span class="mtk1"> [</span><span class="mtk12">name</span><span class="mtk1">, </span><span class="mtk12">setName</span><span class="mtk1">] = </span><span class="mtk11">useState</span><span class="mtk1">(</span><span class="mtk8">&quot;&quot;</span><span class="mtk1">);</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk4">const</span><span class="mtk1"> [</span><span class="mtk12">nameError</span><span class="mtk1">, </span><span class="mtk12">setNameError</span><span class="mtk1">] = </span><span class="mtk11">useState</span><span class="mtk1">(</span><span class="mtk4">false</span><span class="mtk1">);</span></span></span> <span class="grvsc-line"><span class="grvsc-source"></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk4">const</span><span class="mtk1"> </span><span class="mtk11">handleNameChange</span><span class="mtk1"> = </span><span class="mtk12">e</span><span class="mtk1"> </span><span class="mtk4">=&gt;</span><span class="mtk1"> {</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk11">setName</span><span class="mtk1">(</span><span class="mtk12">e</span><span class="mtk1">.</span><span class="mtk12">target</span><span class="mtk1">.</span><span class="mtk12">value</span><span class="mtk1">);</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk15">if</span><span class="mtk1"> (</span><span class="mtk12">e</span><span class="mtk1">.</span><span class="mtk12">target</span><span class="mtk1">.</span><span class="mtk12">validity</span><span class="mtk1">.</span><span class="mtk12">valid</span><span class="mtk1">) {</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk11">setNameError</span><span class="mtk1">(</span><span class="mtk4">false</span><span class="mtk1">);</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> } </span><span class="mtk15">else</span><span class="mtk1"> {</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk11">setNameError</span><span class="mtk1">(</span><span class="mtk4">true</span><span class="mtk1">);</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> }</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> };</span></span></span> <span class="grvsc-line"><span class="grvsc-source"></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk15">return</span><span class="mtk1"> (</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk17">&lt;</span><span class="mtk10">TextField</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">required</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">label</span><span class="mtk1">=</span><span class="mtk8">&quot;Required&quot;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">value</span><span class="mtk1">=</span><span class="mtk4">{</span><span class="mtk12">name</span><span class="mtk4">}</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">onChange</span><span class="mtk1">=</span><span class="mtk4">{</span><span class="mtk12">handleNameChange</span><span class="mtk4">}</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">error</span><span class="mtk1">=</span><span class="mtk4">{</span><span class="mtk12">nameError</span><span class="mtk4">}</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">helperText</span><span class="mtk1">=</span><span class="mtk4">{</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">nameError</span><span class="mtk1"> ? </span><span class="mtk8">&quot;Please enter your name (letters and spaces only)&quot;</span><span class="mtk1"> : </span><span class="mtk8">&quot;&quot;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk4">}</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">inputProps</span><span class="mtk1">=</span><span class="mtk4">{</span><span class="mtk1">{</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">pattern:</span><span class="mtk1"> </span><span class="mtk8">&quot;[A-Za-z ]+&quot;</span><span class="mtk1">,</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> }</span><span class="mtk4">}</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk17">/&gt;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> );</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1">}</span></span></span></code></pre> <div id="MuiTextFieldPatternValidation" data-code data-height="100px"></div> <p>We should see the error message if we try to type in numbers in the example above.</p> <p>Note that we added the <code>pattern</code> attribute to the <code>inputProps</code> because the <code>TexField</code> component is a wrapper that has the <code>input</code> element along with other elements. <code>inputProps</code> will pass the <code>pattern</code> attribute to the <code>input</code> element directly.</p> <h2 id="custom-error-validation" style="position:relative;"><a href="#custom-error-validation" aria-label="custom error validation permalink" class="anchor before"><svg aria-hidden="true" focusable="false" height="16" version="1.1" viewBox="0 0 16 16" width="16"><path fill-rule="evenodd" d="M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z"></path></svg></a>Custom Error Validation</h2> <p>The previous approach works great but doesn’t necessarily cover all the use cases, and regex can sometimes be tricky to read and maintain. Alternatively, we can add a validation logic in the event handle and display the appropriate error message. Let’s take an “Age” input field as an example. We want to validate that the user is at least 18 years old.</p> <pre class="grvsc-container default-dark" data-language="jsx" data-index="4"><code class="grvsc-code"><span class="grvsc-line"><span class="grvsc-source"><span class="mtk15">import</span><span class="mtk1"> </span><span class="mtk12">React</span><span class="mtk1">, { </span><span class="mtk12">useState</span><span class="mtk1"> } </span><span class="mtk15">from</span><span class="mtk1"> </span><span class="mtk8">&quot;react&quot;</span><span class="mtk1">;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk15">import</span><span class="mtk1"> { </span><span class="mtk12">TextField</span><span class="mtk1"> } </span><span class="mtk15">from</span><span class="mtk1"> </span><span class="mtk8">&quot;@mui/material&quot;</span><span class="mtk1">;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk15">export</span><span class="mtk1"> </span><span class="mtk15">default</span><span class="mtk1"> </span><span class="mtk4">function</span><span class="mtk1"> </span><span class="mtk11">TextFieldValidation</span><span class="mtk1">() {</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk4">const</span><span class="mtk1"> [</span><span class="mtk12">age</span><span class="mtk1">, </span><span class="mtk12">setAge</span><span class="mtk1">] = </span><span class="mtk11">useState</span><span class="mtk1">(</span><span class="mtk8">&quot;&quot;</span><span class="mtk1">);</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk4">const</span><span class="mtk1"> [</span><span class="mtk12">ageError</span><span class="mtk1">, </span><span class="mtk12">setAgeError</span><span class="mtk1">] = </span><span class="mtk11">useState</span><span class="mtk1">(</span><span class="mtk4">false</span><span class="mtk1">);</span></span></span> <span class="grvsc-line"><span class="grvsc-source"></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk4">const</span><span class="mtk1"> </span><span class="mtk11">handleAgeChange</span><span class="mtk1"> = </span><span class="mtk12">e</span><span class="mtk1"> </span><span class="mtk4">=&gt;</span><span class="mtk1"> {</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk11">setAge</span><span class="mtk1">(</span><span class="mtk12">e</span><span class="mtk1">.</span><span class="mtk12">target</span><span class="mtk1">.</span><span class="mtk12">value</span><span class="mtk1">);</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk15">if</span><span class="mtk1"> (</span><span class="mtk12">e</span><span class="mtk1">.</span><span class="mtk12">target</span><span class="mtk1">.</span><span class="mtk12">value</span><span class="mtk1"> &gt;= </span><span class="mtk7">18</span><span class="mtk1">) {</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk11">setAgeError</span><span class="mtk1">(</span><span class="mtk4">false</span><span class="mtk1">);</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> } </span><span class="mtk15">else</span><span class="mtk1"> {</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk11">setAgeError</span><span class="mtk1">(</span><span class="mtk4">true</span><span class="mtk1">);</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> }</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> };</span></span></span> <span class="grvsc-line"><span class="grvsc-source"></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk15">return</span><span class="mtk1"> (</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk17">&lt;</span><span class="mtk10">TextField</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">label</span><span class="mtk1">=</span><span class="mtk8">&quot;Age&quot;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">value</span><span class="mtk1">=</span><span class="mtk4">{</span><span class="mtk12">age</span><span class="mtk4">}</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">onChange</span><span class="mtk1">=</span><span class="mtk4">{</span><span class="mtk12">handleAgeChange</span><span class="mtk4">}</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">error</span><span class="mtk1">=</span><span class="mtk4">{</span><span class="mtk12">ageError</span><span class="mtk4">}</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">helperText</span><span class="mtk1">=</span><span class="mtk4">{</span><span class="mtk12">ageError</span><span class="mtk1"> ? </span><span class="mtk8">&quot;You must be at least 18 years old&quot;</span><span class="mtk1"> : </span><span class="mtk8">&quot;&quot;</span><span class="mtk4">}</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk17">/&gt;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> );</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1">}</span></span></span></code></pre> <div id="MuiTextFieldCustomErrorValidation" data-code data-height="100px"></div> <p>If we try to type in a number less than 18, we should see the error message “You must be at least 18 years old”.</p> <p>Additionally, we can add different error messages if the age is invalid or negative.</p> <pre class="grvsc-container default-dark" data-language="jsx" data-index="5"><code class="grvsc-code"><span class="grvsc-line"><span class="grvsc-source"><span class="mtk15">import</span><span class="mtk1"> </span><span class="mtk12">React</span><span class="mtk1">, { </span><span class="mtk12">useState</span><span class="mtk1"> } </span><span class="mtk15">from</span><span class="mtk1"> </span><span class="mtk8">&quot;react&quot;</span><span class="mtk1">;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk15">import</span><span class="mtk1"> { </span><span class="mtk12">TextField</span><span class="mtk1"> } </span><span class="mtk15">from</span><span class="mtk1"> </span><span class="mtk8">&quot;@mui/material&quot;</span><span class="mtk1">;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk15">export</span><span class="mtk1"> </span><span class="mtk15">default</span><span class="mtk1"> </span><span class="mtk4">function</span><span class="mtk1"> </span><span class="mtk11">TextFieldValidation</span><span class="mtk1">() {</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk4">const</span><span class="mtk1"> [</span><span class="mtk12">age</span><span class="mtk1">, </span><span class="mtk12">setAge</span><span class="mtk1">] = </span><span class="mtk11">useState</span><span class="mtk1">(</span><span class="mtk8">&quot;&quot;</span><span class="mtk1">);</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk4">const</span><span class="mtk1"> [</span><span class="mtk12">ageError</span><span class="mtk1">, </span><span class="mtk12">setAgeError</span><span class="mtk1">] = </span><span class="mtk11">useState</span><span class="mtk1">(</span><span class="mtk4">false</span><span class="mtk1">);</span></span></span> <span class="grvsc-line"><span class="grvsc-source"></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk4">const</span><span class="mtk1"> </span><span class="mtk11">handleAgeChange</span><span class="mtk1"> = </span><span class="mtk12">e</span><span class="mtk1"> </span><span class="mtk4">=&gt;</span><span class="mtk1"> {</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk11">setAge</span><span class="mtk1">(</span><span class="mtk12">e</span><span class="mtk1">.</span><span class="mtk12">target</span><span class="mtk1">.</span><span class="mtk12">value</span><span class="mtk1">);</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk15">if</span><span class="mtk1"> (</span><span class="mtk12">e</span><span class="mtk1">.</span><span class="mtk12">target</span><span class="mtk1">.</span><span class="mtk12">value</span><span class="mtk1"> &gt;= </span><span class="mtk7">18</span><span class="mtk1">) {</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk11">setAgeError</span><span class="mtk1">(</span><span class="mtk4">false</span><span class="mtk1">);</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> } </span><span class="mtk15">else</span><span class="mtk1"> </span><span class="mtk15">if</span><span class="mtk1"> (</span><span class="mtk12">e</span><span class="mtk1">.</span><span class="mtk12">target</span><span class="mtk1">.</span><span class="mtk12">value</span><span class="mtk1"> &lt; </span><span class="mtk7">0</span><span class="mtk1">) {</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk11">setAgeError</span><span class="mtk1">(</span><span class="mtk8">&quot;Age must be a positive number&quot;</span><span class="mtk1">);</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> } </span><span class="mtk15">else</span><span class="mtk1"> {</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk11">setAgeError</span><span class="mtk1">(</span><span class="mtk8">&quot;You must be at least 18 years old&quot;</span><span class="mtk1">);</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> }</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> };</span></span></span> <span class="grvsc-line"><span class="grvsc-source"></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk15">return</span><span class="mtk1"> (</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk17">&lt;</span><span class="mtk10">TextField</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">label</span><span class="mtk1">=</span><span class="mtk8">&quot;Age&quot;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">value</span><span class="mtk1">=</span><span class="mtk4">{</span><span class="mtk12">age</span><span class="mtk4">}</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">onChange</span><span class="mtk1">=</span><span class="mtk4">{</span><span class="mtk12">handleAgeChange</span><span class="mtk4">}</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">error</span><span class="mtk1">=</span><span class="mtk4">{</span><span class="mtk12">ageError</span><span class="mtk4">}</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">helperText</span><span class="mtk1">=</span><span class="mtk4">{</span><span class="mtk12">ageError</span><span class="mtk4">}</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk17">/&gt;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> );</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1">}</span></span></span></code></pre> <div id="MuiTextFieldCustomErrorValidation2" data-code data-height="100px"></div> <p>The new code should display the error message “Age must be a positive number” if the age is negative.</p> <h2 id="form-validation" style="position:relative;"><a href="#form-validation" aria-label="form validation permalink" class="anchor before"><svg aria-hidden="true" focusable="false" height="16" version="1.1" viewBox="0 0 16 16" width="16"><path fill-rule="evenodd" d="M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z"></path></svg></a>Form Validation</h2> <p>Now that we know how to validate a single <code>TextField</code>, let’s move on to validating multiple input fields in a form.</p> <p>Similar to the previous section, we will cover built-in HTML and custom error validation for the entire form.</p> <h3 id="form-with-built-in-html-validation" style="position:relative;"><a href="#form-with-built-in-html-validation" aria-label="form with built in html validation permalink" class="anchor before"><svg aria-hidden="true" focusable="false" height="16" version="1.1" viewBox="0 0 16 16" width="16"><path fill-rule="evenodd" d="M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z"></path></svg></a>Form with Built-in HTML Validation</h3> <p>We can leverage the form <code>onSubmit</code> event handler for validation when using a form. It has a built-in function called <code>checkValidity()</code> that returns whether or not the input fields are valid.</p> <p>Let’s create an example with the following requirements:</p> <ul> <li>Create a form element with two input fields (Name and Email)</li> <li>“Name” will only accept letters and spaces, and “Email” will only accept a valid email address</li> <li>Validate the form on submit</li> <li>Trigger alert with an error or success message</li> <li>Add <code>noValidate</code> attribute to the Form to turn off the default HTML validation. Otherwise, the HTML tooltip validation will show up.</li> </ul> <pre class="grvsc-container default-dark" data-language="jsx" data-index="6"><code class="grvsc-code"><span class="grvsc-line"><span class="grvsc-source"><span class="mtk15">import</span><span class="mtk1"> </span><span class="mtk12">React</span><span class="mtk1">, { </span><span class="mtk12">useState</span><span class="mtk1"> } </span><span class="mtk15">from</span><span class="mtk1"> </span><span class="mtk8">&quot;react&quot;</span><span class="mtk1">;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk15">import</span><span class="mtk1"> { </span><span class="mtk12">TextField</span><span class="mtk1">, </span><span class="mtk12">Box</span><span class="mtk1">, </span><span class="mtk12">Button</span><span class="mtk1"> } </span><span class="mtk15">from</span><span class="mtk1"> </span><span class="mtk8">&quot;@mui/material&quot;</span><span class="mtk1">;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk15">export</span><span class="mtk1"> </span><span class="mtk15">default</span><span class="mtk1"> </span><span class="mtk4">function</span><span class="mtk1"> </span><span class="mtk11">FormValidation</span><span class="mtk1">() {</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk4">const</span><span class="mtk1"> </span><span class="mtk11">handleSubmit</span><span class="mtk1"> = </span><span class="mtk12">e</span><span class="mtk1"> </span><span class="mtk4">=&gt;</span><span class="mtk1"> {</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">e</span><span class="mtk1">.</span><span class="mtk11">preventDefault</span><span class="mtk1">();</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk15">if</span><span class="mtk1"> (</span><span class="mtk12">e</span><span class="mtk1">.</span><span class="mtk12">target</span><span class="mtk1">.</span><span class="mtk11">checkValidity</span><span class="mtk1">()) {</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk11">alert</span><span class="mtk1">(</span><span class="mtk8">&quot;Form is valid! Submitting the form...&quot;</span><span class="mtk1">);</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> } </span><span class="mtk15">else</span><span class="mtk1"> {</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk11">alert</span><span class="mtk1">(</span><span class="mtk8">&quot;Form is invalid! Please check the fields...&quot;</span><span class="mtk1">);</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> }</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> };</span></span></span> <span class="grvsc-line"><span class="grvsc-source"></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk15">return</span><span class="mtk1"> (</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk17">&lt;</span><span class="mtk10">Box</span><span class="mtk1"> </span><span class="mtk12">component</span><span class="mtk1">=</span><span class="mtk8">&quot;form&quot;</span><span class="mtk1"> </span><span class="mtk12">onSubmit</span><span class="mtk1">=</span><span class="mtk4">{</span><span class="mtk12">handleSubmit</span><span class="mtk4">}</span><span class="mtk1"> </span><span class="mtk12">noValidate</span><span class="mtk17">&gt;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk17">&lt;</span><span class="mtk10">TextField</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">required</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">label</span><span class="mtk1">=</span><span class="mtk8">&quot;Name&quot;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">inputProps</span><span class="mtk1">=</span><span class="mtk4">{</span><span class="mtk1">{</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">pattern:</span><span class="mtk1"> </span><span class="mtk8">&quot;[A-Za-z ]+&quot;</span><span class="mtk1">,</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> }</span><span class="mtk4">}</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk17">/&gt;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk17">&lt;</span><span class="mtk10">TextField</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">required</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">label</span><span class="mtk1">=</span><span class="mtk8">&quot;Email&quot;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">inputProps</span><span class="mtk1">=</span><span class="mtk4">{</span><span class="mtk1">{</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">type:</span><span class="mtk1"> </span><span class="mtk8">&quot;email&quot;</span><span class="mtk1">,</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> }</span><span class="mtk4">}</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk17">/&gt;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk17">&lt;</span><span class="mtk10">Button</span><span class="mtk1"> </span><span class="mtk12">variant</span><span class="mtk1">=</span><span class="mtk8">&quot;contained&quot;</span><span class="mtk1"> </span><span class="mtk12">color</span><span class="mtk1">=</span><span class="mtk8">&quot;primary&quot;</span><span class="mtk1"> </span><span class="mtk12">type</span><span class="mtk1">=</span><span class="mtk8">&quot;submit&quot;</span><span class="mtk17">&gt;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> Submit</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk17">&lt;/</span><span class="mtk10">Button</span><span class="mtk17">&gt;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk17">&lt;/</span><span class="mtk10">Box</span><span class="mtk17">&gt;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> );</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1">}</span></span></span></code></pre> <div id="MuiFormValidation" data-code data-height="100px"></div> <p>We can see how the <code>handleSubmit</code> function has the <code>event</code> object as an argument that allows us to use the <code>checkValidity()</code> method to check if the form is valid.</p> <p>When trying the example above, we should see a valid or invalid alert message if we try to submit the form.</p> <p>Note that we didn’t add a <code>pattern</code> attribute to the “Email” <code>TextField</code> because an input with type “email” already has a built-in validation specifically for email addresses!</p> <p>Let’s update the example to include the <code>onChange</code> TextField validation.</p> <pre class="grvsc-container default-dark" data-language="jsx" data-index="7"><code class="grvsc-code"><span class="grvsc-line"><span class="grvsc-source"><span class="mtk15">import</span><span class="mtk1"> </span><span class="mtk12">React</span><span class="mtk1">, { </span><span class="mtk12">useState</span><span class="mtk1"> } </span><span class="mtk15">from</span><span class="mtk1"> </span><span class="mtk8">&quot;react&quot;</span><span class="mtk1">;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk15">import</span><span class="mtk1"> { </span><span class="mtk12">TextField</span><span class="mtk1">, </span><span class="mtk12">Box</span><span class="mtk1">, </span><span class="mtk12">Button</span><span class="mtk1"> } </span><span class="mtk15">from</span><span class="mtk1"> </span><span class="mtk8">&quot;@mui/material&quot;</span><span class="mtk1">;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk15">export</span><span class="mtk1"> </span><span class="mtk15">default</span><span class="mtk1"> </span><span class="mtk4">function</span><span class="mtk1"> </span><span class="mtk11">FormValidation</span><span class="mtk1">() {</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk4">const</span><span class="mtk1"> [</span><span class="mtk12">name</span><span class="mtk1">, </span><span class="mtk12">setName</span><span class="mtk1">] = </span><span class="mtk11">useState</span><span class="mtk1">(</span><span class="mtk8">&quot;&quot;</span><span class="mtk1">);</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk4">const</span><span class="mtk1"> [</span><span class="mtk12">nameError</span><span class="mtk1">, </span><span class="mtk12">setNameError</span><span class="mtk1">] = </span><span class="mtk11">useState</span><span class="mtk1">(</span><span class="mtk4">false</span><span class="mtk1">);</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk4">const</span><span class="mtk1"> [</span><span class="mtk12">email</span><span class="mtk1">, </span><span class="mtk12">setEmail</span><span class="mtk1">] = </span><span class="mtk11">useState</span><span class="mtk1">(</span><span class="mtk8">&quot;&quot;</span><span class="mtk1">);</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk4">const</span><span class="mtk1"> [</span><span class="mtk12">emailError</span><span class="mtk1">, </span><span class="mtk12">setEmailError</span><span class="mtk1">] = </span><span class="mtk11">useState</span><span class="mtk1">(</span><span class="mtk4">false</span><span class="mtk1">);</span></span></span> <span class="grvsc-line"><span class="grvsc-source"></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk4">const</span><span class="mtk1"> </span><span class="mtk11">handleNameChange</span><span class="mtk1"> = </span><span class="mtk12">e</span><span class="mtk1"> </span><span class="mtk4">=&gt;</span><span class="mtk1"> {</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk11">setName</span><span class="mtk1">(</span><span class="mtk12">e</span><span class="mtk1">.</span><span class="mtk12">target</span><span class="mtk1">.</span><span class="mtk12">value</span><span class="mtk1">);</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk15">if</span><span class="mtk1"> (</span><span class="mtk12">e</span><span class="mtk1">.</span><span class="mtk12">target</span><span class="mtk1">.</span><span class="mtk12">validity</span><span class="mtk1">.</span><span class="mtk12">valid</span><span class="mtk1">) {</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk11">setNameError</span><span class="mtk1">(</span><span class="mtk4">false</span><span class="mtk1">);</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> } </span><span class="mtk15">else</span><span class="mtk1"> {</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk11">setNameError</span><span class="mtk1">(</span><span class="mtk4">true</span><span class="mtk1">);</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> }</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> };</span></span></span> <span class="grvsc-line"><span class="grvsc-source"></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk4">const</span><span class="mtk1"> </span><span class="mtk11">handleEmailChange</span><span class="mtk1"> = </span><span class="mtk12">e</span><span class="mtk1"> </span><span class="mtk4">=&gt;</span><span class="mtk1"> {</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk11">setEmail</span><span class="mtk1">(</span><span class="mtk12">e</span><span class="mtk1">.</span><span class="mtk12">target</span><span class="mtk1">.</span><span class="mtk12">value</span><span class="mtk1">);</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk15">if</span><span class="mtk1"> (</span><span class="mtk12">e</span><span class="mtk1">.</span><span class="mtk12">target</span><span class="mtk1">.</span><span class="mtk12">validity</span><span class="mtk1">.</span><span class="mtk12">valid</span><span class="mtk1">) {</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk11">setEmailError</span><span class="mtk1">(</span><span class="mtk4">false</span><span class="mtk1">);</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> } </span><span class="mtk15">else</span><span class="mtk1"> {</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk11">setEmailError</span><span class="mtk1">(</span><span class="mtk4">true</span><span class="mtk1">);</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> }</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> };</span></span></span> <span class="grvsc-line"><span class="grvsc-source"></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk4">const</span><span class="mtk1"> </span><span class="mtk11">handleSubmit</span><span class="mtk1"> = </span><span class="mtk12">e</span><span class="mtk1"> </span><span class="mtk4">=&gt;</span><span class="mtk1"> {</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">e</span><span class="mtk1">.</span><span class="mtk11">preventDefault</span><span class="mtk1">();</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk15">if</span><span class="mtk1"> (</span><span class="mtk12">e</span><span class="mtk1">.</span><span class="mtk12">target</span><span class="mtk1">.</span><span class="mtk11">checkValidity</span><span class="mtk1">()) {</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk11">alert</span><span class="mtk1">(</span><span class="mtk8">&quot;Form is valid! Submitting the form...&quot;</span><span class="mtk1">);</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> } </span><span class="mtk15">else</span><span class="mtk1"> {</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk11">alert</span><span class="mtk1">(</span><span class="mtk8">&quot;Form is invalid! Please check the fields...&quot;</span><span class="mtk1">);</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> }</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> };</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk15">return</span><span class="mtk1"> (</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk17">&lt;</span><span class="mtk10">Box</span><span class="mtk1"> </span><span class="mtk12">component</span><span class="mtk1">=</span><span class="mtk8">&quot;form&quot;</span><span class="mtk1"> </span><span class="mtk12">onSubmit</span><span class="mtk1">=</span><span class="mtk4">{</span><span class="mtk12">handleSubmit</span><span class="mtk4">}</span><span class="mtk1"> </span><span class="mtk12">noValidate</span><span class="mtk17">&gt;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk17">&lt;</span><span class="mtk10">TextField</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">required</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">label</span><span class="mtk1">=</span><span class="mtk8">&quot;Name&quot;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">value</span><span class="mtk1">=</span><span class="mtk4">{</span><span class="mtk12">name</span><span class="mtk4">}</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">onChange</span><span class="mtk1">=</span><span class="mtk4">{</span><span class="mtk12">handleNameChange</span><span class="mtk4">}</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">error</span><span class="mtk1">=</span><span class="mtk4">{</span><span class="mtk12">nameError</span><span class="mtk4">}</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">inputProps</span><span class="mtk1">=</span><span class="mtk4">{</span><span class="mtk1">{</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">pattern:</span><span class="mtk1"> </span><span class="mtk8">&quot;[A-Za-z ]+&quot;</span><span class="mtk1">,</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> }</span><span class="mtk4">}</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">helperText</span><span class="mtk1">=</span><span class="mtk4">{</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">nameError</span><span class="mtk1"> ? </span><span class="mtk8">&quot;Please enter your name (letters and spaces only)&quot;</span><span class="mtk1"> : </span><span class="mtk8">&quot;&quot;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk4">}</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk17">/&gt;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk17">&lt;</span><span class="mtk10">TextField</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">required</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">label</span><span class="mtk1">=</span><span class="mtk8">&quot;Email&quot;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">value</span><span class="mtk1">=</span><span class="mtk4">{</span><span class="mtk12">email</span><span class="mtk4">}</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">onChange</span><span class="mtk1">=</span><span class="mtk4">{</span><span class="mtk12">handleEmailChange</span><span class="mtk4">}</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">error</span><span class="mtk1">=</span><span class="mtk4">{</span><span class="mtk12">emailError</span><span class="mtk4">}</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">helperText</span><span class="mtk1">=</span><span class="mtk4">{</span><span class="mtk12">emailError</span><span class="mtk1"> ? </span><span class="mtk8">&quot;Please enter a valid email&quot;</span><span class="mtk1"> : </span><span class="mtk8">&quot;&quot;</span><span class="mtk4">}</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">inputProps</span><span class="mtk1">=</span><span class="mtk4">{</span><span class="mtk1">{</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">type:</span><span class="mtk1"> </span><span class="mtk8">&quot;email&quot;</span><span class="mtk1">,</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> }</span><span class="mtk4">}</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk17">/&gt;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk17">&lt;</span><span class="mtk10">Button</span><span class="mtk1"> </span><span class="mtk12">variant</span><span class="mtk1">=</span><span class="mtk8">&quot;contained&quot;</span><span class="mtk1"> </span><span class="mtk12">color</span><span class="mtk1">=</span><span class="mtk8">&quot;primary&quot;</span><span class="mtk1"> </span><span class="mtk12">type</span><span class="mtk1">=</span><span class="mtk8">&quot;submit&quot;</span><span class="mtk17">&gt;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> Submit</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk17">&lt;/</span><span class="mtk10">Button</span><span class="mtk17">&gt;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk17">&lt;/</span><span class="mtk10">Box</span><span class="mtk17">&gt;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> );</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1">}</span></span></span></code></pre> <div id="MuiFormValidation2" data-code data-height="100px"></div> <p>Now we have both validation, <code>onChange</code> and <code>onSubmit</code>. One is for input field change, and the other is for form validation on submit.</p> <h3 id="form-with-custom-error-validation" style="position:relative;"><a href="#form-with-custom-error-validation" aria-label="form with custom error validation permalink" class="anchor before"><svg aria-hidden="true" focusable="false" height="16" version="1.1" viewBox="0 0 16 16" width="16"><path fill-rule="evenodd" d="M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z"></path></svg></a>Form with Custom Error Validation</h3> <p>As mentioned earlier, using the custom error validation approach gives us more flexibility and control over the validation logic but also requires more work.</p> <p>Let’s take the previous example and add a custom error validation for the input change handlers.</p> <p>Here are the requirements for the example:</p> <ul> <li>“Name” will only accept letters and spaces with a length between 3 and 20 characters</li> <li>“Email” will only accept a valid email address that contains a domain name and ’@’ symbol</li> </ul> <pre class="grvsc-container default-dark" data-language="jsx" data-index="8"><code class="grvsc-code"><span class="grvsc-line"><span class="grvsc-source"><span class="mtk4">const</span><span class="mtk1"> [</span><span class="mtk12">name</span><span class="mtk1">, </span><span class="mtk12">setName</span><span class="mtk1">] = </span><span class="mtk11">useState</span><span class="mtk1">(</span><span class="mtk8">&quot;&quot;</span><span class="mtk1">);</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk4">const</span><span class="mtk1"> [</span><span class="mtk12">nameError</span><span class="mtk1">, </span><span class="mtk12">setNameError</span><span class="mtk1">] = </span><span class="mtk11">useState</span><span class="mtk1">(</span><span class="mtk8">&quot;&quot;</span><span class="mtk1">);</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk4">const</span><span class="mtk1"> [</span><span class="mtk12">email</span><span class="mtk1">, </span><span class="mtk12">setEmail</span><span class="mtk1">] = </span><span class="mtk11">useState</span><span class="mtk1">(</span><span class="mtk8">&quot;&quot;</span><span class="mtk1">);</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk4">const</span><span class="mtk1"> [</span><span class="mtk12">emailError</span><span class="mtk1">, </span><span class="mtk12">setEmailError</span><span class="mtk1">] = </span><span class="mtk11">useState</span><span class="mtk1">(</span><span class="mtk4">false</span><span class="mtk1">);</span></span></span> <span class="grvsc-line"><span class="grvsc-source"></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk4">const</span><span class="mtk1"> </span><span class="mtk11">handleNameChange</span><span class="mtk1"> = </span><span class="mtk12">e</span><span class="mtk1"> </span><span class="mtk4">=&gt;</span><span class="mtk1"> {</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk11">setName</span><span class="mtk1">(</span><span class="mtk12">e</span><span class="mtk1">.</span><span class="mtk12">target</span><span class="mtk1">.</span><span class="mtk12">value</span><span class="mtk1">);</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk15">if</span><span class="mtk1"> (</span><span class="mtk12">e</span><span class="mtk1">.</span><span class="mtk12">target</span><span class="mtk1">.</span><span class="mtk12">value</span><span class="mtk1">.</span><span class="mtk12">length</span><span class="mtk1"> &lt; </span><span class="mtk7">3</span><span class="mtk1">) {</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk11">setNameError</span><span class="mtk1">(</span><span class="mtk8">&quot;Name must be at least 3 characters long&quot;</span><span class="mtk1">);</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> } </span><span class="mtk15">else</span><span class="mtk1"> </span><span class="mtk15">if</span><span class="mtk1"> (</span><span class="mtk12">e</span><span class="mtk1">.</span><span class="mtk12">target</span><span class="mtk1">.</span><span class="mtk12">value</span><span class="mtk1">.</span><span class="mtk12">length</span><span class="mtk1"> &gt; </span><span class="mtk7">20</span><span class="mtk1">) {</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk11">setNameError</span><span class="mtk1">(</span><span class="mtk8">&quot;Name must be less than 20 characters long&quot;</span><span class="mtk1">);</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> } </span><span class="mtk15">else</span><span class="mtk1"> </span><span class="mtk15">if</span><span class="mtk1"> (!</span><span class="mtk5">/</span><span class="mtk11">^</span><span class="mtk8">[</span><span class="mtk5">a-zA-Z </span><span class="mtk8">]</span><span class="mtk6">+</span><span class="mtk11">$</span><span class="mtk5">/</span><span class="mtk1">.</span><span class="mtk11">test</span><span class="mtk1">(</span><span class="mtk12">e</span><span class="mtk1">.</span><span class="mtk12">target</span><span class="mtk1">.</span><span class="mtk12">value</span><span class="mtk1">)) {</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk11">setNameError</span><span class="mtk1">(</span><span class="mtk8">&quot;Name must contain only letters and spaces&quot;</span><span class="mtk1">);</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> } </span><span class="mtk15">else</span><span class="mtk1"> {</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk11">setNameError</span><span class="mtk1">(</span><span class="mtk4">false</span><span class="mtk1">);</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> }</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1">};</span></span></span> <span class="grvsc-line"><span class="grvsc-source"></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk4">const</span><span class="mtk1"> </span><span class="mtk11">handleEmailChange</span><span class="mtk1"> = </span><span class="mtk12">e</span><span class="mtk1"> </span><span class="mtk4">=&gt;</span><span class="mtk1"> {</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk11">setEmail</span><span class="mtk1">(</span><span class="mtk12">e</span><span class="mtk1">.</span><span class="mtk12">target</span><span class="mtk1">.</span><span class="mtk12">value</span><span class="mtk1">);</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk15">if</span><span class="mtk1"> (!</span><span class="mtk5">/</span><span class="mtk11">^</span><span class="mtk8">[</span><span class="mtk5">a-zA-Z0-9._:$!%-</span><span class="mtk8">]</span><span class="mtk6">+</span><span class="mtk5">@</span><span class="mtk8">[</span><span class="mtk5">a-zA-Z0-9.-</span><span class="mtk8">]</span><span class="mtk6">+</span><span class="mtk5">.</span><span class="mtk8">[</span><span class="mtk5">a-zA-Z</span><span class="mtk8">]</span><span class="mtk11">$</span><span class="mtk5">/</span><span class="mtk1">.</span><span class="mtk11">test</span><span class="mtk1">(</span><span class="mtk12">e</span><span class="mtk1">.</span><span class="mtk12">target</span><span class="mtk1">.</span><span class="mtk12">value</span><span class="mtk1">)) {</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk11">setEmailError</span><span class="mtk1">(</span><span class="mtk8">&quot;Invalid email address&quot;</span><span class="mtk1">);</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> } </span><span class="mtk15">else</span><span class="mtk1"> {</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk11">setEmailError</span><span class="mtk1">(</span><span class="mtk4">false</span><span class="mtk1">);</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> }</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1">};</span></span></span></code></pre> <p>We can remove the <code>pattern</code> and <code>required</code> attributes for the elements because now we’re handling the validation logic in the event handler.</p> <pre class="grvsc-container default-dark" data-language="jsx" data-index="9"><code class="grvsc-code"><span class="grvsc-line"><span class="grvsc-source"><span class="mtk17">&lt;</span><span class="mtk10">Box</span><span class="mtk1"> </span><span class="mtk12">component</span><span class="mtk1">=</span><span class="mtk8">&quot;form&quot;</span><span class="mtk1"> </span><span class="mtk12">onSubmit</span><span class="mtk1">=</span><span class="mtk4">{</span><span class="mtk12">handleSubmit</span><span class="mtk4">}</span><span class="mtk1"> </span><span class="mtk12">noValidate</span><span class="mtk17">&gt;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk17">&lt;</span><span class="mtk10">TextField</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">label</span><span class="mtk1">=</span><span class="mtk8">&quot;Name&quot;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">value</span><span class="mtk1">=</span><span class="mtk4">{</span><span class="mtk12">name</span><span class="mtk4">}</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">onChange</span><span class="mtk1">=</span><span class="mtk4">{</span><span class="mtk12">handleNameChange</span><span class="mtk4">}</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">error</span><span class="mtk1">=</span><span class="mtk4">{</span><span class="mtk12">nameError</span><span class="mtk4">}</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">helperText</span><span class="mtk1">=</span><span class="mtk4">{</span><span class="mtk12">nameError</span><span class="mtk4">}</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk17">/&gt;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk17">&lt;</span><span class="mtk10">TextField</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">label</span><span class="mtk1">=</span><span class="mtk8">&quot;Email&quot;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">value</span><span class="mtk1">=</span><span class="mtk4">{</span><span class="mtk12">email</span><span class="mtk4">}</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">onChange</span><span class="mtk1">=</span><span class="mtk4">{</span><span class="mtk12">handleEmailChange</span><span class="mtk4">}</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">error</span><span class="mtk1">=</span><span class="mtk4">{</span><span class="mtk12">emailError</span><span class="mtk4">}</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">helperText</span><span class="mtk1">=</span><span class="mtk4">{</span><span class="mtk12">emailError</span><span class="mtk4">}</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk17">/&gt;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk17">&lt;</span><span class="mtk10">Button</span><span class="mtk1"> </span><span class="mtk12">variant</span><span class="mtk1">=</span><span class="mtk8">&quot;contained&quot;</span><span class="mtk1"> </span><span class="mtk12">color</span><span class="mtk1">=</span><span class="mtk8">&quot;primary&quot;</span><span class="mtk1"> </span><span class="mtk12">type</span><span class="mtk1">=</span><span class="mtk8">&quot;submit&quot;</span><span class="mtk17">&gt;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> Submit</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk17">&lt;/</span><span class="mtk10">Button</span><span class="mtk17">&gt;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk17">&lt;/</span><span class="mtk10">Box</span><span class="mtk17">&gt;</span></span></span></code></pre> <p>Finally, we need to update the <code>handleSubmit</code> event handler to check if the form is valid or not:</p> <pre class="grvsc-container default-dark" data-language="jsx" data-index="10"><code class="grvsc-code"><span class="grvsc-line"><span class="grvsc-source"><span class="mtk4">const</span><span class="mtk1"> </span><span class="mtk11">handleSubmit</span><span class="mtk1"> = </span><span class="mtk12">e</span><span class="mtk1"> </span><span class="mtk4">=&gt;</span><span class="mtk1"> {</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">e</span><span class="mtk1">.</span><span class="mtk11">preventDefault</span><span class="mtk1">();</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk15">if</span><span class="mtk1"> (</span><span class="mtk12">nameError</span><span class="mtk1"> || </span><span class="mtk12">emailError</span><span class="mtk1">) {</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk11">alert</span><span class="mtk1">(</span><span class="mtk8">&quot;Form is invalid! Please check the fields...&quot;</span><span class="mtk1">);</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> } </span><span class="mtk15">else</span><span class="mtk1"> {</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk11">alert</span><span class="mtk1">(</span><span class="mtk8">&quot;Form is valid! Submitting the form...&quot;</span><span class="mtk1">);</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> }</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1">};</span></span></span></code></pre> <p>Here are all the pieces put together.</p> <pre class="grvsc-container default-dark" data-language="jsx" data-index="11"><code class="grvsc-code"><span class="grvsc-line"><span class="grvsc-source"><span class="mtk15">import</span><span class="mtk1"> </span><span class="mtk12">React</span><span class="mtk1">, { </span><span class="mtk12">useState</span><span class="mtk1"> } </span><span class="mtk15">from</span><span class="mtk1"> </span><span class="mtk8">&quot;react&quot;</span><span class="mtk1">;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk15">import</span><span class="mtk1"> { </span><span class="mtk12">TextField</span><span class="mtk1">, </span><span class="mtk12">Box</span><span class="mtk1">, </span><span class="mtk12">Button</span><span class="mtk1"> } </span><span class="mtk15">from</span><span class="mtk1"> </span><span class="mtk8">&quot;@mui/material&quot;</span><span class="mtk1">;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk15">export</span><span class="mtk1"> </span><span class="mtk15">default</span><span class="mtk1"> </span><span class="mtk4">function</span><span class="mtk1"> </span><span class="mtk11">FormValidation</span><span class="mtk1">() {</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk4">const</span><span class="mtk1"> [</span><span class="mtk12">name</span><span class="mtk1">, </span><span class="mtk12">setName</span><span class="mtk1">] = </span><span class="mtk11">useState</span><span class="mtk1">(</span><span class="mtk8">&quot;&quot;</span><span class="mtk1">);</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk4">const</span><span class="mtk1"> [</span><span class="mtk12">nameError</span><span class="mtk1">, </span><span class="mtk12">setNameError</span><span class="mtk1">] = </span><span class="mtk11">useState</span><span class="mtk1">(</span><span class="mtk8">&quot;&quot;</span><span class="mtk1">);</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk4">const</span><span class="mtk1"> [</span><span class="mtk12">email</span><span class="mtk1">, </span><span class="mtk12">setEmail</span><span class="mtk1">] = </span><span class="mtk11">useState</span><span class="mtk1">(</span><span class="mtk8">&quot;&quot;</span><span class="mtk1">);</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk4">const</span><span class="mtk1"> [</span><span class="mtk12">emailError</span><span class="mtk1">, </span><span class="mtk12">setEmailError</span><span class="mtk1">] = </span><span class="mtk11">useState</span><span class="mtk1">(</span><span class="mtk4">false</span><span class="mtk1">);</span></span></span> <span class="grvsc-line"><span class="grvsc-source"></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk4">const</span><span class="mtk1"> </span><span class="mtk11">handleNameChange</span><span class="mtk1"> = </span><span class="mtk12">e</span><span class="mtk1"> </span><span class="mtk4">=&gt;</span><span class="mtk1"> {</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk11">setName</span><span class="mtk1">(</span><span class="mtk12">e</span><span class="mtk1">.</span><span class="mtk12">target</span><span class="mtk1">.</span><span class="mtk12">value</span><span class="mtk1">);</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk15">if</span><span class="mtk1"> (</span><span class="mtk12">e</span><span class="mtk1">.</span><span class="mtk12">target</span><span class="mtk1">.</span><span class="mtk12">value</span><span class="mtk1">.</span><span class="mtk12">length</span><span class="mtk1"> &lt; </span><span class="mtk7">3</span><span class="mtk1">) {</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk11">setNameError</span><span class="mtk1">(</span><span class="mtk8">&quot;Name must be at least 3 characters long&quot;</span><span class="mtk1">);</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> } </span><span class="mtk15">else</span><span class="mtk1"> </span><span class="mtk15">if</span><span class="mtk1"> (</span><span class="mtk12">e</span><span class="mtk1">.</span><span class="mtk12">target</span><span class="mtk1">.</span><span class="mtk12">value</span><span class="mtk1">.</span><span class="mtk12">length</span><span class="mtk1"> &gt; </span><span class="mtk7">20</span><span class="mtk1">) {</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk11">setNameError</span><span class="mtk1">(</span><span class="mtk8">&quot;Name must be less than 20 characters long&quot;</span><span class="mtk1">);</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> } </span><span class="mtk15">else</span><span class="mtk1"> </span><span class="mtk15">if</span><span class="mtk1"> (!</span><span class="mtk5">/</span><span class="mtk11">^</span><span class="mtk8">[</span><span class="mtk5">a-zA-Z </span><span class="mtk8">]</span><span class="mtk6">+</span><span class="mtk11">$</span><span class="mtk5">/</span><span class="mtk1">.</span><span class="mtk11">test</span><span class="mtk1">(</span><span class="mtk12">e</span><span class="mtk1">.</span><span class="mtk12">target</span><span class="mtk1">.</span><span class="mtk12">value</span><span class="mtk1">)) {</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk11">setNameError</span><span class="mtk1">(</span><span class="mtk8">&quot;Name must contain only letters and spaces&quot;</span><span class="mtk1">);</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> } </span><span class="mtk15">else</span><span class="mtk1"> {</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk11">setNameError</span><span class="mtk1">(</span><span class="mtk4">false</span><span class="mtk1">);</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> }</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> };</span></span></span> <span class="grvsc-line"><span class="grvsc-source"></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk4">const</span><span class="mtk1"> </span><span class="mtk11">handleEmailChange</span><span class="mtk1"> = </span><span class="mtk12">e</span><span class="mtk1"> </span><span class="mtk4">=&gt;</span><span class="mtk1"> {</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk11">setEmail</span><span class="mtk1">(</span><span class="mtk12">e</span><span class="mtk1">.</span><span class="mtk12">target</span><span class="mtk1">.</span><span class="mtk12">value</span><span class="mtk1">);</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk15">if</span><span class="mtk1"> (!</span><span class="mtk5">/</span><span class="mtk11">^</span><span class="mtk8">[</span><span class="mtk5">a-zA-Z0-9._:$!%-</span><span class="mtk8">]</span><span class="mtk6">+</span><span class="mtk5">@</span><span class="mtk8">[</span><span class="mtk5">a-zA-Z0-9.-</span><span class="mtk8">]</span><span class="mtk6">+</span><span class="mtk5">.</span><span class="mtk8">[</span><span class="mtk5">a-zA-Z</span><span class="mtk8">]</span><span class="mtk11">$</span><span class="mtk5">/</span><span class="mtk1">.</span><span class="mtk11">test</span><span class="mtk1">(</span><span class="mtk12">e</span><span class="mtk1">.</span><span class="mtk12">target</span><span class="mtk1">.</span><span class="mtk12">value</span><span class="mtk1">)) {</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk11">setEmailError</span><span class="mtk1">(</span><span class="mtk8">&quot;Invalid email address&quot;</span><span class="mtk1">);</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> } </span><span class="mtk15">else</span><span class="mtk1"> {</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk11">setEmailError</span><span class="mtk1">(</span><span class="mtk4">false</span><span class="mtk1">);</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> }</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> };</span></span></span> <span class="grvsc-line"><span class="grvsc-source"></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk4">const</span><span class="mtk1"> </span><span class="mtk11">handleSubmit</span><span class="mtk1"> = </span><span class="mtk12">e</span><span class="mtk1"> </span><span class="mtk4">=&gt;</span><span class="mtk1"> {</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">e</span><span class="mtk1">.</span><span class="mtk11">preventDefault</span><span class="mtk1">();</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk15">if</span><span class="mtk1"> (</span><span class="mtk12">nameError</span><span class="mtk1"> || </span><span class="mtk12">emailError</span><span class="mtk1">) {</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk11">alert</span><span class="mtk1">(</span><span class="mtk8">&quot;Form is invalid! Please check the fields...&quot;</span><span class="mtk1">);</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> } </span><span class="mtk15">else</span><span class="mtk1"> {</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk11">alert</span><span class="mtk1">(</span><span class="mtk8">&quot;Form is valid! Submitting the form...&quot;</span><span class="mtk1">);</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> }</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> };</span></span></span> <span class="grvsc-line"><span class="grvsc-source"></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk15">return</span><span class="mtk1"> (</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk17">&lt;</span><span class="mtk10">Box</span><span class="mtk1"> </span><span class="mtk12">component</span><span class="mtk1">=</span><span class="mtk8">&quot;form&quot;</span><span class="mtk1"> </span><span class="mtk12">onSubmit</span><span class="mtk1">=</span><span class="mtk4">{</span><span class="mtk12">handleSubmit</span><span class="mtk4">}</span><span class="mtk1"> </span><span class="mtk12">noValidate</span><span class="mtk17">&gt;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk17">&lt;</span><span class="mtk10">TextField</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">label</span><span class="mtk1">=</span><span class="mtk8">&quot;Name&quot;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">value</span><span class="mtk1">=</span><span class="mtk4">{</span><span class="mtk12">name</span><span class="mtk4">}</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">onChange</span><span class="mtk1">=</span><span class="mtk4">{</span><span class="mtk12">handleNameChange</span><span class="mtk4">}</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">error</span><span class="mtk1">=</span><span class="mtk4">{</span><span class="mtk12">nameError</span><span class="mtk4">}</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">helperText</span><span class="mtk1">=</span><span class="mtk4">{</span><span class="mtk12">nameError</span><span class="mtk4">}</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk17">/&gt;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk17">&lt;</span><span class="mtk10">TextField</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">label</span><span class="mtk1">=</span><span class="mtk8">&quot;Email&quot;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">value</span><span class="mtk1">=</span><span class="mtk4">{</span><span class="mtk12">email</span><span class="mtk4">}</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">onChange</span><span class="mtk1">=</span><span class="mtk4">{</span><span class="mtk12">handleEmailChange</span><span class="mtk4">}</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">error</span><span class="mtk1">=</span><span class="mtk4">{</span><span class="mtk12">emailError</span><span class="mtk4">}</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">helperText</span><span class="mtk1">=</span><span class="mtk4">{</span><span class="mtk12">emailError</span><span class="mtk4">}</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk17">/&gt;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk17">&lt;</span><span class="mtk10">Button</span><span class="mtk1"> </span><span class="mtk12">variant</span><span class="mtk1">=</span><span class="mtk8">&quot;contained&quot;</span><span class="mtk1"> </span><span class="mtk12">color</span><span class="mtk1">=</span><span class="mtk8">&quot;primary&quot;</span><span class="mtk1"> </span><span class="mtk12">type</span><span class="mtk1">=</span><span class="mtk8">&quot;submit&quot;</span><span class="mtk17">&gt;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> Submit</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk17">&lt;/</span><span class="mtk10">Button</span><span class="mtk17">&gt;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk17">&lt;/</span><span class="mtk10">Box</span><span class="mtk17">&gt;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> );</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1">}</span></span></span></code></pre> <div id="MuiFormValidation3" data-code data-height="100px"></div> <p>The code example should validate both text field change and form submission.</p> <h2 id="code-refactoring-and-optimization" style="position:relative;"><a href="#code-refactoring-and-optimization" aria-label="code refactoring and optimization permalink" class="anchor before"><svg aria-hidden="true" focusable="false" height="16" version="1.1" viewBox="0 0 16 16" width="16"><path fill-rule="evenodd" d="M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z"></path></svg></a>Code Refactoring and Optimization</h2> <p>The code we’ve written so far works great but could cause some maintainability and performance issues as we scale, especially when having a lot of input fields in the form. Let’s break down the code and see how to refactor and optimize it.</p> <p>First of all, every time we trigger <code>onChange</code>, everything is re-rendered. That means if we have ten input fields, every time we type in one of them, all ten input fields will be re-rendered. To avoid that, we can create an isolated component for the <code>TextField</code> and only re-render that component when the value changes.</p> <pre class="grvsc-container default-dark" data-language="jsx" data-index="12"><code class="grvsc-code"><span class="grvsc-line"><span class="grvsc-source"><span class="mtk4">const</span><span class="mtk1"> </span><span class="mtk11">ValidatedTextField</span><span class="mtk1"> = ({ </span><span class="mtk12">label</span><span class="mtk1">, </span><span class="mtk12">validator</span><span class="mtk1">, </span><span class="mtk12">onChange</span><span class="mtk1"> }) </span><span class="mtk4">=&gt;</span><span class="mtk1"> {</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk4">const</span><span class="mtk1"> [</span><span class="mtk12">value</span><span class="mtk1">, </span><span class="mtk12">setValue</span><span class="mtk1">] = </span><span class="mtk11">useState</span><span class="mtk1">(</span><span class="mtk8">&quot;&quot;</span><span class="mtk1">);</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk4">const</span><span class="mtk1"> [</span><span class="mtk12">error</span><span class="mtk1">, </span><span class="mtk12">setError</span><span class="mtk1">] = </span><span class="mtk11">useState</span><span class="mtk1">(</span><span class="mtk4">false</span><span class="mtk1">);</span></span></span> <span class="grvsc-line"><span class="grvsc-source"></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk4">const</span><span class="mtk1"> </span><span class="mtk11">handleChange</span><span class="mtk1"> = </span><span class="mtk12">e</span><span class="mtk1"> </span><span class="mtk4">=&gt;</span><span class="mtk1"> {</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk4">const</span><span class="mtk1"> </span><span class="mtk12">newValue</span><span class="mtk1"> = </span><span class="mtk12">e</span><span class="mtk1">.</span><span class="mtk12">target</span><span class="mtk1">.</span><span class="mtk12">value</span><span class="mtk1">;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk4">const</span><span class="mtk1"> </span><span class="mtk12">errorMessage</span><span class="mtk1"> = </span><span class="mtk11">validator</span><span class="mtk1">(</span><span class="mtk12">newValue</span><span class="mtk1">);</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk11">setValue</span><span class="mtk1">(</span><span class="mtk12">newValue</span><span class="mtk1">);</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk11">setError</span><span class="mtk1">(</span><span class="mtk12">errorMessage</span><span class="mtk1">);</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk11">onChange</span><span class="mtk1">(!</span><span class="mtk12">errorMessage</span><span class="mtk1">);</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> };</span></span></span> <span class="grvsc-line"><span class="grvsc-source"></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk15">return</span><span class="mtk1"> (</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk17">&lt;</span><span class="mtk10">TextField</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">label</span><span class="mtk1">=</span><span class="mtk4">{</span><span class="mtk12">label</span><span class="mtk4">}</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">value</span><span class="mtk1">=</span><span class="mtk4">{</span><span class="mtk12">value</span><span class="mtk4">}</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">onChange</span><span class="mtk1">=</span><span class="mtk4">{</span><span class="mtk12">handleChange</span><span class="mtk4">}</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">error</span><span class="mtk1">=</span><span class="mtk4">{</span><span class="mtk1">!!</span><span class="mtk12">error</span><span class="mtk4">}</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">helperText</span><span class="mtk1">=</span><span class="mtk4">{</span><span class="mtk12">error</span><span class="mtk4">}</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk17">/&gt;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> );</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1">};</span></span></span></code></pre> <p>The component returns a MUI <code>TextField</code>, but since it’s generic, we must pass a few props to make it work.</p> <ul> <li><code>label</code>: The label of the <code>TextField</code> (in our example, it’s “Email” or “Name”)</li> <li><code>validator</code>: A function that takes the value of the input field and returns an error message if the value is invalid or false if the value is valid</li> <li><code>onChange</code>: A function that takes a boolean value to indicate whether the input field is valid. This is required for the Form validation later on.</li> </ul> <p>Let’s create the two validators for the “Name” and “Email” input fields:</p> <pre class="grvsc-container default-dark" data-language="jsx" data-index="13"><code class="grvsc-code"><span class="grvsc-line"><span class="grvsc-source"><span class="mtk4">const</span><span class="mtk1"> </span><span class="mtk11">nameValidator</span><span class="mtk1"> = </span><span class="mtk12">value</span><span class="mtk1"> </span><span class="mtk4">=&gt;</span><span class="mtk1"> {</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk15">if</span><span class="mtk1"> (</span><span class="mtk12">value</span><span class="mtk1">.</span><span class="mtk12">length</span><span class="mtk1"> &lt; </span><span class="mtk7">3</span><span class="mtk1">) </span><span class="mtk15">return</span><span class="mtk1"> </span><span class="mtk8">&quot;Name must be at least 3 characters long&quot;</span><span class="mtk1">;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk15">if</span><span class="mtk1"> (</span><span class="mtk12">value</span><span class="mtk1">.</span><span class="mtk12">length</span><span class="mtk1"> &gt; </span><span class="mtk7">20</span><span class="mtk1">) </span><span class="mtk15">return</span><span class="mtk1"> </span><span class="mtk8">&quot;Name must be less than 20 characters long&quot;</span><span class="mtk1">;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk15">if</span><span class="mtk1"> (!</span><span class="mtk5">/</span><span class="mtk11">^</span><span class="mtk8">[</span><span class="mtk5">a-zA-Z </span><span class="mtk8">]</span><span class="mtk6">+</span><span class="mtk11">$</span><span class="mtk5">/</span><span class="mtk1">.</span><span class="mtk11">test</span><span class="mtk1">(</span><span class="mtk12">value</span><span class="mtk1">))</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk15">return</span><span class="mtk1"> </span><span class="mtk8">&quot;Name must contain only letters and spaces&quot;</span><span class="mtk1">;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk15">return</span><span class="mtk1"> </span><span class="mtk4">false</span><span class="mtk1">;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1">};</span></span></span> <span class="grvsc-line"><span class="grvsc-source"></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk4">const</span><span class="mtk1"> </span><span class="mtk11">emailValidator</span><span class="mtk1"> = </span><span class="mtk12">value</span><span class="mtk1"> </span><span class="mtk4">=&gt;</span><span class="mtk1"> {</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk15">if</span><span class="mtk1"> (!</span><span class="mtk5">/</span><span class="mtk11">^</span><span class="mtk8">[</span><span class="mtk5">a-zA-Z0-9._:$!%-</span><span class="mtk8">]</span><span class="mtk6">+</span><span class="mtk5">@</span><span class="mtk8">[</span><span class="mtk5">a-zA-Z0-9.-</span><span class="mtk8">]</span><span class="mtk6">+\.</span><span class="mtk8">[</span><span class="mtk5">a-zA-Z</span><span class="mtk8">]</span><span class="mtk6">+</span><span class="mtk11">$</span><span class="mtk5">/</span><span class="mtk1">.</span><span class="mtk11">test</span><span class="mtk1">(</span><span class="mtk12">value</span><span class="mtk1">))</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk15">return</span><span class="mtk1"> </span><span class="mtk8">&quot;Invalid email address&quot;</span><span class="mtk1">;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk15">return</span><span class="mtk1"> </span><span class="mtk4">false</span><span class="mtk1">;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1">};</span></span></span></code></pre> <p>The function’s logic is the same as the previous example, but instead of setting the error message to the state, we’re returning it. Also, the two functions don’t necessarily need to be in a specific component and can be moved to a separate file if required.</p> <p>Lastly, in the main <code>FormValidation</code> component, we can now use the new <code>ValidatedTextField</code> component instead of the <code>TextField</code>. Here are the changes we need to make to get it working with the new arrangement:</p> <ul> <li>Remove all the state variables and event handlers as they are now handled in the <code>ValidatedTextField</code> component</li> <li>Pass in the validators to the <code>ValidatedTextField</code> component</li> <li>Create a new <code>ref</code> object to store the validation status of each input field. The object will act as a map where the key is the input field name, and the value is a boolean indicating whether the input field is valid. The reason we use <code>ref</code> instead of the state is that we don’t want to re-render the component every time the validation status changes</li> <li>Use the <code>onChange</code> from the new <code>ValidatedTextField</code> component as a callback to update the validation status in the <code>ref</code> object</li> <li>Update the <code>handleSubmit</code> event handler to check the validation status in the <code>ref</code> object by using <code>Object.values</code> and <code>every</code> methods</li> </ul> <pre class="grvsc-container default-dark" data-language="jsx" data-index="14"><code class="grvsc-code"><span class="grvsc-line"><span class="grvsc-source"><span class="mtk15">export</span><span class="mtk1"> </span><span class="mtk15">default</span><span class="mtk1"> </span><span class="mtk4">function</span><span class="mtk1"> </span><span class="mtk11">FormValidation</span><span class="mtk1">() {</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk4">const</span><span class="mtk1"> </span><span class="mtk12">formValid</span><span class="mtk1"> = </span><span class="mtk11">useRef</span><span class="mtk1">({ </span><span class="mtk12">name:</span><span class="mtk1"> </span><span class="mtk4">false</span><span class="mtk1">, </span><span class="mtk12">email:</span><span class="mtk1"> </span><span class="mtk4">false</span><span class="mtk1"> });</span></span></span> <span class="grvsc-line"><span class="grvsc-source"></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk4">const</span><span class="mtk1"> </span><span class="mtk11">handleSubmit</span><span class="mtk1"> = </span><span class="mtk12">e</span><span class="mtk1"> </span><span class="mtk4">=&gt;</span><span class="mtk1"> {</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">e</span><span class="mtk1">.</span><span class="mtk11">preventDefault</span><span class="mtk1">();</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk15">if</span><span class="mtk1"> (</span><span class="mtk10">Object</span><span class="mtk1">.</span><span class="mtk11">values</span><span class="mtk1">(</span><span class="mtk12">formValid</span><span class="mtk1">.</span><span class="mtk12">current</span><span class="mtk1">).</span><span class="mtk11">every</span><span class="mtk1">(</span><span class="mtk12">isValid</span><span class="mtk1"> </span><span class="mtk4">=&gt;</span><span class="mtk1"> </span><span class="mtk12">isValid</span><span class="mtk1">)) {</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk11">alert</span><span class="mtk1">(</span><span class="mtk8">&quot;Form is valid! Submitting the form...&quot;</span><span class="mtk1">);</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> } </span><span class="mtk15">else</span><span class="mtk1"> {</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk11">alert</span><span class="mtk1">(</span><span class="mtk8">&quot;Form is invalid! Please check the fields...&quot;</span><span class="mtk1">);</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> }</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> };</span></span></span> <span class="grvsc-line"><span class="grvsc-source"></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk15">return</span><span class="mtk1"> (</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk17">&lt;</span><span class="mtk10">Box</span><span class="mtk1"> </span><span class="mtk12">component</span><span class="mtk1">=</span><span class="mtk8">&quot;form&quot;</span><span class="mtk1"> </span><span class="mtk12">onSubmit</span><span class="mtk1">=</span><span class="mtk4">{</span><span class="mtk12">handleSubmit</span><span class="mtk4">}</span><span class="mtk1"> </span><span class="mtk12">noValidate</span><span class="mtk17">&gt;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk17">&lt;</span><span class="mtk10">ValidatedTextField</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">label</span><span class="mtk1">=</span><span class="mtk8">&quot;Name&quot;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">validator</span><span class="mtk1">=</span><span class="mtk4">{</span><span class="mtk12">nameValidator</span><span class="mtk4">}</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">onChange</span><span class="mtk1">=</span><span class="mtk4">{</span><span class="mtk12">isValid</span><span class="mtk1"> </span><span class="mtk4">=&gt;</span><span class="mtk1"> (</span><span class="mtk12">formValid</span><span class="mtk1">.</span><span class="mtk12">current</span><span class="mtk1">.</span><span class="mtk12">name</span><span class="mtk1"> = </span><span class="mtk12">isValid</span><span class="mtk1">)</span><span class="mtk4">}</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk17">/&gt;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk17">&lt;</span><span class="mtk10">ValidatedTextField</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">label</span><span class="mtk1">=</span><span class="mtk8">&quot;Email&quot;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">validator</span><span class="mtk1">=</span><span class="mtk4">{</span><span class="mtk12">emailValidator</span><span class="mtk4">}</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">onChange</span><span class="mtk1">=</span><span class="mtk4">{</span><span class="mtk12">isValid</span><span class="mtk1"> </span><span class="mtk4">=&gt;</span><span class="mtk1"> (</span><span class="mtk12">formValid</span><span class="mtk1">.</span><span class="mtk12">current</span><span class="mtk1">.</span><span class="mtk12">email</span><span class="mtk1"> = </span><span class="mtk12">isValid</span><span class="mtk1">)</span><span class="mtk4">}</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk17">/&gt;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk17">&lt;</span><span class="mtk10">Button</span><span class="mtk1"> </span><span class="mtk12">type</span><span class="mtk1">=</span><span class="mtk8">&quot;submit&quot;</span><span class="mtk1"> </span><span class="mtk12">variant</span><span class="mtk1">=</span><span class="mtk8">&quot;contained&quot;</span><span class="mtk17">&gt;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> Submit</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk17">&lt;/</span><span class="mtk10">Button</span><span class="mtk17">&gt;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk17">&lt;/</span><span class="mtk10">Box</span><span class="mtk17">&gt;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> );</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1">}</span></span></span></code></pre> <p>Now, let’s put everything together and see what the final code looks like.</p> <pre class="grvsc-container default-dark" data-language="jsx" data-index="15"><code class="grvsc-code"><span class="grvsc-line"><span class="grvsc-source"><span class="mtk15">import</span><span class="mtk1"> </span><span class="mtk12">React</span><span class="mtk1">, { </span><span class="mtk12">useState</span><span class="mtk1">, </span><span class="mtk12">useRef</span><span class="mtk1"> } </span><span class="mtk15">from</span><span class="mtk1"> </span><span class="mtk8">&quot;react&quot;</span><span class="mtk1">;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk15">import</span><span class="mtk1"> { </span><span class="mtk12">TextField</span><span class="mtk1">, </span><span class="mtk12">Box</span><span class="mtk1">, </span><span class="mtk12">Button</span><span class="mtk1"> } </span><span class="mtk15">from</span><span class="mtk1"> </span><span class="mtk8">&quot;@mui/material&quot;</span><span class="mtk1">;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk3">// ValidatedTextField.js</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk4">const</span><span class="mtk1"> </span><span class="mtk11">ValidatedTextField</span><span class="mtk1"> = ({ </span><span class="mtk12">label</span><span class="mtk1">, </span><span class="mtk12">validator</span><span class="mtk1">, </span><span class="mtk12">onChange</span><span class="mtk1"> }) </span><span class="mtk4">=&gt;</span><span class="mtk1"> {</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk4">const</span><span class="mtk1"> [</span><span class="mtk12">value</span><span class="mtk1">, </span><span class="mtk12">setValue</span><span class="mtk1">] = </span><span class="mtk11">useState</span><span class="mtk1">(</span><span class="mtk8">&quot;&quot;</span><span class="mtk1">);</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk4">const</span><span class="mtk1"> [</span><span class="mtk12">error</span><span class="mtk1">, </span><span class="mtk12">setError</span><span class="mtk1">] = </span><span class="mtk11">useState</span><span class="mtk1">(</span><span class="mtk4">false</span><span class="mtk1">);</span></span></span> <span class="grvsc-line"><span class="grvsc-source"></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk4">const</span><span class="mtk1"> </span><span class="mtk11">handleChange</span><span class="mtk1"> = </span><span class="mtk12">e</span><span class="mtk1"> </span><span class="mtk4">=&gt;</span><span class="mtk1"> {</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk4">const</span><span class="mtk1"> </span><span class="mtk12">newValue</span><span class="mtk1"> = </span><span class="mtk12">e</span><span class="mtk1">.</span><span class="mtk12">target</span><span class="mtk1">.</span><span class="mtk12">value</span><span class="mtk1">;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk4">const</span><span class="mtk1"> </span><span class="mtk12">errorMessage</span><span class="mtk1"> = </span><span class="mtk11">validator</span><span class="mtk1">(</span><span class="mtk12">newValue</span><span class="mtk1">);</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk11">setValue</span><span class="mtk1">(</span><span class="mtk12">newValue</span><span class="mtk1">);</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk11">setError</span><span class="mtk1">(</span><span class="mtk12">errorMessage</span><span class="mtk1">);</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk11">onChange</span><span class="mtk1">(!</span><span class="mtk12">errorMessage</span><span class="mtk1">);</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> };</span></span></span> <span class="grvsc-line"><span class="grvsc-source"></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk15">return</span><span class="mtk1"> (</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk17">&lt;</span><span class="mtk10">TextField</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">label</span><span class="mtk1">=</span><span class="mtk4">{</span><span class="mtk12">label</span><span class="mtk4">}</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">value</span><span class="mtk1">=</span><span class="mtk4">{</span><span class="mtk12">value</span><span class="mtk4">}</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">onChange</span><span class="mtk1">=</span><span class="mtk4">{</span><span class="mtk12">handleChange</span><span class="mtk4">}</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">error</span><span class="mtk1">=</span><span class="mtk4">{</span><span class="mtk1">!!</span><span class="mtk12">error</span><span class="mtk4">}</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">helperText</span><span class="mtk1">=</span><span class="mtk4">{</span><span class="mtk12">error</span><span class="mtk4">}</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk17">/&gt;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> );</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1">};</span></span></span> <span class="grvsc-line"><span class="grvsc-source"></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk3">// validators.js</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk4">const</span><span class="mtk1"> </span><span class="mtk11">nameValidator</span><span class="mtk1"> = </span><span class="mtk12">value</span><span class="mtk1"> </span><span class="mtk4">=&gt;</span><span class="mtk1"> {</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk15">if</span><span class="mtk1"> (</span><span class="mtk12">value</span><span class="mtk1">.</span><span class="mtk12">length</span><span class="mtk1"> &lt; </span><span class="mtk7">3</span><span class="mtk1">) </span><span class="mtk15">return</span><span class="mtk1"> </span><span class="mtk8">&quot;Name must be at least 3 characters long&quot;</span><span class="mtk1">;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk15">if</span><span class="mtk1"> (</span><span class="mtk12">value</span><span class="mtk1">.</span><span class="mtk12">length</span><span class="mtk1"> &gt; </span><span class="mtk7">20</span><span class="mtk1">) </span><span class="mtk15">return</span><span class="mtk1"> </span><span class="mtk8">&quot;Name must be less than 20 characters long&quot;</span><span class="mtk1">;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk15">if</span><span class="mtk1"> (!</span><span class="mtk5">/</span><span class="mtk11">^</span><span class="mtk8">[</span><span class="mtk5">a-zA-Z </span><span class="mtk8">]</span><span class="mtk6">+</span><span class="mtk11">$</span><span class="mtk5">/</span><span class="mtk1">.</span><span class="mtk11">test</span><span class="mtk1">(</span><span class="mtk12">value</span><span class="mtk1">))</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk15">return</span><span class="mtk1"> </span><span class="mtk8">&quot;Name must contain only letters and spaces&quot;</span><span class="mtk1">;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk15">return</span><span class="mtk1"> </span><span class="mtk4">false</span><span class="mtk1">;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1">};</span></span></span> <span class="grvsc-line"><span class="grvsc-source"></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk4">const</span><span class="mtk1"> </span><span class="mtk11">emailValidator</span><span class="mtk1"> = </span><span class="mtk12">value</span><span class="mtk1"> </span><span class="mtk4">=&gt;</span><span class="mtk1"> {</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk15">if</span><span class="mtk1"> (!</span><span class="mtk5">/</span><span class="mtk11">^</span><span class="mtk8">[</span><span class="mtk5">a-zA-Z0-9._:$!%-</span><span class="mtk8">]</span><span class="mtk6">+</span><span class="mtk5">@</span><span class="mtk8">[</span><span class="mtk5">a-zA-Z0-9.-</span><span class="mtk8">]</span><span class="mtk6">+\.</span><span class="mtk8">[</span><span class="mtk5">a-zA-Z</span><span class="mtk8">]</span><span class="mtk6">+</span><span class="mtk11">$</span><span class="mtk5">/</span><span class="mtk1">.</span><span class="mtk11">test</span><span class="mtk1">(</span><span class="mtk12">value</span><span class="mtk1">))</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk15">return</span><span class="mtk1"> </span><span class="mtk8">&quot;Invalid email address&quot;</span><span class="mtk1">;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk15">return</span><span class="mtk1"> </span><span class="mtk4">false</span><span class="mtk1">;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1">};</span></span></span> <span class="grvsc-line"><span class="grvsc-source"></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk3">// FormValidation.js</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk15">export</span><span class="mtk1"> </span><span class="mtk15">default</span><span class="mtk1"> </span><span class="mtk4">function</span><span class="mtk1"> </span><span class="mtk11">FormValidation</span><span class="mtk1">() {</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk4">const</span><span class="mtk1"> </span><span class="mtk12">formValid</span><span class="mtk1"> = </span><span class="mtk11">useRef</span><span class="mtk1">({ </span><span class="mtk12">name:</span><span class="mtk1"> </span><span class="mtk4">false</span><span class="mtk1">, </span><span class="mtk12">email:</span><span class="mtk1"> </span><span class="mtk4">false</span><span class="mtk1"> });</span></span></span> <span class="grvsc-line"><span class="grvsc-source"></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk4">const</span><span class="mtk1"> </span><span class="mtk11">handleSubmit</span><span class="mtk1"> = </span><span class="mtk12">e</span><span class="mtk1"> </span><span class="mtk4">=&gt;</span><span class="mtk1"> {</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">e</span><span class="mtk1">.</span><span class="mtk11">preventDefault</span><span class="mtk1">();</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk15">if</span><span class="mtk1"> (</span><span class="mtk10">Object</span><span class="mtk1">.</span><span class="mtk11">values</span><span class="mtk1">(</span><span class="mtk12">formValid</span><span class="mtk1">.</span><span class="mtk12">current</span><span class="mtk1">).</span><span class="mtk11">every</span><span class="mtk1">(</span><span class="mtk12">isValid</span><span class="mtk1"> </span><span class="mtk4">=&gt;</span><span class="mtk1"> </span><span class="mtk12">isValid</span><span class="mtk1">)) {</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk11">alert</span><span class="mtk1">(</span><span class="mtk8">&quot;Form is valid! Submitting the form...&quot;</span><span class="mtk1">);</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> } </span><span class="mtk15">else</span><span class="mtk1"> {</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk11">alert</span><span class="mtk1">(</span><span class="mtk8">&quot;Form is invalid! Please check the fields...&quot;</span><span class="mtk1">);</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> }</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> };</span></span></span> <span class="grvsc-line"><span class="grvsc-source"></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk15">return</span><span class="mtk1"> (</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk17">&lt;</span><span class="mtk10">Box</span><span class="mtk1"> </span><span class="mtk12">component</span><span class="mtk1">=</span><span class="mtk8">&quot;form&quot;</span><span class="mtk1"> </span><span class="mtk12">onSubmit</span><span class="mtk1">=</span><span class="mtk4">{</span><span class="mtk12">handleSubmit</span><span class="mtk4">}</span><span class="mtk1"> </span><span class="mtk12">noValidate</span><span class="mtk17">&gt;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk17">&lt;</span><span class="mtk10">ValidatedTextField</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">label</span><span class="mtk1">=</span><span class="mtk8">&quot;Name&quot;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">validator</span><span class="mtk1">=</span><span class="mtk4">{</span><span class="mtk12">nameValidator</span><span class="mtk4">}</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">onChange</span><span class="mtk1">=</span><span class="mtk4">{</span><span class="mtk12">isValid</span><span class="mtk1"> </span><span class="mtk4">=&gt;</span><span class="mtk1"> (</span><span class="mtk12">formValid</span><span class="mtk1">.</span><span class="mtk12">current</span><span class="mtk1">.</span><span class="mtk12">name</span><span class="mtk1"> = </span><span class="mtk12">isValid</span><span class="mtk1">)</span><span class="mtk4">}</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk17">/&gt;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk17">&lt;</span><span class="mtk10">ValidatedTextField</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">label</span><span class="mtk1">=</span><span class="mtk8">&quot;Email&quot;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">validator</span><span class="mtk1">=</span><span class="mtk4">{</span><span class="mtk12">emailValidator</span><span class="mtk4">}</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">onChange</span><span class="mtk1">=</span><span class="mtk4">{</span><span class="mtk12">isValid</span><span class="mtk1"> </span><span class="mtk4">=&gt;</span><span class="mtk1"> (</span><span class="mtk12">formValid</span><span class="mtk1">.</span><span class="mtk12">current</span><span class="mtk1">.</span><span class="mtk12">email</span><span class="mtk1"> = </span><span class="mtk12">isValid</span><span class="mtk1">)</span><span class="mtk4">}</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk17">/&gt;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk17">&lt;</span><span class="mtk10">Button</span><span class="mtk1"> </span><span class="mtk12">type</span><span class="mtk1">=</span><span class="mtk8">&quot;submit&quot;</span><span class="mtk1"> </span><span class="mtk12">variant</span><span class="mtk1">=</span><span class="mtk8">&quot;contained&quot;</span><span class="mtk17">&gt;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> Submit</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk17">&lt;/</span><span class="mtk10">Button</span><span class="mtk17">&gt;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk17">&lt;/</span><span class="mtk10">Box</span><span class="mtk17">&gt;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> );</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1">}</span></span></span></code></pre> <div id="MuiFormValidation4" data-code data-height="100px"></div> <p>The outcome is the same as the previous example. Still, now we have a more generic and reusable input field component that can be used without repeatedly writing the same component. As indicated in the comments, we can split the code into separate files for better organization.</p> <h2 id="styling-and-colors" style="position:relative;"><a href="#styling-and-colors" aria-label="styling and colors permalink" class="anchor before"><svg aria-hidden="true" focusable="false" height="16" version="1.1" viewBox="0 0 16 16" width="16"><path fill-rule="evenodd" d="M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z"></path></svg></a>Styling and Colors</h2> <p>To customize the colors and other styles of the TextField error state, we can use the <code>Mui-error</code> class that is added to the TextField when the error prop is <code>true</code>.</p> <p>In the following example, we can use the error class to style the <code>helperText</code> and the input field border and label colors.</p> <pre class="grvsc-container default-dark" data-language="jsx" data-index="16"><code class="grvsc-code"><span class="grvsc-line"><span class="grvsc-source"><span class="mtk1">...</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk17">&lt;</span><span class="mtk10">TextField</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk14">...</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">sx</span><span class="mtk1">=</span><span class="mtk4">{</span><span class="mtk1">{</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk8">&quot;&amp; .MuiInputLabel-root.Mui-error&quot;</span><span class="mtk12">:</span><span class="mtk1"> {</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">color:</span><span class="mtk1"> </span><span class="mtk8">&quot;#ff8804&quot;</span><span class="mtk1">,</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> },</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk8">&quot;&amp; .MuiOutlinedInput-root.Mui-error .MuiOutlinedInput-notchedOutline&quot;</span><span class="mtk12">:</span><span class="mtk1"> {</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">border:</span><span class="mtk1"> </span><span class="mtk8">&quot;3px solid #ff8804&quot;</span><span class="mtk1">,</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> },</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk8">&quot;&amp; .MuiFormHelperText-root.Mui-error&quot;</span><span class="mtk12">:</span><span class="mtk1"> {</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">color:</span><span class="mtk1"> </span><span class="mtk8">&quot;#ff8804&quot;</span><span class="mtk1">,</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> },</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> }</span><span class="mtk4">}</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk17">/&gt;</span></span></span></code></pre> <div id="MuiTextFieldStyling" data-code data-height="100px"></div> <h2 id="conclusion" style="position:relative;"><a href="#conclusion" aria-label="conclusion permalink" class="anchor before"><svg aria-hidden="true" focusable="false" height="16" version="1.1" viewBox="0 0 16 16" width="16"><path fill-rule="evenodd" d="M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z"></path></svg></a>Conclusion</h2> <p>In this tutorial, we learned how to validate MUI TextField and Form using built-in HTML and custom error validation with code refactoring and optimization. Although plenty of useful libraries can help us with the validation, it’s always good to understand the underlying principles and build our own validation logic.</p> <p>Bye for now 👋</p> <style class="grvsc-styles"> .grvsc-container { overflow: auto; position: relative; -webkit-overflow-scrolling: touch; padding-top: 1rem; padding-top: var(--grvsc-padding-top, var(--grvsc-padding-v, 1rem)); padding-bottom: 1rem; padding-bottom: var(--grvsc-padding-bottom, var(--grvsc-padding-v, 1rem)); border-radius: 8px; border-radius: var(--grvsc-border-radius, 8px); font-feature-settings: normal; line-height: 1.4; } .grvsc-code { display: table; } .grvsc-line { display: table-row; box-sizing: border-box; width: 100%; position: relative; } .grvsc-line > * { position: relative; } .grvsc-gutter-pad { display: table-cell; padding-left: 0.75rem; padding-left: calc(var(--grvsc-padding-left, var(--grvsc-padding-h, 1.5rem)) / 2); } .grvsc-gutter { display: table-cell; -webkit-user-select: none; -moz-user-select: none; user-select: none; } .grvsc-gutter::before { content: attr(data-content); } .grvsc-source { display: table-cell; padding-left: 1.5rem; padding-left: var(--grvsc-padding-left, var(--grvsc-padding-h, 1.5rem)); padding-right: 1.5rem; padding-right: var(--grvsc-padding-right, var(--grvsc-padding-h, 1.5rem)); } .grvsc-source:empty::after { content: ' '; -webkit-user-select: none; -moz-user-select: none; user-select: none; } .grvsc-gutter + .grvsc-source { padding-left: 0.75rem; padding-left: calc(var(--grvsc-padding-left, var(--grvsc-padding-h, 1.5rem)) / 2); } /* Line transformer styles */ .grvsc-has-line-highlighting > .grvsc-code > .grvsc-line::before { content: ' '; position: absolute; width: 100%; } .grvsc-line-diff-add::before { background-color: var(--grvsc-line-diff-add-background-color, rgba(0, 255, 60, 0.2)); } .grvsc-line-diff-del::before { background-color: var(--grvsc-line-diff-del-background-color, rgba(255, 0, 20, 0.2)); } .grvsc-line-number { padding: 0 2px; text-align: right; opacity: 0.7; } .default-dark { background-color: #1E1E1E; color: #D4D4D4; } .default-dark .mtk17 { color: #808080; } .default-dark .mtk10 { color: #4EC9B0; } .default-dark .mtk1 { color: #D4D4D4; } .default-dark .mtk12 { color: #9CDCFE; } .default-dark .mtk8 { color: #CE9178; } .default-dark .mtk15 { color: #C586C0; } .default-dark .mtk4 { color: #569CD6; } .default-dark .mtk11 { color: #DCDCAA; } .default-dark .mtk7 { color: #B5CEA8; } .default-dark .mtk5 { color: #D16969; } .default-dark .mtk6 { color: #D7BA7D; } .default-dark .mtk3 { color: #6A9955; } .default-dark .mtk14 { color: #F44747; } .default-dark .grvsc-line-highlighted::before { background-color: var(--grvsc-line-highlighted-background-color, rgba(255, 255, 255, 0.1)); box-shadow: inset var(--grvsc-line-highlighted-border-width, 4px) 0 0 0 var(--grvsc-line-highlighted-border-color, rgba(255, 255, 255, 0.5)); } </style><![CDATA[MUI Typography - Complete Styling & Customization Guide]]>https://muhimasri.commui-typographyhttps://muhimasri.commui-typography<p>MUI Typography is a CSS utility component that is used to display text. It is a wrapper that renders a limited set of HTML elements like <code>p</code>, <code>h1</code>, <code>h2</code>, <code>h3</code>…etc. It follows the Material Design typography principles, including a range of highly customizable styles.</p> <p>Having a typography system helps create a consistent visual experience across platforms and devices. This tutorial will cover how to use and customize MUI Typography, including variant, color, font weight, text alignment, and other styling customizations.</p> <h2 id="mui-typography-variants" style="position:relative;"><a href="#mui-typography-variants" aria-label="mui typography variants permalink" class="anchor before"><svg aria-hidden="true" focusable="false" height="16" version="1.1" viewBox="0 0 16 16" width="16"><path fill-rule="evenodd" d="M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z"></path></svg></a>MUI Typography Variants</h2> <p>The Typography component depends on the <code>variant</code> prop to render the correct HTML element. By default, using the Typography component without a <code>variant</code> prop will render a <code>p</code> element.</p> <pre class="grvsc-container default-dark" data-language="jsx" data-index="0"><code class="grvsc-code"><span class="grvsc-line"><span class="grvsc-source"><span class="mtk17">&lt;</span><span class="mtk10">Typography</span><span class="mtk17">&gt;</span><span class="mtk1">Default Text</span><span class="mtk17">&lt;/</span><span class="mtk10">Typography</span><span class="mtk17">&gt;</span></span></span></code></pre> <div id="MuiTypographyComponent" data-code data-height="50px"></div> <p>If we inspect the element in the browser, we can see that the <code>&#x3C;p></code> element has a predefined set of styles applied to it.</p> <pre class="grvsc-container default-dark" data-language="css" data-index="1"><code class="grvsc-code"><span class="grvsc-line"><span class="grvsc-source"><span class="mtk4">font-family</span><span class="mtk1">: ..</span><span class="mtk14">.;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk4">font-weight</span><span class="mtk1">: ..</span><span class="mtk14">.;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk4">font-size</span><span class="mtk1">: ..</span><span class="mtk14">.;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk4">line-height</span><span class="mtk1">: ..</span><span class="mtk14">.;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk4">letter-spacing</span><span class="mtk1">: ..</span><span class="mtk14">.;</span></span></span></code></pre> <p>The available variants are based on the <a href="https://material.io/design/typography/the-type-system.html#type-scale">Material Design typographic scale</a>. The <code>variant</code> prop accepts a <code>string</code> value that can be one of the following:</p> <table> <thead> <tr> <th>Variant</th> <th>Element</th> <th>Description</th> </tr> </thead> <tbody> <tr> <td><code>h1</code></td> <td><code>h1</code></td> <td>Heading 1</td> </tr> <tr> <td><code>h2</code></td> <td><code>h2</code></td> <td>Heading 2</td> </tr> <tr> <td><code>h3</code></td> <td><code>h3</code></td> <td>Heading 3</td> </tr> <tr> <td><code>h4</code></td> <td><code>h4</code></td> <td>Heading 4</td> </tr> <tr> <td><code>h5</code></td> <td><code>h5</code></td> <td>Heading 5</td> </tr> <tr> <td><code>h6</code></td> <td><code>h6</code></td> <td>Heading 6</td> </tr> <tr> <td><code>body1</code></td> <td><code>p</code></td> <td>Body 1</td> </tr> <tr> <td><code>body2</code></td> <td><code>p</code></td> <td>Body 2</td> </tr> <tr> <td><code>subtitle1</code></td> <td><code>p</code></td> <td>Subtitle 1</td> </tr> <tr> <td><code>subtitle2</code></td> <td><code>p</code></td> <td>Subtitle 2</td> </tr> <tr> <td><code>caption</code></td> <td><code>p</code></td> <td>Caption</td> </tr> <tr> <td><code>button</code></td> <td><code>span</code></td> <td>Button</td> </tr> <tr> <td><code>overline</code></td> <td><code>span</code></td> <td>Overline</td> </tr> </tbody> </table> <p>Here is how we can use the <code>variant</code> prop to render each variant:</p> <pre class="grvsc-container default-dark" data-language="jsx" data-index="2"><code class="grvsc-code"><span class="grvsc-line"><span class="grvsc-source"><span class="mtk17">&lt;</span><span class="mtk10">Typography</span><span class="mtk1"> </span><span class="mtk12">variant</span><span class="mtk1">=</span><span class="mtk8">&quot;h1&quot;</span><span class="mtk17">&gt;</span><span class="mtk1">Heading 1</span><span class="mtk17">&lt;/</span><span class="mtk10">Typography</span><span class="mtk17">&gt;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk17">&lt;</span><span class="mtk10">Typography</span><span class="mtk1"> </span><span class="mtk12">variant</span><span class="mtk1">=</span><span class="mtk8">&quot;h2&quot;</span><span class="mtk17">&gt;</span><span class="mtk1">Heading 2</span><span class="mtk17">&lt;/</span><span class="mtk10">Typography</span><span class="mtk17">&gt;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk17">&lt;</span><span class="mtk10">Typography</span><span class="mtk1"> </span><span class="mtk12">variant</span><span class="mtk1">=</span><span class="mtk8">&quot;h3&quot;</span><span class="mtk17">&gt;</span><span class="mtk1">Heading 3</span><span class="mtk17">&lt;/</span><span class="mtk10">Typography</span><span class="mtk17">&gt;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk17">&lt;</span><span class="mtk10">Typography</span><span class="mtk1"> </span><span class="mtk12">variant</span><span class="mtk1">=</span><span class="mtk8">&quot;h4&quot;</span><span class="mtk17">&gt;</span><span class="mtk1">Heading 3</span><span class="mtk17">&lt;/</span><span class="mtk10">Typography</span><span class="mtk17">&gt;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk17">&lt;</span><span class="mtk10">Typography</span><span class="mtk1"> </span><span class="mtk12">variant</span><span class="mtk1">=</span><span class="mtk8">&quot;h5&quot;</span><span class="mtk17">&gt;</span><span class="mtk1">Heading 3</span><span class="mtk17">&lt;/</span><span class="mtk10">Typography</span><span class="mtk17">&gt;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk17">&lt;</span><span class="mtk10">Typography</span><span class="mtk1"> </span><span class="mtk12">variant</span><span class="mtk1">=</span><span class="mtk8">&quot;h6&quot;</span><span class="mtk17">&gt;</span><span class="mtk1">Heading 3</span><span class="mtk17">&lt;/</span><span class="mtk10">Typography</span><span class="mtk17">&gt;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk17">&lt;</span><span class="mtk10">Typography</span><span class="mtk1"> </span><span class="mtk12">variant</span><span class="mtk1">=</span><span class="mtk8">&quot;body1&quot;</span><span class="mtk17">&gt;</span><span class="mtk1">Body 1</span><span class="mtk17">&lt;/</span><span class="mtk10">Typography</span><span class="mtk17">&gt;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk17">&lt;</span><span class="mtk10">Typography</span><span class="mtk1"> </span><span class="mtk12">variant</span><span class="mtk1">=</span><span class="mtk8">&quot;body2&quot;</span><span class="mtk17">&gt;</span><span class="mtk1">Body 2</span><span class="mtk17">&lt;/</span><span class="mtk10">Typography</span><span class="mtk17">&gt;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk17">&lt;</span><span class="mtk10">Typography</span><span class="mtk1"> </span><span class="mtk12">variant</span><span class="mtk1">=</span><span class="mtk8">&quot;subtitle1&quot;</span><span class="mtk17">&gt;</span><span class="mtk1">Subtitle 1</span><span class="mtk17">&lt;/</span><span class="mtk10">Typography</span><span class="mtk17">&gt;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk17">&lt;</span><span class="mtk10">Typography</span><span class="mtk1"> </span><span class="mtk12">variant</span><span class="mtk1">=</span><span class="mtk8">&quot;subtitle2&quot;</span><span class="mtk17">&gt;</span><span class="mtk1">Subtitle 2</span><span class="mtk17">&lt;/</span><span class="mtk10">Typography</span><span class="mtk17">&gt;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk17">&lt;</span><span class="mtk10">Typography</span><span class="mtk1"> </span><span class="mtk12">variant</span><span class="mtk1">=</span><span class="mtk8">&quot;caption&quot;</span><span class="mtk17">&gt;</span><span class="mtk1">Caption</span><span class="mtk17">&lt;/</span><span class="mtk10">Typography</span><span class="mtk17">&gt;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk17">&lt;</span><span class="mtk10">Typography</span><span class="mtk1"> </span><span class="mtk12">variant</span><span class="mtk1">=</span><span class="mtk8">&quot;button&quot;</span><span class="mtk17">&gt;</span><span class="mtk1">Button</span><span class="mtk17">&lt;/</span><span class="mtk10">Typography</span><span class="mtk17">&gt;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk17">&lt;</span><span class="mtk10">Typography</span><span class="mtk1"> </span><span class="mtk12">variant</span><span class="mtk1">=</span><span class="mtk8">&quot;overline&quot;</span><span class="mtk17">&gt;</span><span class="mtk1">Overline</span><span class="mtk17">&lt;/</span><span class="mtk10">Typography</span><span class="mtk17">&gt;</span></span></span></code></pre> <div id="MuiTypographyVariants" data-code data-height="475px"></div> <h3 id="customize-a-variant" style="position:relative;"><a href="#customize-a-variant" aria-label="customize a variant permalink" class="anchor before"><svg aria-hidden="true" focusable="false" height="16" version="1.1" viewBox="0 0 16 16" width="16"><path fill-rule="evenodd" d="M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z"></path></svg></a>Customize a variant</h3> <p>We can customize any variant from the theme in the <code>typography</code> object. In the following example, we will change the <code>h1</code> variant to have a font size of <code>6rem</code> and a font-weight of <code>700</code>.</p> <pre class="grvsc-container default-dark" data-language="jsx" data-index="3"><code class="grvsc-code"><span class="grvsc-line"><span class="grvsc-source"><span class="mtk15">import</span><span class="mtk1"> </span><span class="mtk12">React</span><span class="mtk1"> </span><span class="mtk15">from</span><span class="mtk1"> </span><span class="mtk8">&quot;react&quot;</span><span class="mtk1">;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk15">import</span><span class="mtk1"> { </span><span class="mtk12">createTheme</span><span class="mtk1">, </span><span class="mtk12">ThemeProvider</span><span class="mtk1">, </span><span class="mtk12">Typography</span><span class="mtk1"> } </span><span class="mtk15">from</span><span class="mtk1"> </span><span class="mtk8">&quot;@mui/material&quot;</span><span class="mtk1">;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk4">const</span><span class="mtk1"> </span><span class="mtk12">theme</span><span class="mtk1"> = </span><span class="mtk11">createTheme</span><span class="mtk1">({</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">typography:</span><span class="mtk1"> {</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">h1:</span><span class="mtk1"> {</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">fontSize:</span><span class="mtk1"> </span><span class="mtk8">&quot;4rem&quot;</span><span class="mtk1">,</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">fontWeight:</span><span class="mtk1"> </span><span class="mtk7">700</span><span class="mtk1">,</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> },</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> },</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1">});</span></span></span> <span class="grvsc-line"><span class="grvsc-source"></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk15">export</span><span class="mtk1"> </span><span class="mtk15">default</span><span class="mtk1"> </span><span class="mtk4">function</span><span class="mtk1"> </span><span class="mtk11">App</span><span class="mtk1">() {</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk15">return</span><span class="mtk1"> (</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk17">&lt;</span><span class="mtk10">ThemeProvider</span><span class="mtk1"> </span><span class="mtk12">theme</span><span class="mtk1">=</span><span class="mtk4">{</span><span class="mtk12">theme</span><span class="mtk4">}</span><span class="mtk17">&gt;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk17">&lt;</span><span class="mtk10">Typography</span><span class="mtk1"> </span><span class="mtk12">variant</span><span class="mtk1">=</span><span class="mtk8">&quot;h1&quot;</span><span class="mtk17">&gt;</span><span class="mtk1">Heading 1</span><span class="mtk17">&lt;/</span><span class="mtk10">Typography</span><span class="mtk17">&gt;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk17">&lt;/</span><span class="mtk10">ThemeProvider</span><span class="mtk17">&gt;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> );</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1">}</span></span></span></code></pre> <div id="MuiTypographyCustomizeVariant" data-code data-height="125px"></div> <p>Using MUI theme for styling and other customizations is always helpful if we want the changes to persist throughout the app.</p> <h3 id="add-new-variant" style="position:relative;"><a href="#add-new-variant" aria-label="add new variant permalink" class="anchor before"><svg aria-hidden="true" focusable="false" height="16" version="1.1" viewBox="0 0 16 16" width="16"><path fill-rule="evenodd" d="M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z"></path></svg></a>Add new variant</h3> <p>Variants are not limited to the ones provided by MUI. We can add custom variants by adding a new key to the <code>typography</code> object.</p> <p>Let’s create a new variant called <code>h7</code> with some custom styles.</p> <pre class="grvsc-container default-dark" data-language="jsx" data-index="4"><code class="grvsc-code"><span class="grvsc-line"><span class="grvsc-source"><span class="mtk15">import</span><span class="mtk1"> </span><span class="mtk12">React</span><span class="mtk1"> </span><span class="mtk15">from</span><span class="mtk1"> </span><span class="mtk8">&quot;react&quot;</span><span class="mtk1">;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk15">import</span><span class="mtk1"> { </span><span class="mtk12">createTheme</span><span class="mtk1">, </span><span class="mtk12">ThemeProvider</span><span class="mtk1">, </span><span class="mtk12">Typography</span><span class="mtk1"> } </span><span class="mtk15">from</span><span class="mtk1"> </span><span class="mtk8">&quot;@mui/material&quot;</span><span class="mtk1">;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk4">const</span><span class="mtk1"> </span><span class="mtk12">theme</span><span class="mtk1"> = </span><span class="mtk11">createTheme</span><span class="mtk1">({</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">typography:</span><span class="mtk1"> {</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">h7:</span><span class="mtk1"> {</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">fontSize:</span><span class="mtk1"> </span><span class="mtk8">&quot;3rem&quot;</span><span class="mtk1">,</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">fontWeight:</span><span class="mtk1"> </span><span class="mtk7">500</span><span class="mtk1">,</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">fontFamily:</span><span class="mtk1"> </span><span class="mtk8">&quot;sans-serif&quot;</span><span class="mtk1">,</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">fontStyle:</span><span class="mtk1"> </span><span class="mtk8">&quot;italic&quot;</span><span class="mtk1">,</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> },</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> },</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1">});</span></span></span> <span class="grvsc-line"><span class="grvsc-source"></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk15">export</span><span class="mtk1"> </span><span class="mtk15">default</span><span class="mtk1"> </span><span class="mtk4">function</span><span class="mtk1"> </span><span class="mtk11">App</span><span class="mtk1">() {</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk15">return</span><span class="mtk1"> (</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk17">&lt;</span><span class="mtk10">ThemeProvider</span><span class="mtk1"> </span><span class="mtk12">theme</span><span class="mtk1">=</span><span class="mtk4">{</span><span class="mtk12">theme</span><span class="mtk4">}</span><span class="mtk17">&gt;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk17">&lt;</span><span class="mtk10">Typography</span><span class="mtk1"> </span><span class="mtk12">variant</span><span class="mtk1">=</span><span class="mtk8">&quot;h7&quot;</span><span class="mtk17">&gt;</span><span class="mtk1">H7 Title</span><span class="mtk17">&lt;/</span><span class="mtk10">Typography</span><span class="mtk17">&gt;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk17">&lt;/</span><span class="mtk10">ThemeProvider</span><span class="mtk17">&gt;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> );</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1">}</span></span></span></code></pre> <div id="MuiTypographyAddVariant" data-code data-height="75px"></div> <p>Now, we have a new variant called <code>h7</code> that we can use anywhere in our app.</p> <p>The default rendered element for any new variant we add will be <code>span</code>. If we want to change the element, we can use <code>variantMapping</code> in the <code>typography</code> object. For example, if we’re going to render the <code>h7</code> variant as a <code>h1</code> element, we can do the following:</p> <pre class="grvsc-container default-dark" data-language="jsx" data-index="5"><code class="grvsc-code"><span class="grvsc-line"><span class="grvsc-source"><span class="mtk1">...</span></span></span> <span class="grvsc-line"><span class="grvsc-source"></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk4">const</span><span class="mtk1"> </span><span class="mtk12">theme</span><span class="mtk1"> = </span><span class="mtk11">createTheme</span><span class="mtk1">({</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">typography:</span><span class="mtk1"> {</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> ...</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> },</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">components:</span><span class="mtk1"> {</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">MuiTypography:</span><span class="mtk1"> {</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">defaultProps:</span><span class="mtk1"> {</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">variantMapping:</span><span class="mtk1"> {</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk3">// Map the new variant to render a &lt;h1&gt; by default</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">h7:</span><span class="mtk1"> </span><span class="mtk8">&#39;h1&#39;</span><span class="mtk1">,</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> },</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> },</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> },</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> },</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1">});</span></span></span> <span class="grvsc-line"><span class="grvsc-source"></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1">...</span></span></span></code></pre> <h3 id="disable-variant" style="position:relative;"><a href="#disable-variant" aria-label="disable variant permalink" class="anchor before"><svg aria-hidden="true" focusable="false" height="16" version="1.1" viewBox="0 0 16 16" width="16"><path fill-rule="evenodd" d="M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z"></path></svg></a>Disable variant</h3> <p>If there are specific variants we don’t want to use, we can disable them by simply applying an <code>undefined</code> value to the variant in the <code>typography</code> object. In the following example, we will disable the <code>caption</code> variant.</p> <pre class="grvsc-container default-dark" data-language="jsx" data-index="6"><code class="grvsc-code"><span class="grvsc-line"><span class="grvsc-source"><span class="mtk15">import</span><span class="mtk1"> </span><span class="mtk12">React</span><span class="mtk1"> </span><span class="mtk15">from</span><span class="mtk1"> </span><span class="mtk8">&quot;react&quot;</span><span class="mtk1">;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk15">import</span><span class="mtk1"> { </span><span class="mtk12">createTheme</span><span class="mtk1">, </span><span class="mtk12">ThemeProvider</span><span class="mtk1">, </span><span class="mtk12">Typography</span><span class="mtk1"> } </span><span class="mtk15">from</span><span class="mtk1"> </span><span class="mtk8">&quot;@mui/material&quot;</span><span class="mtk1">;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk4">const</span><span class="mtk1"> </span><span class="mtk12">theme</span><span class="mtk1"> = </span><span class="mtk11">createTheme</span><span class="mtk1">({</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">typography:</span><span class="mtk1"> {</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">caption:</span><span class="mtk1"> </span><span class="mtk4">undefined</span><span class="mtk1">,</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> },</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1">});</span></span></span> <span class="grvsc-line"><span class="grvsc-source"></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk15">export</span><span class="mtk1"> </span><span class="mtk15">default</span><span class="mtk1"> </span><span class="mtk4">function</span><span class="mtk1"> </span><span class="mtk11">App</span><span class="mtk1">() {</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk15">return</span><span class="mtk1"> (</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk17">&lt;</span><span class="mtk10">ThemeProvider</span><span class="mtk1"> </span><span class="mtk12">theme</span><span class="mtk1">=</span><span class="mtk4">{</span><span class="mtk12">theme</span><span class="mtk4">}</span><span class="mtk17">&gt;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk17">&lt;</span><span class="mtk10">Typography</span><span class="mtk1"> </span><span class="mtk12">variant</span><span class="mtk1">=</span><span class="mtk8">&quot;caption&quot;</span><span class="mtk17">&gt;</span><span class="mtk1">Caption</span><span class="mtk17">&lt;/</span><span class="mtk10">Typography</span><span class="mtk17">&gt;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk17">&lt;/</span><span class="mtk10">ThemeProvider</span><span class="mtk17">&gt;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> );</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1">}</span></span></span></code></pre> <div id="MuiTypographyDisableVariant" data-code data-height="35px"></div> <p>As we can see above, the <code>caption</code> variant no longer has styles applied to it. And we can double-check that by inspecting the element in the browser and looking at the element’s styles.</p> <h2 id="typography-styling" style="position:relative;"><a href="#typography-styling" aria-label="typography styling permalink" class="anchor before"><svg aria-hidden="true" focusable="false" height="16" version="1.1" viewBox="0 0 16 16" width="16"><path fill-rule="evenodd" d="M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z"></path></svg></a>Typography Styling</h2> <p>Since the Typography component is CSS utility component, it supports all system properties. You can use them as props directly on the component with either string values or shorthand access to the theme object.</p> <p>Let’s explore some of the most common ones.</p> <h3 id="color" style="position:relative;"><a href="#color" aria-label="color permalink" class="anchor before"><svg aria-hidden="true" focusable="false" height="16" version="1.1" viewBox="0 0 16 16" width="16"><path fill-rule="evenodd" d="M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z"></path></svg></a>Color</h3> <p>The <code>color</code> prop is used to change the color of the text. It accepts a <code>string</code> value that can be a color name, hex code, RGB, RGBA, or HSL value.</p> <pre class="grvsc-container default-dark" data-language="jsx" data-index="7"><code class="grvsc-code"><span class="grvsc-line"><span class="grvsc-source"><span class="mtk17">&lt;</span><span class="mtk10">Typography</span><span class="mtk1"> </span><span class="mtk12">color</span><span class="mtk1">=</span><span class="mtk8">&quot;#cccccc&quot;</span><span class="mtk17">&gt;</span><span class="mtk1">Light Grey Text</span><span class="mtk17">&lt;/</span><span class="mtk10">Typography</span><span class="mtk17">&gt;</span></span></span></code></pre> <div id="MuiTypographyColor" data-code data-height="35px"></div> <p>The <code>color</code> prop supports the theme colors, which allows us to use colors from the theme palette.</p> <pre class="grvsc-container default-dark" data-language="jsx" data-index="8"><code class="grvsc-code"><span class="grvsc-line"><span class="grvsc-source"><span class="mtk17">&lt;</span><span class="mtk10">Typography</span><span class="mtk1"> </span><span class="mtk12">color</span><span class="mtk1">=</span><span class="mtk8">&quot;primary&quot;</span><span class="mtk17">&gt;</span><span class="mtk1">Primary Text</span><span class="mtk17">&lt;/</span><span class="mtk10">Typography</span><span class="mtk17">&gt;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk17">&lt;</span><span class="mtk10">Typography</span><span class="mtk1"> </span><span class="mtk12">color</span><span class="mtk1">=</span><span class="mtk8">&quot;secondary&quot;</span><span class="mtk17">&gt;</span><span class="mtk1">Secondary Text</span><span class="mtk17">&lt;/</span><span class="mtk10">Typography</span><span class="mtk17">&gt;</span></span></span></code></pre> <div id="MuiTypographyColorTheme" data-code data-height="70px"></div> <p>Using the theme colors is very helpful because we can create and change the color palette only once and use it in multiple places. For example, if we have a specific text color that we want to use throughout the app, we can add it to the <code>theme</code> under the <code>palette</code> object.</p> <pre class="grvsc-container default-dark" data-language="jsx" data-index="9"><code class="grvsc-code"><span class="grvsc-line"><span class="grvsc-source"><span class="mtk15">import</span><span class="mtk1"> { </span><span class="mtk12">createTheme</span><span class="mtk1"> } </span><span class="mtk15">from</span><span class="mtk1"> </span><span class="mtk8">&quot;@mui/material/styles&quot;</span><span class="mtk1">;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk4">const</span><span class="mtk1"> </span><span class="mtk12">theme</span><span class="mtk1"> = </span><span class="mtk11">createTheme</span><span class="mtk1">({</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">palette:</span><span class="mtk1"> {</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">textBlue:</span><span class="mtk1"> </span><span class="mtk8">&quot;#1e88e5&quot;</span><span class="mtk1">,</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> },</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1">});</span></span></span> <span class="grvsc-line"><span class="grvsc-source"></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk4">function</span><span class="mtk1"> </span><span class="mtk11">App</span><span class="mtk1">() {</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk15">return</span><span class="mtk1"> (</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk17">&lt;</span><span class="mtk10">ThemeProvider</span><span class="mtk1"> </span><span class="mtk12">theme</span><span class="mtk1">=</span><span class="mtk4">{</span><span class="mtk12">theme</span><span class="mtk4">}</span><span class="mtk17">&gt;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk17">&lt;</span><span class="mtk10">Typography</span><span class="mtk1"> </span><span class="mtk12">color</span><span class="mtk1">=</span><span class="mtk8">&quot;textBlue&quot;</span><span class="mtk17">&gt;</span><span class="mtk1">Text Blue</span><span class="mtk17">&lt;/</span><span class="mtk10">Typography</span><span class="mtk17">&gt;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk17">&lt;/</span><span class="mtk10">ThemeProvider</span><span class="mtk17">&gt;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> );</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1">}</span></span></span></code></pre> <div id="MuiTypographyColorThemeCustom" data-code data-height="35px"></div> <p>Now, anywhere we need to use the <code>textBlue</code> color, we can apply it to the <code>color</code> prop.</p> <h3 id="font-size" style="position:relative;"><a href="#font-size" aria-label="font size permalink" class="anchor before"><svg aria-hidden="true" focusable="false" height="16" version="1.1" viewBox="0 0 16 16" width="16"><path fill-rule="evenodd" d="M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z"></path></svg></a>Font Size</h3> <p>The <code>fontSize</code> prop is used to change the size of the text. It accepts a <code>string</code> value that can be a pixel value, percentage, em, rem, or any other valid CSS unit.</p> <pre class="grvsc-container default-dark" data-language="jsx" data-index="10"><code class="grvsc-code"><span class="grvsc-line"><span class="grvsc-source"><span class="mtk17">&lt;</span><span class="mtk10">Typography</span><span class="mtk1"> </span><span class="mtk12">fontSize</span><span class="mtk1">=</span><span class="mtk8">&quot;2rem&quot;</span><span class="mtk17">&gt;</span><span class="mtk1">2rem</span><span class="mtk17">&lt;/</span><span class="mtk10">Typography</span><span class="mtk17">&gt;</span></span></span></code></pre> <div id="MuiTypographyFontSize" data-code data-height="65px"></div> <p>We can use the <code>theme</code> to create custom font sizes using the <code>typography</code> object.</p> <pre class="grvsc-container default-dark" data-language="jsx" data-index="11"><code class="grvsc-code"><span class="grvsc-line"><span class="grvsc-source"><span class="mtk15">import</span><span class="mtk1"> </span><span class="mtk12">React</span><span class="mtk1"> </span><span class="mtk15">from</span><span class="mtk1"> </span><span class="mtk8">&quot;react&quot;</span><span class="mtk1">;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk15">import</span><span class="mtk1"> { </span><span class="mtk12">createTheme</span><span class="mtk1">, </span><span class="mtk12">ThemeProvider</span><span class="mtk1">, </span><span class="mtk12">Typography</span><span class="mtk1"> } </span><span class="mtk15">from</span><span class="mtk1"> </span><span class="mtk8">&quot;@mui/material&quot;</span><span class="mtk1">;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk4">const</span><span class="mtk1"> </span><span class="mtk12">theme</span><span class="mtk1"> = </span><span class="mtk11">createTheme</span><span class="mtk1">({</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">typography:</span><span class="mtk1"> {</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">fontSizeSmall:</span><span class="mtk1"> </span><span class="mtk8">&quot;1rem&quot;</span><span class="mtk1">,</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">fontSizeMedium:</span><span class="mtk1"> </span><span class="mtk8">&quot;2rem&quot;</span><span class="mtk1">,</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">fontSizeLarge:</span><span class="mtk1"> </span><span class="mtk8">&quot;3rem&quot;</span><span class="mtk1">,</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> },</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1">});</span></span></span> <span class="grvsc-line"><span class="grvsc-source"></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk15">export</span><span class="mtk1"> </span><span class="mtk15">default</span><span class="mtk1"> </span><span class="mtk4">function</span><span class="mtk1"> </span><span class="mtk11">App</span><span class="mtk1">() {</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk15">return</span><span class="mtk1"> (</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk17">&lt;</span><span class="mtk10">ThemeProvider</span><span class="mtk1"> </span><span class="mtk12">theme</span><span class="mtk1">=</span><span class="mtk4">{</span><span class="mtk12">theme</span><span class="mtk4">}</span><span class="mtk17">&gt;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk17">&lt;</span><span class="mtk10">Typography</span><span class="mtk1"> </span><span class="mtk12">fontSize</span><span class="mtk1">=</span><span class="mtk8">&quot;fontSizeSmall&quot;</span><span class="mtk17">&gt;</span><span class="mtk1">Small</span><span class="mtk17">&lt;/</span><span class="mtk10">Typography</span><span class="mtk17">&gt;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk17">&lt;</span><span class="mtk10">Typography</span><span class="mtk1"> </span><span class="mtk12">fontSize</span><span class="mtk1">=</span><span class="mtk8">&quot;fontSizeMedium&quot;</span><span class="mtk17">&gt;</span><span class="mtk1">Medium</span><span class="mtk17">&lt;/</span><span class="mtk10">Typography</span><span class="mtk17">&gt;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk17">&lt;</span><span class="mtk10">Typography</span><span class="mtk1"> </span><span class="mtk12">fontSize</span><span class="mtk1">=</span><span class="mtk8">&quot;fontSizeLarge&quot;</span><span class="mtk17">&gt;</span><span class="mtk1">Large</span><span class="mtk17">&lt;/</span><span class="mtk10">Typography</span><span class="mtk17">&gt;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk17">&lt;/</span><span class="mtk10">ThemeProvider</span><span class="mtk17">&gt;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> );</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1">}</span></span></span></code></pre> <div id="MuiTypographyFontSizeCustom" data-code data-height="150px"></div> <p>Additionally, we can choose to change the size of the text to an existing variant size.</p> <pre class="grvsc-container default-dark" data-language="jsx" data-index="12"><code class="grvsc-code"><span class="grvsc-line"><span class="grvsc-source"><span class="mtk17">&lt;</span><span class="mtk10">Typography</span><span class="mtk1"> </span><span class="mtk12">fontSize</span><span class="mtk1">=</span><span class="mtk8">&quot;h4.fontSize&quot;</span><span class="mtk17">&gt;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> Some text that is the same size as the h4 variant</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk17">&lt;/</span><span class="mtk10">Typography</span><span class="mtk17">&gt;</span></span></span></code></pre> <div id="MuiTypographyH1FontSize" data-code data-height="100px"></div> <h3 id="font-weight" style="position:relative;"><a href="#font-weight" aria-label="font weight permalink" class="anchor before"><svg aria-hidden="true" focusable="false" height="16" version="1.1" viewBox="0 0 16 16" width="16"><path fill-rule="evenodd" d="M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z"></path></svg></a>Font Weight</h3> <p>The <code>fontWeight</code> prop is used to change the weight of the text. It accepts a <code>string</code> value that can be a number or keyword. For example, the value can be <code>100</code> to <code>900</code> or <code>normal</code>, <code>bold</code>, <code>bolder</code> or <code>lighter</code>.</p> <pre class="grvsc-container default-dark" data-language="jsx" data-index="13"><code class="grvsc-code"><span class="grvsc-line"><span class="grvsc-source"><span class="mtk17">&lt;</span><span class="mtk10">Typography</span><span class="mtk1"> </span><span class="mtk12">fontWeight</span><span class="mtk1">=</span><span class="mtk8">&quot;700&quot;</span><span class="mtk17">&gt;</span><span class="mtk1">Bold</span><span class="mtk17">&lt;/</span><span class="mtk10">Typography</span><span class="mtk17">&gt;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk17">&lt;</span><span class="mtk10">Typography</span><span class="mtk1"> </span><span class="mtk12">fontWeight</span><span class="mtk1">=</span><span class="mtk8">&quot;bold&quot;</span><span class="mtk17">&gt;</span><span class="mtk1">Bold</span><span class="mtk17">&lt;/</span><span class="mtk10">Typography</span><span class="mtk17">&gt;</span></span></span></code></pre> <div id="MuiTypographyFontWeight" data-code data-height="70px"></div> <p>We can use the <code>theme</code> to create custom font weights using the <code>typography</code> object.</p> <pre class="grvsc-container default-dark" data-language="jsx" data-index="14"><code class="grvsc-code"><span class="grvsc-line"><span class="grvsc-source"><span class="mtk15">import</span><span class="mtk1"> </span><span class="mtk12">React</span><span class="mtk1"> </span><span class="mtk15">from</span><span class="mtk1"> </span><span class="mtk8">&quot;react&quot;</span><span class="mtk1">;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk15">import</span><span class="mtk1"> { </span><span class="mtk12">Typography</span><span class="mtk1">, </span><span class="mtk12">createTheme</span><span class="mtk1">, </span><span class="mtk12">ThemeProvider</span><span class="mtk1"> } </span><span class="mtk15">from</span><span class="mtk1"> </span><span class="mtk8">&quot;@mui/material&quot;</span><span class="mtk1">;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk4">const</span><span class="mtk1"> </span><span class="mtk12">theme</span><span class="mtk1"> = </span><span class="mtk11">createTheme</span><span class="mtk1">({</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">typography:</span><span class="mtk1"> {</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">fontWeightRegular:</span><span class="mtk1"> </span><span class="mtk7">400</span><span class="mtk1">,</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">fontWeightMedium:</span><span class="mtk1"> </span><span class="mtk7">700</span><span class="mtk1">,</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">fontWeightBold:</span><span class="mtk1"> </span><span class="mtk7">900</span><span class="mtk1">,</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> },</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1">});</span></span></span> <span class="grvsc-line"><span class="grvsc-source"></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk15">export</span><span class="mtk1"> </span><span class="mtk15">default</span><span class="mtk1"> </span><span class="mtk4">function</span><span class="mtk1"> </span><span class="mtk11">MuiTypographyFontWeightCustom</span><span class="mtk1">() {</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk15">return</span><span class="mtk1"> (</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk17">&lt;</span><span class="mtk10">ThemeProvider</span><span class="mtk1"> </span><span class="mtk12">theme</span><span class="mtk1">=</span><span class="mtk4">{</span><span class="mtk12">theme</span><span class="mtk4">}</span><span class="mtk17">&gt;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk17">&lt;</span><span class="mtk10">Typography</span><span class="mtk1"> </span><span class="mtk12">fontWeight</span><span class="mtk1">=</span><span class="mtk8">&quot;fontWeightRegular&quot;</span><span class="mtk17">&gt;</span><span class="mtk1">Regular</span><span class="mtk17">&lt;/</span><span class="mtk10">Typography</span><span class="mtk17">&gt;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk17">&lt;</span><span class="mtk10">Typography</span><span class="mtk1"> </span><span class="mtk12">fontWeight</span><span class="mtk1">=</span><span class="mtk8">&quot;fontWeightMedium&quot;</span><span class="mtk17">&gt;</span><span class="mtk1">Medium</span><span class="mtk17">&lt;/</span><span class="mtk10">Typography</span><span class="mtk17">&gt;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk17">&lt;</span><span class="mtk10">Typography</span><span class="mtk1"> </span><span class="mtk12">fontWeight</span><span class="mtk1">=</span><span class="mtk8">&quot;fontWeightBold&quot;</span><span class="mtk17">&gt;</span><span class="mtk1">Bold</span><span class="mtk17">&lt;/</span><span class="mtk10">Typography</span><span class="mtk17">&gt;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk17">&lt;/</span><span class="mtk10">ThemeProvider</span><span class="mtk17">&gt;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> );</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1">}</span></span></span></code></pre> <div id="MuiTypographyFontWeightCustom" data-code data-height="130px"></div> <p>Additionally, we can choose to change the font weight of the text to an existing variant weight.</p> <pre class="grvsc-container default-dark" data-language="jsx" data-index="15"><code class="grvsc-code"><span class="grvsc-line"><span class="grvsc-source"><span class="mtk17">&lt;</span><span class="mtk10">Typography</span><span class="mtk1"> </span><span class="mtk12">fontWeight</span><span class="mtk1">=</span><span class="mtk8">&quot;h1.fontWeight&quot;</span><span class="mtk17">&gt;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> Some text that is the same weight as the h1 variant</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk17">&lt;/</span><span class="mtk10">Typography</span><span class="mtk17">&gt;</span></span></span></code></pre> <div id="MuiTypographyH1FontWeight" data-code data-height="35px"></div> <h3 id="font-family" style="position:relative;"><a href="#font-family" aria-label="font family permalink" class="anchor before"><svg aria-hidden="true" focusable="false" height="16" version="1.1" viewBox="0 0 16 16" width="16"><path fill-rule="evenodd" d="M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z"></path></svg></a>Font Family</h3> <p>The <code>fontFamily</code> prop is used to change the text’s font family. It accepts a <code>string</code> value that can be a font family name, generic family name, or a comma-separated list of font family names.</p> <pre class="grvsc-container default-dark" data-language="jsx" data-index="16"><code class="grvsc-code"><span class="grvsc-line"><span class="grvsc-source"><span class="mtk17">&lt;</span><span class="mtk10">Typography</span><span class="mtk1"> </span><span class="mtk12">fontFamily</span><span class="mtk1">=</span><span class="mtk8">&quot;monospace&quot;</span><span class="mtk17">&gt;</span><span class="mtk1">Monospace Font</span><span class="mtk17">&lt;/</span><span class="mtk10">Typography</span><span class="mtk17">&gt;</span></span></span></code></pre> <div id="MuiTypographyFontFamily" data-code data-height="35px"></div> <p>We can use the <code>theme</code> to create custom font families using the <code>typography</code> object.</p> <pre class="grvsc-container default-dark" data-language="jsx" data-index="17"><code class="grvsc-code"><span class="grvsc-line"><span class="grvsc-source"><span class="mtk15">import</span><span class="mtk1"> </span><span class="mtk12">React</span><span class="mtk1"> </span><span class="mtk15">from</span><span class="mtk1"> </span><span class="mtk8">&quot;react&quot;</span><span class="mtk1">;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk15">import</span><span class="mtk1"> { </span><span class="mtk12">Typography</span><span class="mtk1">, </span><span class="mtk12">createTheme</span><span class="mtk1">, </span><span class="mtk12">ThemeProvider</span><span class="mtk1"> } </span><span class="mtk15">from</span><span class="mtk1"> </span><span class="mtk8">&quot;@mui/material&quot;</span><span class="mtk1">;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk4">const</span><span class="mtk1"> </span><span class="mtk12">theme</span><span class="mtk1"> = </span><span class="mtk11">createTheme</span><span class="mtk1">({</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">typography:</span><span class="mtk1"> {</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">fontFamilyPrimary:</span><span class="mtk1"> </span><span class="mtk8">&quot;monospace&quot;</span><span class="mtk1">,</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">fontFamilySecondary:</span><span class="mtk1"> </span><span class="mtk8">&quot;Arial&quot;</span><span class="mtk1">,</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> },</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1">});</span></span></span> <span class="grvsc-line"><span class="grvsc-source"></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk15">export</span><span class="mtk1"> </span><span class="mtk15">default</span><span class="mtk1"> </span><span class="mtk4">function</span><span class="mtk1"> </span><span class="mtk11">MuiTypographyFontFamilyCustom</span><span class="mtk1">() {</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk15">return</span><span class="mtk1"> (</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk17">&lt;</span><span class="mtk10">ThemeProvider</span><span class="mtk1"> </span><span class="mtk12">theme</span><span class="mtk1">=</span><span class="mtk4">{</span><span class="mtk12">theme</span><span class="mtk4">}</span><span class="mtk17">&gt;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk17">&lt;</span><span class="mtk10">Typography</span><span class="mtk1"> </span><span class="mtk12">fontFamily</span><span class="mtk1">=</span><span class="mtk8">&quot;fontFamilyPrimary&quot;</span><span class="mtk17">&gt;</span><span class="mtk1">Primary Font</span><span class="mtk17">&lt;/</span><span class="mtk10">Typography</span><span class="mtk17">&gt;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk17">&lt;</span><span class="mtk10">Typography</span><span class="mtk1"> </span><span class="mtk12">fontFamily</span><span class="mtk1">=</span><span class="mtk8">&quot;fontFamilySecondary&quot;</span><span class="mtk17">&gt;</span><span class="mtk1">Secondary Font</span><span class="mtk17">&lt;/</span><span class="mtk10">Typography</span><span class="mtk17">&gt;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk17">&lt;/</span><span class="mtk10">ThemeProvider</span><span class="mtk17">&gt;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> );</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1">}</span></span></span></code></pre> <div id="MuiTypographyFontFamilyCustom" data-code data-height="70px"></div> <p>Additionally, we can change the text’s font family to an existing variant font family.</p> <pre class="grvsc-container default-dark" data-language="jsx" data-index="18"><code class="grvsc-code"><span class="grvsc-line"><span class="grvsc-source"><span class="mtk17">&lt;</span><span class="mtk10">Typography</span><span class="mtk1"> </span><span class="mtk12">fontFamily</span><span class="mtk1">=</span><span class="mtk8">&quot;h1.fontFamily&quot;</span><span class="mtk17">&gt;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> Some text that is the same family as the h1 variant</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk17">&lt;/</span><span class="mtk10">Typography</span><span class="mtk17">&gt;</span></span></span></code></pre> <div id="MuiTypographyH1FontFamily" data-code data-height="35px"></div> <h3 id="text-align" style="position:relative;"><a href="#text-align" aria-label="text align permalink" class="anchor before"><svg aria-hidden="true" focusable="false" height="16" version="1.1" viewBox="0 0 16 16" width="16"><path fill-rule="evenodd" d="M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z"></path></svg></a>Text Align</h3> <p>The <code>textAlign</code> prop is used to change the alignment of the text. It accepts a <code>string</code> value and can be one of the following: <code>left</code>, <code>center</code>, <code>right</code>, <code>initial</code>, <code>inherit</code>, or <code>unset</code>.</p> <pre class="grvsc-container default-dark" data-language="jsx" data-index="19"><code class="grvsc-code"><span class="grvsc-line"><span class="grvsc-source"><span class="mtk17">&lt;</span><span class="mtk10">Typography</span><span class="mtk1"> </span><span class="mtk12">textAlign</span><span class="mtk1">=</span><span class="mtk8">&quot;left&quot;</span><span class="mtk17">&gt;</span><span class="mtk1">Left</span><span class="mtk17">&lt;/</span><span class="mtk10">Typography</span><span class="mtk17">&gt;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk17">&lt;</span><span class="mtk10">Typography</span><span class="mtk1"> </span><span class="mtk12">textAlign</span><span class="mtk1">=</span><span class="mtk8">&quot;center&quot;</span><span class="mtk17">&gt;</span><span class="mtk1">Center</span><span class="mtk17">&lt;/</span><span class="mtk10">Typography</span><span class="mtk17">&gt;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk17">&lt;</span><span class="mtk10">Typography</span><span class="mtk1"> </span><span class="mtk12">textAlign</span><span class="mtk1">=</span><span class="mtk8">&quot;right&quot;</span><span class="mtk17">&gt;</span><span class="mtk1">Right</span><span class="mtk17">&lt;/</span><span class="mtk10">Typography</span><span class="mtk17">&gt;</span></span></span></code></pre> <div id="MuiTypographyTextAlign" data-code data-height="150px"></div> <h3 id="letter-spacing" style="position:relative;"><a href="#letter-spacing" aria-label="letter spacing permalink" class="anchor before"><svg aria-hidden="true" focusable="false" height="16" version="1.1" viewBox="0 0 16 16" width="16"><path fill-rule="evenodd" d="M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z"></path></svg></a>Letter Spacing</h3> <p>The <code>letterSpacing</code> prop is used to change the spacing between letters. It accepts a <code>string</code> value that can be a pixel value, percentage, em, rem, or any other valid CSS unit.</p> <pre class="grvsc-container default-dark" data-language="jsx" data-index="20"><code class="grvsc-code"><span class="grvsc-line"><span class="grvsc-source"><span class="mtk17">&lt;</span><span class="mtk10">Typography</span><span class="mtk1"> </span><span class="mtk12">letterSpacing</span><span class="mtk1">=</span><span class="mtk8">&quot;2px&quot;</span><span class="mtk17">&gt;</span><span class="mtk1">Letter Spacing</span><span class="mtk17">&lt;/</span><span class="mtk10">Typography</span><span class="mtk17">&gt;</span></span></span></code></pre> <div id="MuiTypographyLetterSpacing" data-code data-height="35px"></div> <p>We can use the <code>theme</code> to create custom letter spacing using the <code>typography</code> object.</p> <pre class="grvsc-container default-dark" data-language="jsx" data-index="21"><code class="grvsc-code"><span class="grvsc-line"><span class="grvsc-source"><span class="mtk15">import</span><span class="mtk1"> </span><span class="mtk12">React</span><span class="mtk1"> </span><span class="mtk15">from</span><span class="mtk1"> </span><span class="mtk8">&quot;react&quot;</span><span class="mtk1">;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk15">import</span><span class="mtk1"> { </span><span class="mtk12">createTheme</span><span class="mtk1">, </span><span class="mtk12">ThemeProvider</span><span class="mtk1">, </span><span class="mtk12">Typography</span><span class="mtk1"> } </span><span class="mtk15">from</span><span class="mtk1"> </span><span class="mtk8">&quot;@mui/material&quot;</span><span class="mtk1">;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk4">const</span><span class="mtk1"> </span><span class="mtk12">theme</span><span class="mtk1"> = </span><span class="mtk11">createTheme</span><span class="mtk1">({</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">typography:</span><span class="mtk1"> {</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">letterSpacingSmall:</span><span class="mtk1"> </span><span class="mtk8">&quot;1px&quot;</span><span class="mtk1">,</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">letterSpacingMedium:</span><span class="mtk1"> </span><span class="mtk8">&quot;2px&quot;</span><span class="mtk1">,</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">letterSpacingLarge:</span><span class="mtk1"> </span><span class="mtk8">&quot;3px&quot;</span><span class="mtk1">,</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> },</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1">});</span></span></span> <span class="grvsc-line"><span class="grvsc-source"></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk15">export</span><span class="mtk1"> </span><span class="mtk15">default</span><span class="mtk1"> </span><span class="mtk4">function</span><span class="mtk1"> </span><span class="mtk11">MuiTypographyLetterSpacingCustom</span><span class="mtk1">() {</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk15">return</span><span class="mtk1"> (</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk17">&lt;</span><span class="mtk10">ThemeProvider</span><span class="mtk1"> </span><span class="mtk12">theme</span><span class="mtk1">=</span><span class="mtk4">{</span><span class="mtk12">theme</span><span class="mtk4">}</span><span class="mtk17">&gt;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk17">&lt;</span><span class="mtk10">Typography</span><span class="mtk1"> </span><span class="mtk12">letterSpacing</span><span class="mtk1">=</span><span class="mtk4">{</span><span class="mtk12">theme</span><span class="mtk1">.</span><span class="mtk12">typography</span><span class="mtk1">.</span><span class="mtk12">letterSpacingSmall</span><span class="mtk4">}</span><span class="mtk17">&gt;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> Small</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk17">&lt;/</span><span class="mtk10">Typography</span><span class="mtk17">&gt;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk17">&lt;</span><span class="mtk10">Typography</span><span class="mtk1"> </span><span class="mtk12">letterSpacing</span><span class="mtk1">=</span><span class="mtk4">{</span><span class="mtk12">theme</span><span class="mtk1">.</span><span class="mtk12">typography</span><span class="mtk1">.</span><span class="mtk12">letterSpacingMedium</span><span class="mtk4">}</span><span class="mtk17">&gt;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> Medium</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk17">&lt;/</span><span class="mtk10">Typography</span><span class="mtk17">&gt;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk17">&lt;</span><span class="mtk10">Typography</span><span class="mtk1"> </span><span class="mtk12">letterSpacing</span><span class="mtk1">=</span><span class="mtk4">{</span><span class="mtk12">theme</span><span class="mtk1">.</span><span class="mtk12">typography</span><span class="mtk1">.</span><span class="mtk12">letterSpacingLarge</span><span class="mtk4">}</span><span class="mtk17">&gt;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> Large</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk17">&lt;/</span><span class="mtk10">Typography</span><span class="mtk17">&gt;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk17">&lt;/</span><span class="mtk10">ThemeProvider</span><span class="mtk17">&gt;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> );</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1">}</span></span></span></code></pre> <div id="MuiTypographyLetterSpacingCustom" data-code data-height="150px"></div> <p>Additionally, we can choose to change the spacing between letters to an existing variant spacing.</p> <pre class="grvsc-container default-dark" data-language="jsx" data-index="22"><code class="grvsc-code"><span class="grvsc-line"><span class="grvsc-source"><span class="mtk17">&lt;</span><span class="mtk10">Typography</span><span class="mtk1"> </span><span class="mtk12">letterSpacing</span><span class="mtk1">=</span><span class="mtk4">{</span><span class="mtk12">theme</span><span class="mtk1"> </span><span class="mtk4">=&gt;</span><span class="mtk1"> </span><span class="mtk12">theme</span><span class="mtk1">.</span><span class="mtk12">typography</span><span class="mtk1">.</span><span class="mtk12">h1</span><span class="mtk1">.</span><span class="mtk12">letterSpacing</span><span class="mtk4">}</span><span class="mtk17">&gt;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> Some text that has the same letter spacing as the h1 variant</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk17">&lt;/</span><span class="mtk10">Typography</span><span class="mtk17">&gt;</span></span></span></code></pre> <div id="MuiTypographyH1LetterSpacing" data-code data-height="35px"></div> <p>Note, unlike the other style props, the <code>letterSpacing</code> does not support shorthand access to the theme object. We must pass a function to the prop and use the full path to get the value.</p> <h3 id="line-height" style="position:relative;"><a href="#line-height" aria-label="line height permalink" class="anchor before"><svg aria-hidden="true" focusable="false" height="16" version="1.1" viewBox="0 0 16 16" width="16"><path fill-rule="evenodd" d="M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z"></path></svg></a>Line Height</h3> <p>The <code>lineHeight</code> prop is used to change the height of each line of text. It accepts a <code>string</code> value that can be a pixel value, percentage, em, rem, or any other valid CSS unit.</p> <pre class="grvsc-container default-dark" data-language="jsx" data-index="23"><code class="grvsc-code"><span class="grvsc-line"><span class="grvsc-source"><span class="mtk17">&lt;</span><span class="mtk10">Typography</span><span class="mtk1"> </span><span class="mtk12">lineHeight</span><span class="mtk1">=</span><span class="mtk8">&quot;2rem&quot;</span><span class="mtk17">&gt;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> Lorem ipsum dolor sit amet, consectetur adipiscing elit. Nulla vehicula congue</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> convallis. Cras mollis imperdiet quam, vitae euismod nisi fringilla sed.</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk17">&lt;/</span><span class="mtk10">Typography</span><span class="mtk17">&gt;</span></span></span></code></pre> <div id="MuiTypographyLineHeight" data-code data-height="70px"></div> <p>We can use the <code>theme</code> to create custom line heights using the <code>typography</code> object.</p> <pre class="grvsc-container default-dark" data-language="jsx" data-index="24"><code class="grvsc-code"><span class="grvsc-line"><span class="grvsc-source"><span class="mtk15">import</span><span class="mtk1"> </span><span class="mtk12">React</span><span class="mtk1"> </span><span class="mtk15">from</span><span class="mtk1"> </span><span class="mtk8">&quot;react&quot;</span><span class="mtk1">;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk15">import</span><span class="mtk1"> { </span><span class="mtk12">Typography</span><span class="mtk1">, </span><span class="mtk12">createTheme</span><span class="mtk1">, </span><span class="mtk12">ThemeProvider</span><span class="mtk1"> } </span><span class="mtk15">from</span><span class="mtk1"> </span><span class="mtk8">&quot;@mui/material&quot;</span><span class="mtk1">;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk4">const</span><span class="mtk1"> </span><span class="mtk12">theme</span><span class="mtk1"> = </span><span class="mtk11">createTheme</span><span class="mtk1">({</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">typography:</span><span class="mtk1"> {</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">lineHeightSmall:</span><span class="mtk1"> </span><span class="mtk8">&quot;1rem&quot;</span><span class="mtk1">,</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">lineHeightMedium:</span><span class="mtk1"> </span><span class="mtk8">&quot;2rem&quot;</span><span class="mtk1">,</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">lineHeightLarge:</span><span class="mtk1"> </span><span class="mtk8">&quot;3rem&quot;</span><span class="mtk1">,</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> },</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1">});</span></span></span> <span class="grvsc-line"><span class="grvsc-source"></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk15">export</span><span class="mtk1"> </span><span class="mtk15">default</span><span class="mtk1"> </span><span class="mtk4">function</span><span class="mtk1"> </span><span class="mtk11">MuiTypographyLineHeightCustom</span><span class="mtk1">() {</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk15">return</span><span class="mtk1"> (</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk17">&lt;</span><span class="mtk10">ThemeProvider</span><span class="mtk1"> </span><span class="mtk12">theme</span><span class="mtk1">=</span><span class="mtk4">{</span><span class="mtk12">theme</span><span class="mtk4">}</span><span class="mtk17">&gt;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk17">&lt;</span><span class="mtk10">Typography</span><span class="mtk1"> </span><span class="mtk12">lineHeight</span><span class="mtk1">=</span><span class="mtk4">{</span><span class="mtk12">theme</span><span class="mtk1">.</span><span class="mtk12">typography</span><span class="mtk1">.</span><span class="mtk12">lineHeightSmall</span><span class="mtk4">}</span><span class="mtk17">&gt;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> Small</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk17">&lt;/</span><span class="mtk10">Typography</span><span class="mtk17">&gt;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk17">&lt;</span><span class="mtk10">Typography</span><span class="mtk1"> </span><span class="mtk12">lineHeight</span><span class="mtk1">=</span><span class="mtk4">{</span><span class="mtk12">theme</span><span class="mtk1">.</span><span class="mtk12">typography</span><span class="mtk1">.</span><span class="mtk12">lineHeightMedium</span><span class="mtk4">}</span><span class="mtk17">&gt;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> Medium</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk17">&lt;/</span><span class="mtk10">Typography</span><span class="mtk17">&gt;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk17">&lt;</span><span class="mtk10">Typography</span><span class="mtk1"> </span><span class="mtk12">lineHeight</span><span class="mtk1">=</span><span class="mtk4">{</span><span class="mtk12">theme</span><span class="mtk1">.</span><span class="mtk12">typography</span><span class="mtk1">.</span><span class="mtk12">lineHeightLarge</span><span class="mtk4">}</span><span class="mtk17">&gt;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> Large</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk17">&lt;/</span><span class="mtk10">Typography</span><span class="mtk17">&gt;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk17">&lt;/</span><span class="mtk10">ThemeProvider</span><span class="mtk17">&gt;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> );</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1">}</span></span></span></code></pre> <div id="MuiTypographyLineHeightCustom" data-code data-height="150px"></div> <p>Additionally, we can choose to change the line height of the text to an existing variant line height.</p> <pre class="grvsc-container default-dark" data-language="jsx" data-index="25"><code class="grvsc-code"><span class="grvsc-line"><span class="grvsc-source"><span class="mtk17">&lt;</span><span class="mtk10">Typography</span><span class="mtk1"> </span><span class="mtk12">lineHeight</span><span class="mtk1">=</span><span class="mtk4">{</span><span class="mtk12">theme</span><span class="mtk1"> </span><span class="mtk4">=&gt;</span><span class="mtk1"> </span><span class="mtk12">theme</span><span class="mtk1">.</span><span class="mtk12">typography</span><span class="mtk1">.</span><span class="mtk12">h1</span><span class="mtk1">.</span><span class="mtk12">lineHeight</span><span class="mtk4">}</span><span class="mtk17">&gt;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> Lorem ipsum dolor sit amet, consectetur adipiscing elit. Nulla vehicula congue</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> convallis. Cras mollis imperdiet quam, vitae euismod nisi fringilla sed.</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk17">&lt;/</span><span class="mtk10">Typography</span><span class="mtk17">&gt;</span></span></span></code></pre> <div id="MuiTypographyH1LineHeight" data-code data-height="70px"></div> <p>Note, unlike the other style props, the <code>lineHeight</code> does not support shorthand access to the theme object. We must pass a function to the prop and use the full path to get the value.</p> <h2 id="additional-styling" style="position:relative;"><a href="#additional-styling" aria-label="additional styling permalink" class="anchor before"><svg aria-hidden="true" focusable="false" height="16" version="1.1" viewBox="0 0 16 16" width="16"><path fill-rule="evenodd" d="M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z"></path></svg></a>Additional Styling</h2> <p>The Typography component props don’t support all CSS properties, so alternatively, we can use the <code>sx</code> prop to apply any CSS styles. Let’s take an example that combines all the styles we covered earlier with some additions, including the <code>text-shadow</code> property.</p> <pre class="grvsc-container default-dark" data-language="jsx" data-index="26"><code class="grvsc-code"><span class="grvsc-line"><span class="grvsc-source"><span class="mtk17">&lt;</span><span class="mtk10">Typography</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">sx</span><span class="mtk1">=</span><span class="mtk4">{</span><span class="mtk1">{</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">color:</span><span class="mtk1"> </span><span class="mtk8">&quot;#cccccc&quot;</span><span class="mtk1">,</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">fontSize:</span><span class="mtk1"> </span><span class="mtk8">&quot;20px&quot;</span><span class="mtk1">,</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">fontWeight:</span><span class="mtk1"> </span><span class="mtk7">700</span><span class="mtk1">,</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">fontFamily:</span><span class="mtk1"> </span><span class="mtk8">&quot;Roboto&quot;</span><span class="mtk1">,</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">textAlign:</span><span class="mtk1"> </span><span class="mtk8">&quot;center&quot;</span><span class="mtk1">,</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">letterSpacing:</span><span class="mtk1"> </span><span class="mtk8">&quot;2px&quot;</span><span class="mtk1">,</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">lineHeight:</span><span class="mtk1"> </span><span class="mtk8">&quot;2rem&quot;</span><span class="mtk1">,</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">textTransform:</span><span class="mtk1"> </span><span class="mtk8">&quot;uppercase&quot;</span><span class="mtk1">,</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">textShadow:</span><span class="mtk1"> </span><span class="mtk8">&quot;1px 1px 2px black, 0 0 1em blue, 0 0 0.2em&quot;</span><span class="mtk1">,</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">width:</span><span class="mtk1"> </span><span class="mtk8">&quot;fit-content&quot;</span><span class="mtk1">,</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">backgroundColor:</span><span class="mtk1"> </span><span class="mtk8">&quot;#ccc&quot;</span><span class="mtk1">,</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">padding:</span><span class="mtk1"> </span><span class="mtk8">&quot;5px&quot;</span><span class="mtk1">,</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> }</span><span class="mtk4">}</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk17">&gt;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> Custom Text Styling</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk17">&lt;/</span><span class="mtk10">Typography</span><span class="mtk17">&gt;</span></span></span></code></pre> <div id="MuiTypographySx" data-code data-height="50px"></div> <p>We can also apply the styles above as a new variant. Let’s create a new variant called <code>fancy</code> with the latest styles.</p> <pre class="grvsc-container default-dark" data-language="jsx" data-index="27"><code class="grvsc-code"><span class="grvsc-line"><span class="grvsc-source"><span class="mtk15">import</span><span class="mtk1"> </span><span class="mtk12">React</span><span class="mtk1"> </span><span class="mtk15">from</span><span class="mtk1"> </span><span class="mtk8">&quot;react&quot;</span><span class="mtk1">;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk15">import</span><span class="mtk1"> { </span><span class="mtk12">Typography</span><span class="mtk1">, </span><span class="mtk12">createTheme</span><span class="mtk1">, </span><span class="mtk12">ThemeProvider</span><span class="mtk1"> } </span><span class="mtk15">from</span><span class="mtk1"> </span><span class="mtk8">&quot;@mui/material&quot;</span><span class="mtk1">;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk4">const</span><span class="mtk1"> </span><span class="mtk12">theme</span><span class="mtk1"> = </span><span class="mtk11">createTheme</span><span class="mtk1">({</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">typography:</span><span class="mtk1"> {</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">fancy:</span><span class="mtk1"> {</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">color:</span><span class="mtk1"> </span><span class="mtk8">&quot;#cccccc&quot;</span><span class="mtk1">,</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">fontSize:</span><span class="mtk1"> </span><span class="mtk8">&quot;20px&quot;</span><span class="mtk1">,</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">fontWeight:</span><span class="mtk1"> </span><span class="mtk7">700</span><span class="mtk1">,</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">fontFamily:</span><span class="mtk1"> </span><span class="mtk8">&quot;Roboto&quot;</span><span class="mtk1">,</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">textAlign:</span><span class="mtk1"> </span><span class="mtk8">&quot;center&quot;</span><span class="mtk1">,</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">letterSpacing:</span><span class="mtk1"> </span><span class="mtk8">&quot;2px&quot;</span><span class="mtk1">,</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">lineHeight:</span><span class="mtk1"> </span><span class="mtk8">&quot;2rem&quot;</span><span class="mtk1">,</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">textTransform:</span><span class="mtk1"> </span><span class="mtk8">&quot;uppercase&quot;</span><span class="mtk1">,</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">textShadow:</span><span class="mtk1"> </span><span class="mtk8">&quot;1px 1px 2px black, 0 0 1em blue, 0 0 0.2em&quot;</span><span class="mtk1">,</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">width:</span><span class="mtk1"> </span><span class="mtk8">&quot;fit-content&quot;</span><span class="mtk1">,</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">backgroundColor:</span><span class="mtk1"> </span><span class="mtk8">&quot;#ccc&quot;</span><span class="mtk1">,</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">padding:</span><span class="mtk1"> </span><span class="mtk8">&quot;5px&quot;</span><span class="mtk1">,</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> },</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> },</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1">});</span></span></span> <span class="grvsc-line"><span class="grvsc-source"></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk15">export</span><span class="mtk1"> </span><span class="mtk15">default</span><span class="mtk1"> </span><span class="mtk4">function</span><span class="mtk1"> </span><span class="mtk11">MuiTypographySxVariant</span><span class="mtk1">() {</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk15">return</span><span class="mtk1"> (</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk17">&lt;</span><span class="mtk10">ThemeProvider</span><span class="mtk1"> </span><span class="mtk12">theme</span><span class="mtk1">=</span><span class="mtk4">{</span><span class="mtk12">theme</span><span class="mtk4">}</span><span class="mtk17">&gt;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk17">&lt;</span><span class="mtk10">Typography</span><span class="mtk1"> </span><span class="mtk12">variant</span><span class="mtk1">=</span><span class="mtk8">&quot;fancy&quot;</span><span class="mtk17">&gt;</span><span class="mtk1">Custom Text Styling</span><span class="mtk17">&lt;/</span><span class="mtk10">Typography</span><span class="mtk17">&gt;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk17">&lt;/</span><span class="mtk10">ThemeProvider</span><span class="mtk17">&gt;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> );</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1">}</span></span></span></code></pre> <div id="MuiTypographySxVariant" data-code data-height="50px"></div> <p>Finally, MUI Typography can be used as a utility to other components. For example, we can create a <code>Box</code> component and apply a <code>typography</code> style using any defined variants.</p> <pre class="grvsc-container default-dark" data-language="jsx" data-index="28"><code class="grvsc-code"><span class="grvsc-line"><span class="grvsc-source"><span class="mtk17">&lt;</span><span class="mtk10">Box</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">component</span><span class="mtk1">=</span><span class="mtk8">&quot;span&quot;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">sx</span><span class="mtk1">=</span><span class="mtk4">{</span><span class="mtk1">{</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">typography:</span><span class="mtk1"> </span><span class="mtk8">&quot;h4&quot;</span><span class="mtk1">,</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">color:</span><span class="mtk1"> </span><span class="mtk8">&quot;primary.main&quot;</span><span class="mtk1">,</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> }</span><span class="mtk4">}</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk17">&gt;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> Box Typography</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk17">&lt;/</span><span class="mtk10">Box</span><span class="mtk17">&gt;</span></span></span></code></pre> <div id="MuiTypographyBox" data-code data-height="100px"></div> <p>This will render a <code>span</code> element with the <code>h4</code> variant styles. So, if we inspect the element in the browser, we can see that the <code>span</code> element has a predefined set of styles.</p> <pre class="grvsc-container default-dark" data-language="css" data-index="29"><code class="grvsc-code"><span class="grvsc-line"><span class="grvsc-source"><span class="mtk4">font-family</span><span class="mtk1">: &quot;Roboto&quot;, &quot;Helvetica&quot;, &quot;Arial&quot;, </span><span class="mtk4">sans-serif</span><span class="mtk1">;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk4">font-weight</span><span class="mtk1">: 400;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk4">font-size</span><span class="mtk1">: 2.125rem;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk4">line-height</span><span class="mtk1">: 1.235;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk4">letter-spacing</span><span class="mtk1">: 0.00735em;</span></span></span></code></pre> <h2 id="summary" style="position:relative;"><a href="#summary" aria-label="summary permalink" class="anchor before"><svg aria-hidden="true" focusable="false" height="16" version="1.1" viewBox="0 0 16 16" width="16"><path fill-rule="evenodd" d="M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z"></path></svg></a>Summary</h2> <p>Working with MUI Typography is easy and offers a lot of flexibility. Here are some of the key takeaways from this tutorial:</p> <ul> <li>We can use the <code>variant</code> prop to render a predefined set of HTML elements.</li> <li>We can customize the predefined variants using the theme in the <code>typography</code> object.</li> <li>We can directly modify the color, font size, font weight, font family, text align, letter spacing, and line height styles from the component props.</li> <li>We can use the <code>sx</code> prop to apply any CSS styles to the text.</li> <li>We can apply the <code>typography</code> styles on other components.</li> </ul> <p>Bye for now 👋</p> <style class="grvsc-styles"> .grvsc-container { overflow: auto; position: relative; -webkit-overflow-scrolling: touch; padding-top: 1rem; padding-top: var(--grvsc-padding-top, var(--grvsc-padding-v, 1rem)); padding-bottom: 1rem; padding-bottom: var(--grvsc-padding-bottom, var(--grvsc-padding-v, 1rem)); border-radius: 8px; border-radius: var(--grvsc-border-radius, 8px); font-feature-settings: normal; line-height: 1.4; } .grvsc-code { display: table; } .grvsc-line { display: table-row; box-sizing: border-box; width: 100%; position: relative; } .grvsc-line > * { position: relative; } .grvsc-gutter-pad { display: table-cell; padding-left: 0.75rem; padding-left: calc(var(--grvsc-padding-left, var(--grvsc-padding-h, 1.5rem)) / 2); } .grvsc-gutter { display: table-cell; -webkit-user-select: none; -moz-user-select: none; user-select: none; } .grvsc-gutter::before { content: attr(data-content); } .grvsc-source { display: table-cell; padding-left: 1.5rem; padding-left: var(--grvsc-padding-left, var(--grvsc-padding-h, 1.5rem)); padding-right: 1.5rem; padding-right: var(--grvsc-padding-right, var(--grvsc-padding-h, 1.5rem)); } .grvsc-source:empty::after { content: ' '; -webkit-user-select: none; -moz-user-select: none; user-select: none; } .grvsc-gutter + .grvsc-source { padding-left: 0.75rem; padding-left: calc(var(--grvsc-padding-left, var(--grvsc-padding-h, 1.5rem)) / 2); } /* Line transformer styles */ .grvsc-has-line-highlighting > .grvsc-code > .grvsc-line::before { content: ' '; position: absolute; width: 100%; } .grvsc-line-diff-add::before { background-color: var(--grvsc-line-diff-add-background-color, rgba(0, 255, 60, 0.2)); } .grvsc-line-diff-del::before { background-color: var(--grvsc-line-diff-del-background-color, rgba(255, 0, 20, 0.2)); } .grvsc-line-number { padding: 0 2px; text-align: right; opacity: 0.7; } .default-dark { background-color: #1E1E1E; color: #D4D4D4; } .default-dark .mtk17 { color: #808080; } .default-dark .mtk10 { color: #4EC9B0; } .default-dark .mtk1 { color: #D4D4D4; } .default-dark .mtk4 { color: #569CD6; } .default-dark .mtk14 { color: #F44747; } .default-dark .mtk12 { color: #9CDCFE; } .default-dark .mtk8 { color: #CE9178; } .default-dark .mtk15 { color: #C586C0; } .default-dark .mtk11 { color: #DCDCAA; } .default-dark .mtk7 { color: #B5CEA8; } .default-dark .mtk3 { color: #6A9955; } .default-dark .grvsc-line-highlighted::before { background-color: var(--grvsc-line-highlighted-background-color, rgba(255, 255, 255, 0.1)); box-shadow: inset var(--grvsc-line-highlighted-border-width, 4px) 0 0 0 var(--grvsc-line-highlighted-border-color, rgba(255, 255, 255, 0.5)); } </style><![CDATA[Spacing, Padding, and Margin with Material UI (MUI)]]>https://muhimasri.commui-spacinghttps://muhimasri.commui-spacing<p>Applying spacing between components is an essential part of building a UI. One common way is to use CSS padding and margin. MUI spacing provides an efficient way to apply inline padding and margin in components and a theme helper function that allows us to systemize spacing throughout the application.</p> <p>This tutorial will explore the MUI’s approach to creating spacing and customizing it to fit our design system.</p> <h2 id="inline-padding-and-margin" style="position:relative;"><a href="#inline-padding-and-margin" aria-label="inline padding and margin permalink" class="anchor before"><svg aria-hidden="true" focusable="false" height="16" version="1.1" viewBox="0 0 16 16" width="16"><path fill-rule="evenodd" d="M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z"></path></svg></a>Inline Padding and Margin</h2> <p>MUI <code>sx</code> prop allows us to apply padding and margin to our components with shorthand properties.</p> <p>For example, when using the normal padding syntax, we would write:</p> <pre class="grvsc-container default-dark" data-language="jsx" data-index="0"><code class="grvsc-code"><span class="grvsc-line"><span class="grvsc-source"><span class="mtk17">&lt;</span><span class="mtk10">Box</span><span class="mtk1"> </span><span class="mtk12">sx</span><span class="mtk1">=</span><span class="mtk4">{</span><span class="mtk1">{ </span><span class="mtk12">paddingRight:</span><span class="mtk1"> </span><span class="mtk8">&quot;16px&quot;</span><span class="mtk1"> }</span><span class="mtk4">}</span><span class="mtk1"> </span><span class="mtk17">/&gt;</span></span></span></code></pre> <p>But with the shorthand syntax, we can write:</p> <pre class="grvsc-container default-dark" data-language="jsx" data-index="1"><code class="grvsc-code"><span class="grvsc-line"><span class="grvsc-source"><span class="mtk17">&lt;</span><span class="mtk10">Box</span><span class="mtk1"> </span><span class="mtk12">sx</span><span class="mtk1">=</span><span class="mtk4">{</span><span class="mtk1">{ </span><span class="mtk12">pr:</span><span class="mtk1"> </span><span class="mtk8">&quot;16px&quot;</span><span class="mtk1"> }</span><span class="mtk4">}</span><span class="mtk1"> </span><span class="mtk17">/&gt;</span></span></span></code></pre> <p>This has the benefit of being shorter and allows us to use the spacing scale defined in the theme. Later in this tutorial, we will explore how to customize the spacing scale.</p> <p>Here is a list of the available margin and padding properties with the actions they perform:</p> <h3 id="padding-properties" style="position:relative;"><a href="#padding-properties" aria-label="padding properties permalink" class="anchor before"><svg aria-hidden="true" focusable="false" height="16" version="1.1" viewBox="0 0 16 16" width="16"><path fill-rule="evenodd" d="M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z"></path></svg></a>Padding Properties</h3> <table> <thead> <tr> <th>Property</th> <th>Description</th> <th>Action</th> </tr> </thead> <tbody> <tr> <td><code>p</code></td> <td>Padding</td> <td>Applies padding to all sides</td> </tr> <tr> <td><code>px</code></td> <td>Padding X</td> <td>Applies padding to the left and right sides</td> </tr> <tr> <td><code>py</code></td> <td>Padding Y</td> <td>Applies padding to the top and bottom sides</td> </tr> <tr> <td><code>pt</code></td> <td>Padding Top</td> <td>Applies padding to the top side</td> </tr> <tr> <td><code>pr</code></td> <td>Padding Right</td> <td>Applies padding to the right side</td> </tr> <tr> <td><code>pb</code></td> <td>Padding Bottom</td> <td>Applies padding to the bottom side</td> </tr> <tr> <td><code>pl</code></td> <td>Padding Left</td> <td>Applies padding to the left side</td> </tr> </tbody> </table> <h3 id="margin-properties" style="position:relative;"><a href="#margin-properties" aria-label="margin properties permalink" class="anchor before"><svg aria-hidden="true" focusable="false" height="16" version="1.1" viewBox="0 0 16 16" width="16"><path fill-rule="evenodd" d="M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z"></path></svg></a>Margin Properties</h3> <table> <thead> <tr> <th>Property</th> <th>Description</th> <th>Action</th> </tr> </thead> <tbody> <tr> <td><code>m</code></td> <td>Margin</td> <td>Applies margin to all sides</td> </tr> <tr> <td><code>mx</code></td> <td>Margin X</td> <td>Applies margin to the left and right sides</td> </tr> <tr> <td><code>my</code></td> <td>Margin Y</td> <td>Applies margin to the top and bottom sides</td> </tr> <tr> <td><code>mt</code></td> <td>Margin Top</td> <td>Applies margin to the top side</td> </tr> <tr> <td><code>mr</code></td> <td>Margin Right</td> <td>Applies margin to the right side</td> </tr> <tr> <td><code>mb</code></td> <td>Margin Bottom</td> <td>Applies margin to the bottom side</td> </tr> <tr> <td><code>ml</code></td> <td>Margin Left</td> <td>Applies margin to the left side</td> </tr> </tbody> </table> <p>In the following example, we will add padding to the <code>Box</code> component using the <code>p</code> property and margin to the <code>Typography</code> component using the <code>mx</code> property to center the text content.</p> <pre class="grvsc-container grvsc-has-line-highlighting default-dark" data-language="jsx" data-index="2"><code class="grvsc-code"><span class="grvsc-line"><span class="grvsc-source"><span class="mtk15">import</span><span class="mtk1"> </span><span class="mtk12">React</span><span class="mtk1"> </span><span class="mtk15">from</span><span class="mtk1"> </span><span class="mtk8">&quot;react&quot;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk15">import</span><span class="mtk1"> { </span><span class="mtk12">Box</span><span class="mtk1">, </span><span class="mtk12">Typography</span><span class="mtk1"> } </span><span class="mtk15">from</span><span class="mtk1"> </span><span class="mtk8">&quot;@mui/material&quot;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk15">export</span><span class="mtk1"> </span><span class="mtk15">default</span><span class="mtk1"> </span><span class="mtk4">function</span><span class="mtk1"> </span><span class="mtk11">App</span><span class="mtk1">() {</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk15">return</span><span class="mtk1"> (</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk17">&lt;</span><span class="mtk10">Box</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">sx</span><span class="mtk1">=</span><span class="mtk4">{</span><span class="mtk1">{</span></span></span> <span class="grvsc-line grvsc-line-highlighted"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">p:</span><span class="mtk1"> </span><span class="mtk8">&quot;16px&quot;</span><span class="mtk1">,</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">backgroundColor:</span><span class="mtk1"> </span><span class="mtk8">&quot;#c9e4d5&quot;</span><span class="mtk1">,</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">color:</span><span class="mtk1"> </span><span class="mtk8">&quot;#fff&quot;</span><span class="mtk1">,</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> }</span><span class="mtk4">}</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk17">&gt;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk17">&lt;</span><span class="mtk10">Typography</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">sx</span><span class="mtk1">=</span><span class="mtk4">{</span><span class="mtk1">{</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">backgroundColor:</span><span class="mtk1"> </span><span class="mtk8">&quot;#6669ad&quot;</span><span class="mtk1">,</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">width:</span><span class="mtk1"> </span><span class="mtk8">&quot;fit-content&quot;</span><span class="mtk1">,</span></span></span> <span class="grvsc-line grvsc-line-highlighted"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">p:</span><span class="mtk1"> </span><span class="mtk8">&quot;16px&quot;</span><span class="mtk1">,</span></span></span> <span class="grvsc-line grvsc-line-highlighted"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">mx:</span><span class="mtk1"> </span><span class="mtk8">&quot;auto&quot;</span><span class="mtk1">,</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> }</span><span class="mtk4">}</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk17">&gt;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> Hello World</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk17">&lt;/</span><span class="mtk10">Typography</span><span class="mtk17">&gt;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk17">&lt;/</span><span class="mtk10">Box</span><span class="mtk17">&gt;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> )</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1">}</span></span></span></code></pre> <p><span class="gatsby-resp-image-wrapper" style="position: relative; display: block; margin-left: auto; margin-right: auto; max-width: 720px; " > <a class="gatsby-resp-image-link" href="/static/f3b869e14bbfa2512de57596dc8a29c7/525d3/mui-spacing-example.png" style="display: block" target="_blank" rel="noopener" > <span class="gatsby-resp-image-background-image" style="padding-bottom: 39.44444444444444%; position: relative; bottom: 0; left: 0; background-image: url('data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABQAAAAICAYAAAD5nd/tAAAACXBIWXMAABJ0AAASdAHeZh94AAAAdUlEQVR42mM4+eTqf2z4xOOr/8++uv5/+c4T/zsn7fnfO33v/10Xz/8/8+IaWA6XPobTT6//x4ZPPbn+/8Lrm/+XbQca2L/3f+/U/f93Xbjw/9zLG2A5XPoYfvz59R8f/vX3938Y/PkXv1oQZvhPZTBqIOUAAGBfZh/MwvDVAAAAAElFTkSuQmCC'); background-size: cover; display: block;" ></span> <img class="gatsby-resp-image-image" alt="MUI Padding and Margin" title="" src="/static/f3b869e14bbfa2512de57596dc8a29c7/37523/mui-spacing-example.png" srcset="/static/f3b869e14bbfa2512de57596dc8a29c7/e9ff0/mui-spacing-example.png 180w, /static/f3b869e14bbfa2512de57596dc8a29c7/f21e7/mui-spacing-example.png 360w, /static/f3b869e14bbfa2512de57596dc8a29c7/37523/mui-spacing-example.png 720w, /static/f3b869e14bbfa2512de57596dc8a29c7/302a4/mui-spacing-example.png 1080w, /static/f3b869e14bbfa2512de57596dc8a29c7/525d3/mui-spacing-example.png 1090w" sizes="(max-width: 720px) 100vw, 720px" style="width:100%;height:100%;margin:0;vertical-align:middle;position:absolute;top:0;left:0;" loading="lazy" decoding="async" /> </a> </span></p> <p>The results above demonstrate how <code>p</code> applies padding to all sides and <code>mx</code> applies margin to the left and right sides of the <code>Typography</code> component.</p> <h2 id="theme-spacing" style="position:relative;"><a href="#theme-spacing" aria-label="theme spacing permalink" class="anchor before"><svg aria-hidden="true" focusable="false" height="16" version="1.1" viewBox="0 0 16 16" width="16"><path fill-rule="evenodd" d="M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z"></path></svg></a>Theme Spacing</h2> <p>MUI provides a theme helper function to systemize spacing and create consistency all throughout the application. The <code>theme.spacing</code> function returns a value from the spacing scale based on the argument passed to it.</p> <h3 id="default-spacing-scale" style="position:relative;"><a href="#default-spacing-scale" aria-label="default spacing scale permalink" class="anchor before"><svg aria-hidden="true" focusable="false" height="16" version="1.1" viewBox="0 0 16 16" width="16"><path fill-rule="evenodd" d="M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z"></path></svg></a>Default Spacing Scale</h3> <p>By default, MUI uses the 8px scaling factor. So, when we pass <code>1</code> to the <code>theme.spacing</code> function, it will return <code>8px</code>. Similarly, when we pass <code>2</code>, it will return <code>16px</code> and so on.</p> <p>Let’s try a simple example to understand how it works. We will create a <code>Box</code> component and apply padding to it using the <code>theme.spacing</code> function.</p> <pre class="grvsc-container grvsc-has-line-highlighting default-dark" data-language="jsx" data-index="3"><code class="grvsc-code"><span class="grvsc-line"><span class="grvsc-source"><span class="mtk17">&lt;</span><span class="mtk10">Box</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">sx</span><span class="mtk1">=</span><span class="mtk4">{</span><span class="mtk1">{</span></span></span> <span class="grvsc-line grvsc-line-highlighted"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk11">p</span><span class="mtk12">:</span><span class="mtk1"> </span><span class="mtk12">theme</span><span class="mtk1"> </span><span class="mtk4">=&gt;</span><span class="mtk1"> </span><span class="mtk12">theme</span><span class="mtk1">.</span><span class="mtk11">spacing</span><span class="mtk1">(</span><span class="mtk7">2</span><span class="mtk1">),</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> }</span><span class="mtk4">}</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk17">&gt;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> Hello World</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk17">&lt;/</span><span class="mtk10">Box</span><span class="mtk17">&gt;</span></span></span></code></pre> <p>The padding value is now <code>16px</code>, which is the value returned by the <code>theme.spacing</code> function when we pass <code>2</code> to it.</p> <p>To simplify this, we can pass only the number to the <code>p</code> property, and MUI will automatically call the <code>theme.spacing</code> function for us!</p> <pre class="grvsc-container grvsc-has-line-highlighting default-dark" data-language="jsx" data-index="4"><code class="grvsc-code"><span class="grvsc-line"><span class="grvsc-source"><span class="mtk17">&lt;</span><span class="mtk10">Box</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">sx</span><span class="mtk1">=</span><span class="mtk4">{</span><span class="mtk1">{</span></span></span> <span class="grvsc-line grvsc-line-highlighted"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">p:</span><span class="mtk1"> </span><span class="mtk7">2</span><span class="mtk1">, </span><span class="mtk3">// equivalent to (theme) =&gt; theme.spacing(2)</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> }</span><span class="mtk4">}</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk17">&gt;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> Hello World</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk17">&lt;/</span><span class="mtk10">Box</span><span class="mtk17">&gt;</span></span></span></code></pre> <h3 id="custom-spacing-scale" style="position:relative;"><a href="#custom-spacing-scale" aria-label="custom spacing scale permalink" class="anchor before"><svg aria-hidden="true" focusable="false" height="16" version="1.1" viewBox="0 0 16 16" width="16"><path fill-rule="evenodd" d="M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z"></path></svg></a>Custom Spacing Scale</h3> <p>We can use the <code>spacing</code> property in the <code>theme</code> object to customize the spacing scale and pass it a new value.</p> <pre class="grvsc-container grvsc-has-line-highlighting default-dark" data-language="jsx" data-index="5"><code class="grvsc-code"><span class="grvsc-line"><span class="grvsc-source"><span class="mtk15">import</span><span class="mtk1"> </span><span class="mtk12">React</span><span class="mtk1"> </span><span class="mtk15">from</span><span class="mtk1"> </span><span class="mtk8">&quot;react&quot;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk15">import</span><span class="mtk1"> { </span><span class="mtk12">createTheme</span><span class="mtk1">, </span><span class="mtk12">ThemeProvider</span><span class="mtk1">, </span><span class="mtk12">Box</span><span class="mtk1"> } </span><span class="mtk15">from</span><span class="mtk1"> </span><span class="mtk8">&quot;@mui/material&quot;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"></span></span> <span class="grvsc-line grvsc-line-highlighted"><span class="grvsc-source"><span class="mtk4">const</span><span class="mtk1"> </span><span class="mtk12">theme</span><span class="mtk1"> = </span><span class="mtk11">createTheme</span><span class="mtk1">({</span></span></span> <span class="grvsc-line grvsc-line-highlighted"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">spacing:</span><span class="mtk1"> </span><span class="mtk7">4</span><span class="mtk1">,</span></span></span> <span class="grvsc-line grvsc-line-highlighted"><span class="grvsc-source"><span class="mtk1">})</span></span></span> <span class="grvsc-line"><span class="grvsc-source"></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk15">export</span><span class="mtk1"> </span><span class="mtk15">default</span><span class="mtk1"> </span><span class="mtk4">function</span><span class="mtk1"> </span><span class="mtk11">App</span><span class="mtk1">() {</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk15">return</span><span class="mtk1"> (</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk17">&lt;</span><span class="mtk10">ThemeProvider</span><span class="mtk1"> </span><span class="mtk12">theme</span><span class="mtk1">=</span><span class="mtk4">{</span><span class="mtk12">theme</span><span class="mtk4">}</span><span class="mtk17">&gt;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk17">&lt;</span><span class="mtk10">Box</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">sx</span><span class="mtk1">=</span><span class="mtk4">{</span><span class="mtk1">{</span></span></span> <span class="grvsc-line grvsc-line-highlighted"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">p:</span><span class="mtk1"> </span><span class="mtk7">2</span><span class="mtk1">, </span><span class="mtk3">// 8px</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> }</span><span class="mtk4">}</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk17">&gt;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> ...</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk17">&lt;/</span><span class="mtk10">Box</span><span class="mtk17">&gt;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk17">&lt;/</span><span class="mtk10">ThemeProvider</span><span class="mtk17">&gt;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> )</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1">}</span></span></span></code></pre> <p>Now, the padding value is <code>8px</code> because we have changed the spacing scale to a multiple of 4.</p> <p>Alternatively, we can pass an array of values to the <code>spacing</code> property to create a custom spacing scale.</p> <pre class="grvsc-container grvsc-has-line-highlighting default-dark" data-language="jsx" data-index="6"><code class="grvsc-code"><span class="grvsc-line"><span class="grvsc-source"><span class="mtk15">import</span><span class="mtk1"> </span><span class="mtk12">React</span><span class="mtk1"> </span><span class="mtk15">from</span><span class="mtk1"> </span><span class="mtk8">&quot;react&quot;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk15">import</span><span class="mtk1"> { </span><span class="mtk12">createTheme</span><span class="mtk1">, </span><span class="mtk12">ThemeProvider</span><span class="mtk1">, </span><span class="mtk12">Box</span><span class="mtk1"> } </span><span class="mtk15">from</span><span class="mtk1"> </span><span class="mtk8">&quot;@mui/material&quot;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"></span></span> <span class="grvsc-line grvsc-line-highlighted"><span class="grvsc-source"><span class="mtk4">const</span><span class="mtk1"> </span><span class="mtk12">theme</span><span class="mtk1"> = </span><span class="mtk11">createTheme</span><span class="mtk1">({</span></span></span> <span class="grvsc-line grvsc-line-highlighted"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">spacing:</span><span class="mtk1"> [</span><span class="mtk8">&quot;0&quot;</span><span class="mtk1">, </span><span class="mtk8">&quot;4px&quot;</span><span class="mtk1">, </span><span class="mtk8">&quot;8px&quot;</span><span class="mtk1">, </span><span class="mtk8">&quot;16px&quot;</span><span class="mtk1">, </span><span class="mtk8">&quot;32px&quot;</span><span class="mtk1">, </span><span class="mtk8">&quot;64px&quot;</span><span class="mtk1">],</span></span></span> <span class="grvsc-line grvsc-line-highlighted"><span class="grvsc-source"><span class="mtk1">})</span></span></span> <span class="grvsc-line"><span class="grvsc-source"></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk15">export</span><span class="mtk1"> </span><span class="mtk15">default</span><span class="mtk1"> </span><span class="mtk4">function</span><span class="mtk1"> </span><span class="mtk11">App</span><span class="mtk1">() {</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk15">return</span><span class="mtk1"> (</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk17">&lt;</span><span class="mtk10">ThemeProvider</span><span class="mtk1"> </span><span class="mtk12">theme</span><span class="mtk1">=</span><span class="mtk4">{</span><span class="mtk12">theme</span><span class="mtk4">}</span><span class="mtk17">&gt;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk17">&lt;</span><span class="mtk10">Box</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">sx</span><span class="mtk1">=</span><span class="mtk4">{</span><span class="mtk1">{</span></span></span> <span class="grvsc-line grvsc-line-highlighted"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">p:</span><span class="mtk1"> </span><span class="mtk7">2</span><span class="mtk1">, </span><span class="mtk3">// 8px</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> }</span><span class="mtk4">}</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk17">&gt;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> ...</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk17">&lt;/</span><span class="mtk10">Box</span><span class="mtk17">&gt;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk17">&lt;/</span><span class="mtk10">ThemeProvider</span><span class="mtk17">&gt;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> )</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1">}</span></span></span></code></pre> <p>When using a custom array, the value passed to the <code>theme.spacing</code> function will be used as an index to return the value from the array. So, when we pass <code>2</code>, it will return <code>8px</code> because it is the value at index 2 in the array.</p> <h2 id="grid-and-flex-gap" style="position:relative;"><a href="#grid-and-flex-gap" aria-label="grid and flex gap permalink" class="anchor before"><svg aria-hidden="true" focusable="false" height="16" version="1.1" viewBox="0 0 16 16" width="16"><path fill-rule="evenodd" d="M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z"></path></svg></a>Grid and Flex Gap</h2> <p>Creating spacing is not limited to padding and margin. CSS <code>grid</code> and <code>flex</code> have a <code>gap</code> property for creating spacing between components in a grid or flex layout. Additionally, the value of the <code>gap</code> property is used by the <code>theme.spacing</code> function to utilize the spacing scale.</p> <p>In the following example, we will create a grid layout with 3 columns using the <code>Grid</code> component. We will use the <code>gap</code> property to create spacing between the grid items.</p> <pre class="grvsc-container default-dark" data-language="jsx" data-index="7"><code class="grvsc-code"><span class="grvsc-line"><span class="grvsc-source"><span class="mtk15">import</span><span class="mtk1"> </span><span class="mtk12">React</span><span class="mtk1"> </span><span class="mtk15">from</span><span class="mtk1"> </span><span class="mtk8">&quot;react&quot;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk15">import</span><span class="mtk1"> { </span><span class="mtk12">createTheme</span><span class="mtk1">, </span><span class="mtk12">ThemeProvider</span><span class="mtk1">, </span><span class="mtk12">Grid</span><span class="mtk1">, </span><span class="mtk12">Box</span><span class="mtk1"> } </span><span class="mtk15">from</span><span class="mtk1"> </span><span class="mtk8">&quot;@mui/material&quot;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk4">const</span><span class="mtk1"> </span><span class="mtk12">theme</span><span class="mtk1"> = </span><span class="mtk11">createTheme</span><span class="mtk1">({</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">spacing:</span><span class="mtk1"> </span><span class="mtk7">4</span><span class="mtk1">,</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1">})</span></span></span> <span class="grvsc-line"><span class="grvsc-source"></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk15">export</span><span class="mtk1"> </span><span class="mtk15">default</span><span class="mtk1"> </span><span class="mtk4">function</span><span class="mtk1"> </span><span class="mtk11">App</span><span class="mtk1">() {</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk15">return</span><span class="mtk1"> (</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk17">&lt;</span><span class="mtk10">ThemeProvider</span><span class="mtk1"> </span><span class="mtk12">theme</span><span class="mtk1">=</span><span class="mtk4">{</span><span class="mtk12">theme</span><span class="mtk4">}</span><span class="mtk17">&gt;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk17">&lt;</span><span class="mtk10">Grid</span><span class="mtk1"> </span><span class="mtk12">container</span><span class="mtk1"> </span><span class="mtk12">gap</span><span class="mtk1">=</span><span class="mtk4">{</span><span class="mtk7">2</span><span class="mtk4">}</span><span class="mtk1"> </span><span class="mtk12">wrap</span><span class="mtk1">=</span><span class="mtk8">&quot;nowrap&quot;</span><span class="mtk17">&gt;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk17">&lt;</span><span class="mtk10">Grid</span><span class="mtk1"> </span><span class="mtk12">item</span><span class="mtk1"> </span><span class="mtk12">xs</span><span class="mtk1">=</span><span class="mtk4">{</span><span class="mtk7">4</span><span class="mtk4">}</span><span class="mtk17">&gt;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk17">&lt;</span><span class="mtk10">Box</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">sx</span><span class="mtk1">=</span><span class="mtk4">{</span><span class="mtk1">{</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">backgroundColor:</span><span class="mtk1"> </span><span class="mtk8">&quot;#c9e4d5&quot;</span><span class="mtk1">,</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">height:</span><span class="mtk1"> </span><span class="mtk8">&quot;100px&quot;</span><span class="mtk1">,</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> }</span><span class="mtk4">}</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk17">/&gt;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk17">&lt;/</span><span class="mtk10">Grid</span><span class="mtk17">&gt;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk17">&lt;</span><span class="mtk10">Grid</span><span class="mtk1"> </span><span class="mtk12">item</span><span class="mtk1"> </span><span class="mtk12">xs</span><span class="mtk1">=</span><span class="mtk4">{</span><span class="mtk7">4</span><span class="mtk4">}</span><span class="mtk17">&gt;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk17">&lt;</span><span class="mtk10">Box</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">sx</span><span class="mtk1">=</span><span class="mtk4">{</span><span class="mtk1">{</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">backgroundColor:</span><span class="mtk1"> </span><span class="mtk8">&quot;#c9e4d5&quot;</span><span class="mtk1">,</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">height:</span><span class="mtk1"> </span><span class="mtk8">&quot;100px&quot;</span><span class="mtk1">,</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> }</span><span class="mtk4">}</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk17">/&gt;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk17">&lt;/</span><span class="mtk10">Grid</span><span class="mtk17">&gt;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk17">&lt;</span><span class="mtk10">Grid</span><span class="mtk1"> </span><span class="mtk12">item</span><span class="mtk1"> </span><span class="mtk12">xs</span><span class="mtk1">=</span><span class="mtk4">{</span><span class="mtk7">4</span><span class="mtk4">}</span><span class="mtk17">&gt;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk17">&lt;</span><span class="mtk10">Box</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">sx</span><span class="mtk1">=</span><span class="mtk4">{</span><span class="mtk1">{</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">backgroundColor:</span><span class="mtk1"> </span><span class="mtk8">&quot;#c9e4d5&quot;</span><span class="mtk1">,</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">height:</span><span class="mtk1"> </span><span class="mtk8">&quot;100px&quot;</span><span class="mtk1">,</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> }</span><span class="mtk4">}</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk17">/&gt;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk17">&lt;/</span><span class="mtk10">Grid</span><span class="mtk17">&gt;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk17">&lt;/</span><span class="mtk10">Grid</span><span class="mtk17">&gt;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk17">&lt;/</span><span class="mtk10">ThemeProvider</span><span class="mtk17">&gt;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> )</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1">}</span></span></span></code></pre> <p><span class="gatsby-resp-image-wrapper" style="position: relative; display: block; margin-left: auto; margin-right: auto; max-width: 720px; " > <a class="gatsby-resp-image-link" href="/static/6dca6ef9c22fbb8b10c85b6c865a63cf/c88ae/mui-grid-gap.png" style="display: block" target="_blank" rel="noopener" > <span class="gatsby-resp-image-background-image" style="padding-bottom: 8.88888888888889%; position: relative; bottom: 0; left: 0; background-image: url('data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABQAAAACCAYAAABYBvyLAAAACXBIWXMAABnWAAAZ1gEY0crtAAAATklEQVR42mM4++z6/3PPbsDxWSC+8Pzm/ysv7/4/+xRVDiwPFAPJgdScxSLHcPY5kAOUhOGzQHzhxa3/V17dg2hAkjsHNQQkB1JzFoscAOVTjg96RKFJAAAAAElFTkSuQmCC'); background-size: cover; display: block;" ></span> <img class="gatsby-resp-image-image" alt="MUI Grid Gap" title="" src="/static/6dca6ef9c22fbb8b10c85b6c865a63cf/37523/mui-grid-gap.png" srcset="/static/6dca6ef9c22fbb8b10c85b6c865a63cf/e9ff0/mui-grid-gap.png 180w, /static/6dca6ef9c22fbb8b10c85b6c865a63cf/f21e7/mui-grid-gap.png 360w, /static/6dca6ef9c22fbb8b10c85b6c865a63cf/37523/mui-grid-gap.png 720w, /static/6dca6ef9c22fbb8b10c85b6c865a63cf/302a4/mui-grid-gap.png 1080w, /static/6dca6ef9c22fbb8b10c85b6c865a63cf/07a9c/mui-grid-gap.png 1440w, /static/6dca6ef9c22fbb8b10c85b6c865a63cf/c88ae/mui-grid-gap.png 1541w" sizes="(max-width: 720px) 100vw, 720px" style="width:100%;height:100%;margin:0;vertical-align:middle;position:absolute;top:0;left:0;" loading="lazy" decoding="async" /> </a> </span></p> <p>Similar to the margin and padding, <code>gap={2}</code> is equivalent to <code>gap={theme => theme.spacing(2)}</code> and will return <code>8px</code> because we have set the spacing scale to a multiple of 4.</p> <p><code>gap</code> can also be used in <code>sx</code> prop to create spacing between flex or grid items without using the <code>Grid</code> component.</p> <pre class="grvsc-container default-dark" data-language="jsx" data-index="8"><code class="grvsc-code"><span class="grvsc-line"><span class="grvsc-source"><span class="mtk17">&lt;</span><span class="mtk10">Box</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">sx</span><span class="mtk1">=</span><span class="mtk4">{</span><span class="mtk1">{</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">display:</span><span class="mtk1"> </span><span class="mtk8">&quot;flex&quot;</span><span class="mtk1">,</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">gap:</span><span class="mtk1"> </span><span class="mtk7">2</span><span class="mtk1">,</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> }</span><span class="mtk4">}</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk17">&gt;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> ...</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk17">&lt;/</span><span class="mtk10">Box</span><span class="mtk17">&gt;</span></span></span></code></pre> <pre class="grvsc-container default-dark" data-language="jsx" data-index="9"><code class="grvsc-code"><span class="grvsc-line"><span class="grvsc-source"><span class="mtk17">&lt;</span><span class="mtk10">Box</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">sx</span><span class="mtk1">=</span><span class="mtk4">{</span><span class="mtk1">{</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">display:</span><span class="mtk1"> </span><span class="mtk8">&quot;grid&quot;</span><span class="mtk1">,</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">gap:</span><span class="mtk1"> </span><span class="mtk7">2</span><span class="mtk1">,</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> }</span><span class="mtk4">}</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk17">&gt;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> ...</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk17">&lt;/</span><span class="mtk10">Box</span><span class="mtk17">&gt;</span></span></span></code></pre> <h2 id="summary" style="position:relative;"><a href="#summary" aria-label="summary permalink" class="anchor before"><svg aria-hidden="true" focusable="false" height="16" version="1.1" viewBox="0 0 16 16" width="16"><path fill-rule="evenodd" d="M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z"></path></svg></a>Summary</h2> <p>In this tutorial, we learned how spacing works in MUI using <code>sx</code> inline styles and a custom spacing scale in the theme. It is important to follow and create a spacing system in our application; it makes the UI look more consistent and the code easier to maintain and scale.</p> <p>Bye for now 👋</p> <style class="grvsc-styles"> .grvsc-container { overflow: auto; position: relative; -webkit-overflow-scrolling: touch; padding-top: 1rem; padding-top: var(--grvsc-padding-top, var(--grvsc-padding-v, 1rem)); padding-bottom: 1rem; padding-bottom: var(--grvsc-padding-bottom, var(--grvsc-padding-v, 1rem)); border-radius: 8px; border-radius: var(--grvsc-border-radius, 8px); font-feature-settings: normal; line-height: 1.4; } .grvsc-code { display: table; } .grvsc-line { display: table-row; box-sizing: border-box; width: 100%; position: relative; } .grvsc-line > * { position: relative; } .grvsc-gutter-pad { display: table-cell; padding-left: 0.75rem; padding-left: calc(var(--grvsc-padding-left, var(--grvsc-padding-h, 1.5rem)) / 2); } .grvsc-gutter { display: table-cell; -webkit-user-select: none; -moz-user-select: none; user-select: none; } .grvsc-gutter::before { content: attr(data-content); } .grvsc-source { display: table-cell; padding-left: 1.5rem; padding-left: var(--grvsc-padding-left, var(--grvsc-padding-h, 1.5rem)); padding-right: 1.5rem; padding-right: var(--grvsc-padding-right, var(--grvsc-padding-h, 1.5rem)); } .grvsc-source:empty::after { content: ' '; -webkit-user-select: none; -moz-user-select: none; user-select: none; } .grvsc-gutter + .grvsc-source { padding-left: 0.75rem; padding-left: calc(var(--grvsc-padding-left, var(--grvsc-padding-h, 1.5rem)) / 2); } /* Line transformer styles */ .grvsc-has-line-highlighting > .grvsc-code > .grvsc-line::before { content: ' '; position: absolute; width: 100%; } .grvsc-line-diff-add::before { background-color: var(--grvsc-line-diff-add-background-color, rgba(0, 255, 60, 0.2)); } .grvsc-line-diff-del::before { background-color: var(--grvsc-line-diff-del-background-color, rgba(255, 0, 20, 0.2)); } .grvsc-line-number { padding: 0 2px; text-align: right; opacity: 0.7; } .default-dark { background-color: #1E1E1E; color: #D4D4D4; } .default-dark .mtk17 { color: #808080; } .default-dark .mtk10 { color: #4EC9B0; } .default-dark .mtk1 { color: #D4D4D4; } .default-dark .mtk12 { color: #9CDCFE; } .default-dark .mtk4 { color: #569CD6; } .default-dark .mtk8 { color: #CE9178; } .default-dark .mtk15 { color: #C586C0; } .default-dark .mtk11 { color: #DCDCAA; } .default-dark .mtk7 { color: #B5CEA8; } .default-dark .mtk3 { color: #6A9955; } .default-dark .grvsc-line-highlighted::before { background-color: var(--grvsc-line-highlighted-background-color, rgba(255, 255, 255, 0.1)); box-shadow: inset var(--grvsc-line-highlighted-border-width, 4px) 0 0 0 var(--grvsc-line-highlighted-border-color, rgba(255, 255, 255, 0.5)); } </style><![CDATA[Breakpoints and Responsive Design with Material UI (MUI)]]>https://muhimasri.commui-breakpointhttps://muhimasri.commui-breakpoint<p>Breakpoints are a crucial concept in responsive design. They allow us to define the application’s appearance on different screen sizes. In this tutorial, we will learn how to use and customize Material UI (MUI) breakpoints to create responsive designs.</p> <video width="720" height="400" autoplay loop muted playsinline preload="none"> <source src="/7754ed86837b6e0992f9981293389c25/mui-breakpoints.mp4" type="video/mp4"> </video> <h2 id="using-theme-breakpoints" style="position:relative;"><a href="#using-theme-breakpoints" aria-label="using theme breakpoints permalink" class="anchor before"><svg aria-hidden="true" focusable="false" height="16" version="1.1" viewBox="0 0 16 16" width="16"><path fill-rule="evenodd" d="M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z"></path></svg></a>Using theme breakpoints</h2> <p>We can use the <code>theme</code> object to access the MUI breakpoints when styling components. It’s an object available in the <code>props</code> of all styled-components.</p> <p>We can access them using the <code>theme.breakpoints</code> object. It has the following keys:</p> <ul> <li><code>xs</code>: Extra small devices (less than 600px)</li> <li><code>sm</code>: Small devices (600px and up)</li> <li><code>md</code>: Medium devices (900px and up)</li> <li><code>lg</code>: Large devices (1200px and up)</li> <li><code>xl</code>: Extra large devices (1536px and up)</li> </ul> <p>Here’s a simple example of how to add the breakpoint styles to a component:</p> <pre class="grvsc-container grvsc-has-line-highlighting default-dark" data-language="jsx" data-index="0"><code class="grvsc-code"><span class="grvsc-line"><span class="grvsc-source"><span class="mtk17">&lt;</span><span class="mtk10">Box</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">sx</span><span class="mtk1">=</span><span class="mtk4">{</span><span class="mtk1">(</span><span class="mtk12">theme</span><span class="mtk1">) </span><span class="mtk4">=&gt;</span><span class="mtk1"> ({</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">textAlign:</span><span class="mtk1"> </span><span class="mtk8">&#39;center&#39;</span><span class="mtk1">,</span></span></span> <span class="grvsc-line grvsc-line-highlighted"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">[theme.breakpoints.</span><span class="mtk11">up</span><span class="mtk12">(</span><span class="mtk8">&#39;md&#39;</span><span class="mtk12">)]:</span><span class="mtk1"> { </span><span class="mtk12">textAlign:</span><span class="mtk1"> </span><span class="mtk8">&#39;left&#39;</span><span class="mtk1"> },</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> })</span><span class="mtk4">}</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk17">&gt;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> TEXT</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk17">&lt;/</span><span class="mtk10">Box</span><span class="mtk17">&gt;</span></span></span></code></pre> <p><code>theme.breakpoints.up('md')</code> is a function that returns a CSS media query string. It’s equivalent to <code>@media (min-width: 900px)</code>. So, the above code will set the <code>textAlign</code> to <code>left</code> for screen sizes greater than <code>900px</code>.</p> <p>Let’s see another example with a more practical use case. We will create a header component that will align the logo to the left for screen sizes greater than <code>600px</code> and center it for smaller screen sizes.</p> <pre class="grvsc-container grvsc-has-line-highlighting default-dark" data-language="jsx" data-index="1"><code class="grvsc-code"><span class="grvsc-line"><span class="grvsc-source"><span class="mtk15">import</span><span class="mtk1"> </span><span class="mtk4">*</span><span class="mtk1"> </span><span class="mtk15">as</span><span class="mtk1"> </span><span class="mtk12">React</span><span class="mtk1"> </span><span class="mtk15">from</span><span class="mtk1"> </span><span class="mtk8">&#39;react&#39;</span><span class="mtk1">;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk15">import</span><span class="mtk1"> </span><span class="mtk12">Typography</span><span class="mtk1"> </span><span class="mtk15">from</span><span class="mtk1"> </span><span class="mtk8">&#39;@mui/material/Typography&#39;</span><span class="mtk1">;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk15">import</span><span class="mtk1"> { </span><span class="mtk12">Stack</span><span class="mtk1">, </span><span class="mtk12">Toolbar</span><span class="mtk1">, </span><span class="mtk12">AppBar</span><span class="mtk1"> } </span><span class="mtk15">from</span><span class="mtk1"> </span><span class="mtk8">&#39;@mui/material&#39;</span><span class="mtk1">;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk15">import</span><span class="mtk1"> </span><span class="mtk12">LogoDev</span><span class="mtk1"> </span><span class="mtk15">from</span><span class="mtk1"> </span><span class="mtk8">&#39;@mui/icons-material/LogoDev&#39;</span><span class="mtk1">;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk4">function</span><span class="mtk1"> </span><span class="mtk11">ResponsiveHeader</span><span class="mtk1">() {</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk15">return</span><span class="mtk1"> (</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk17">&lt;</span><span class="mtk10">AppBar</span><span class="mtk1"> </span><span class="mtk12">position</span><span class="mtk1">=</span><span class="mtk8">&quot;static&quot;</span><span class="mtk17">&gt;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk17">&lt;</span><span class="mtk10">Toolbar</span></span></span> <span class="grvsc-line grvsc-line-highlighted"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">sx</span><span class="mtk1">=</span><span class="mtk4">{</span><span class="mtk1">(</span><span class="mtk12">theme</span><span class="mtk1">) </span><span class="mtk4">=&gt;</span><span class="mtk1"> ({</span></span></span> <span class="grvsc-line grvsc-line-highlighted"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">[theme.breakpoints.</span><span class="mtk11">up</span><span class="mtk12">(</span><span class="mtk8">&#39;xs&#39;</span><span class="mtk12">)]:</span><span class="mtk1"> { </span><span class="mtk12">justifyContent:</span><span class="mtk1"> </span><span class="mtk8">&#39;center&#39;</span><span class="mtk1"> },</span></span></span> <span class="grvsc-line grvsc-line-highlighted"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">[theme.breakpoints.</span><span class="mtk11">up</span><span class="mtk12">(</span><span class="mtk8">&#39;sm&#39;</span><span class="mtk12">)]:</span><span class="mtk1"> { </span><span class="mtk12">justifyContent:</span><span class="mtk1"> </span><span class="mtk8">&#39;left&#39;</span><span class="mtk1"> },</span></span></span> <span class="grvsc-line grvsc-line-highlighted"><span class="grvsc-source"><span class="mtk1"> })</span><span class="mtk4">}</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk17">&gt;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk17">&lt;</span><span class="mtk10">Stack</span><span class="mtk1"> </span><span class="mtk12">direction</span><span class="mtk1">=</span><span class="mtk8">&quot;row&quot;</span><span class="mtk1"> </span><span class="mtk12">alignItems</span><span class="mtk1">=</span><span class="mtk8">&quot;center&quot;</span><span class="mtk17">&gt;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk17">&lt;</span><span class="mtk10">LogoDev</span><span class="mtk1"> </span><span class="mtk12">fontSize</span><span class="mtk1">=</span><span class="mtk8">&quot;large&quot;</span><span class="mtk1"> </span><span class="mtk17">/&gt;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk17">&lt;</span><span class="mtk10">Typography</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">variant</span><span class="mtk1">=</span><span class="mtk8">&quot;h6&quot;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">sx</span><span class="mtk1">=</span><span class="mtk4">{</span><span class="mtk1">{</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">ml:</span><span class="mtk1"> </span><span class="mtk7">0.5</span><span class="mtk1">,</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> }</span><span class="mtk4">}</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk17">&gt;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> LOGO</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk17">&lt;/</span><span class="mtk10">Typography</span><span class="mtk17">&gt;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk17">&lt;/</span><span class="mtk10">Stack</span><span class="mtk17">&gt;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk17">&lt;/</span><span class="mtk10">Toolbar</span><span class="mtk17">&gt;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk17">&lt;/</span><span class="mtk10">AppBar</span><span class="mtk17">&gt;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> );</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1">}</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk15">export</span><span class="mtk1"> </span><span class="mtk15">default</span><span class="mtk1"> </span><span class="mtk12">ResponsiveHeader</span><span class="mtk1">;</span></span></span></code></pre> <div id="MuiBreakPointOne" data-code data-height="220px" data-resize style="display:flex;justify-content: center; background: #f3f3f3"></div> <p>The example above has a resize handle at the bottom right corner. If we resize the window, we can see the logo move to the center when the screen size is less than <code>600px</code>.</p> <p><code>theme.breakpoints</code> object also provides different options to create media queries. Here’s a list of all the options:</p> <ul> <li><code>up</code>: min-width</li> <li><code>down</code>: max-width</li> <li><code>between</code>: between min-width and max-width</li> <li><code>only</code>: only the given breakpoint</li> <li><code>not</code>: not between min-width and max-width</li> </ul> <h2 id="using-sx-shortcut-syntax" style="position:relative;"><a href="#using-sx-shortcut-syntax" aria-label="using sx shortcut syntax permalink" class="anchor before"><svg aria-hidden="true" focusable="false" height="16" version="1.1" viewBox="0 0 16 16" width="16"><path fill-rule="evenodd" d="M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z"></path></svg></a>Using SX shortcut syntax</h2> <p><code>sx</code> provides a shortcut syntax to access the theme and add component styles. It provides a more straightforward way to add breakpoints. Here’s an example:</p> <pre class="grvsc-container default-dark" data-language="jsx" data-index="2"><code class="grvsc-code"><span class="grvsc-line"><span class="grvsc-source"><span class="mtk17">&lt;</span><span class="mtk10">Box</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">sx</span><span class="mtk1">=</span><span class="mtk4">{</span><span class="mtk1">{</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">textAlign:</span><span class="mtk1"> { </span><span class="mtk12">xs:</span><span class="mtk1"> </span><span class="mtk8">&#39;center&#39;</span><span class="mtk1">, </span><span class="mtk12">md:</span><span class="mtk1"> </span><span class="mtk8">&#39;left&#39;</span><span class="mtk1"> },</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> }</span><span class="mtk4">}</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk17">&gt;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> TEXT</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk17">&lt;/</span><span class="mtk10">Box</span><span class="mtk17">&gt;</span></span></span></code></pre> <p>Using <code>md</code> or <code>sm</code> is equivalent to <code>theme.breakpoints.up('md')</code> or <code>theme.breakpoints.up('sm')</code>, and they’re used as a key of the CSS property value. So the above code will set the <code>textAlign</code> to <code>left</code> for screen sizes greater than <code>900px</code>.</p> <p>This syntax is cleaner and easier to read, but it has a limitation. We can only use the <code>up</code> option and can’t use <code>down</code>, <code>between</code> or <code>only</code> options.</p> <p>Let’s create the header example again using the <code>sx</code> shortcut syntax.</p> <pre class="grvsc-container grvsc-has-line-highlighting default-dark" data-language="jsx" data-index="3"><code class="grvsc-code"><span class="grvsc-line"><span class="grvsc-source"><span class="mtk15">import</span><span class="mtk1"> </span><span class="mtk4">*</span><span class="mtk1"> </span><span class="mtk15">as</span><span class="mtk1"> </span><span class="mtk12">React</span><span class="mtk1"> </span><span class="mtk15">from</span><span class="mtk1"> </span><span class="mtk8">&#39;react&#39;</span><span class="mtk1">;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk15">import</span><span class="mtk1"> </span><span class="mtk12">Typography</span><span class="mtk1"> </span><span class="mtk15">from</span><span class="mtk1"> </span><span class="mtk8">&#39;@mui/material/Typography&#39;</span><span class="mtk1">;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk15">import</span><span class="mtk1"> { </span><span class="mtk12">Stack</span><span class="mtk1">, </span><span class="mtk12">Toolbar</span><span class="mtk1">, </span><span class="mtk12">AppBar</span><span class="mtk1">, </span><span class="mtk12">Box</span><span class="mtk1"> } </span><span class="mtk15">from</span><span class="mtk1"> </span><span class="mtk8">&#39;@mui/material&#39;</span><span class="mtk1">;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk15">import</span><span class="mtk1"> </span><span class="mtk12">LogoDev</span><span class="mtk1"> </span><span class="mtk15">from</span><span class="mtk1"> </span><span class="mtk8">&#39;@mui/icons-material/LogoDev&#39;</span><span class="mtk1">;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk4">function</span><span class="mtk1"> </span><span class="mtk11">ResponsiveHeader</span><span class="mtk1">() {</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk15">return</span><span class="mtk1"> (</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk17">&lt;</span><span class="mtk10">AppBar</span><span class="mtk1"> </span><span class="mtk12">position</span><span class="mtk1">=</span><span class="mtk8">&quot;static&quot;</span><span class="mtk17">&gt;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk17">&lt;</span><span class="mtk10">Toolbar</span></span></span> <span class="grvsc-line grvsc-line-highlighted"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">sx</span><span class="mtk1">=</span><span class="mtk4">{</span><span class="mtk1">{</span></span></span> <span class="grvsc-line grvsc-line-highlighted"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">justifyContent:</span><span class="mtk1"> { </span><span class="mtk12">xs:</span><span class="mtk1"> </span><span class="mtk8">&#39;center&#39;</span><span class="mtk1">, </span><span class="mtk12">sm:</span><span class="mtk1"> </span><span class="mtk8">&#39;left&#39;</span><span class="mtk1"> },</span></span></span> <span class="grvsc-line grvsc-line-highlighted"><span class="grvsc-source"><span class="mtk1"> }</span><span class="mtk4">}</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk17">&gt;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk17">&lt;</span><span class="mtk10">Stack</span><span class="mtk1"> </span><span class="mtk12">direction</span><span class="mtk1">=</span><span class="mtk8">&quot;row&quot;</span><span class="mtk1"> </span><span class="mtk12">alignItems</span><span class="mtk1">=</span><span class="mtk8">&quot;center&quot;</span><span class="mtk17">&gt;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk17">&lt;</span><span class="mtk10">LogoDev</span><span class="mtk1"> </span><span class="mtk12">fontSize</span><span class="mtk1">=</span><span class="mtk8">&quot;large&quot;</span><span class="mtk1"> </span><span class="mtk17">/&gt;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk17">&lt;</span><span class="mtk10">Typography</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">variant</span><span class="mtk1">=</span><span class="mtk8">&quot;h6&quot;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">sx</span><span class="mtk1">=</span><span class="mtk4">{</span><span class="mtk1">{</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">ml:</span><span class="mtk1"> </span><span class="mtk7">0.5</span><span class="mtk1">,</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> }</span><span class="mtk4">}</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk17">&gt;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> LOGO</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk17">&lt;/</span><span class="mtk10">Typography</span><span class="mtk17">&gt;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk17">&lt;/</span><span class="mtk10">Stack</span><span class="mtk17">&gt;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk17">&lt;/</span><span class="mtk10">Toolbar</span><span class="mtk17">&gt;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk17">&lt;/</span><span class="mtk10">AppBar</span><span class="mtk17">&gt;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> );</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1">}</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk15">export</span><span class="mtk1"> </span><span class="mtk15">default</span><span class="mtk1"> </span><span class="mtk12">ResponsiveHeader</span><span class="mtk1">;</span></span></span></code></pre> <div id="MuiBreakPointOne" data-code data-height="220px" data-resize style="display:flex;justify-content: center; background: #f3f3f3"></div> <h2 id="using-media-query-hook" style="position:relative;"><a href="#using-media-query-hook" aria-label="using media query hook permalink" class="anchor before"><svg aria-hidden="true" focusable="false" height="16" version="1.1" viewBox="0 0 16 16" width="16"><path fill-rule="evenodd" d="M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z"></path></svg></a>Using media query hook</h2> <p><code>useMediaQuery</code> is a hook that returns a boolean value based on the current screen size. It’s helpful if we want to use JavaScript to access the breakpoints and do more complex logic.</p> <p>Here’s an example of how to use <code>useMediaQuery</code> hook:</p> <pre class="grvsc-container default-dark" data-language="jsx" data-index="4"><code class="grvsc-code"><span class="grvsc-line"><span class="grvsc-source"><span class="mtk15">import</span><span class="mtk1"> </span><span class="mtk12">React</span><span class="mtk1"> </span><span class="mtk15">from</span><span class="mtk1"> </span><span class="mtk8">&#39;react&#39;</span><span class="mtk1">;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk15">import</span><span class="mtk1"> </span><span class="mtk12">useMediaQuery</span><span class="mtk1"> </span><span class="mtk15">from</span><span class="mtk1"> </span><span class="mtk8">&#39;@mui/material/useMediaQuery&#39;</span><span class="mtk1">;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk15">import</span><span class="mtk1"> { </span><span class="mtk12">useTheme</span><span class="mtk1"> } </span><span class="mtk15">from</span><span class="mtk1"> </span><span class="mtk8">&#39;@mui/material/styles&#39;</span><span class="mtk1">;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk4">const</span><span class="mtk1"> </span><span class="mtk11">MyComponent</span><span class="mtk1"> = () </span><span class="mtk4">=&gt;</span><span class="mtk1"> {</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk4">const</span><span class="mtk1"> </span><span class="mtk12">theme</span><span class="mtk1"> = </span><span class="mtk11">useTheme</span><span class="mtk1">();</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk4">const</span><span class="mtk1"> </span><span class="mtk12">isMobile</span><span class="mtk1"> = </span><span class="mtk11">useMediaQuery</span><span class="mtk1">(</span><span class="mtk12">theme</span><span class="mtk1">.</span><span class="mtk12">breakpoints</span><span class="mtk1">.</span><span class="mtk11">down</span><span class="mtk1">(</span><span class="mtk8">&#39;sm&#39;</span><span class="mtk1">));</span></span></span> <span class="grvsc-line"><span class="grvsc-source"></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk15">return</span><span class="mtk1"> (</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk17">&lt;</span><span class="mtk4">div</span><span class="mtk17">&gt;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk4">{</span><span class="mtk12">isMobile</span><span class="mtk1"> ? (</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk17">&lt;</span><span class="mtk4">div</span><span class="mtk17">&gt;</span><span class="mtk1">Mobile View: More simplified layout or content</span><span class="mtk17">&lt;/</span><span class="mtk4">div</span><span class="mtk17">&gt;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> ) : (</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk17">&lt;</span><span class="mtk4">div</span><span class="mtk17">&gt;</span><span class="mtk1">Desktop View: More complex layout or additional content</span><span class="mtk17">&lt;/</span><span class="mtk4">div</span><span class="mtk17">&gt;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> )</span><span class="mtk4">}</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk17">&lt;/</span><span class="mtk4">div</span><span class="mtk17">&gt;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> );</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1">};</span></span></span> <span class="grvsc-line"><span class="grvsc-source"></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk15">export</span><span class="mtk1"> </span><span class="mtk15">default</span><span class="mtk1"> </span><span class="mtk12">MyComponent</span><span class="mtk1">;</span></span></span></code></pre> <p>In the above example, we’re using <code>useMediaQuery</code> to check if the screen size is less than <code>600px</code>. If it’s true, we’re rendering a simplified layout. Otherwise, we’re rendering a more complex layout.</p> <h2 id="customizing-breakpoints" style="position:relative;"><a href="#customizing-breakpoints" aria-label="customizing breakpoints permalink" class="anchor before"><svg aria-hidden="true" focusable="false" height="16" version="1.1" viewBox="0 0 16 16" width="16"><path fill-rule="evenodd" d="M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z"></path></svg></a>Customizing breakpoints</h2> <p>The breakpoints we used in the previous examples are the default breakpoints provided by MUI. Sometimes, we need to modify the breakpoints to match the design requirements or create new ones.</p> <p>We can customize the values using the <code>createTheme</code> object.</p> <pre class="grvsc-container default-dark" data-language="jsx" data-index="5"><code class="grvsc-code"><span class="grvsc-line"><span class="grvsc-source"><span class="mtk15">import</span><span class="mtk1"> { </span><span class="mtk12">createTheme</span><span class="mtk1"> } </span><span class="mtk15">from</span><span class="mtk1"> </span><span class="mtk8">&#39;@mui/material/styles&#39;</span><span class="mtk1">;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk4">const</span><span class="mtk1"> </span><span class="mtk12">theme</span><span class="mtk1"> = </span><span class="mtk11">createTheme</span><span class="mtk1">({</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">breakpoints:</span><span class="mtk1"> {</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">values:</span><span class="mtk1"> {</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">xs:</span><span class="mtk1"> </span><span class="mtk7">0</span><span class="mtk1">,</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">sm:</span><span class="mtk1"> </span><span class="mtk7">600</span><span class="mtk1">,</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">md:</span><span class="mtk1"> </span><span class="mtk7">960</span><span class="mtk1">,</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">lg:</span><span class="mtk1"> </span><span class="mtk7">1280</span><span class="mtk1">,</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">xl:</span><span class="mtk1"> </span><span class="mtk7">1920</span><span class="mtk1">,</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">xxl:</span><span class="mtk1"> </span><span class="mtk7">2000</span><span class="mtk1">,</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> },</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> },</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1">});</span></span></span></code></pre> <p>In the above example, we customized the default breakpoints and added a new one called <code>xxl</code> <code>xxl</code> with a value of <code>2000px</code>. We can now use this breakpoint in our components.</p> <pre class="grvsc-container default-dark" data-language="jsx" data-index="6"><code class="grvsc-code"><span class="grvsc-line"><span class="grvsc-source"><span class="mtk17">&lt;</span><span class="mtk10">Box</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">sx</span><span class="mtk1">=</span><span class="mtk4">{</span><span class="mtk1">(</span><span class="mtk12">theme</span><span class="mtk1">) </span><span class="mtk4">=&gt;</span><span class="mtk1"> ({</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">textAlign:</span><span class="mtk1"> </span><span class="mtk8">&#39;center&#39;</span><span class="mtk1">,</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">[theme.breakpoints.</span><span class="mtk11">up</span><span class="mtk12">(</span><span class="mtk8">&#39;xxl&#39;</span><span class="mtk12">)]:</span><span class="mtk1"> { </span><span class="mtk12">textAlign:</span><span class="mtk1"> </span><span class="mtk8">&#39;left&#39;</span><span class="mtk1"> },</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> })</span><span class="mtk4">}</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk17">&gt;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> TEXT</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk17">&lt;/</span><span class="mtk10">Box</span><span class="mtk17">&gt;</span></span></span></code></pre> <p>For more details about customizing the theme in MUI, this tutorial delves deeper into the topic: <a href="https://muhimasri.com/blogs/how-to-customize-theme-and-colors-in-material-ui/">Customizing Theme, Palette, and Colors</a></p> <h2 id="complete-example" style="position:relative;"><a href="#complete-example" aria-label="complete example permalink" class="anchor before"><svg aria-hidden="true" focusable="false" height="16" version="1.1" viewBox="0 0 16 16" width="16"><path fill-rule="evenodd" d="M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z"></path></svg></a>Complete example</h2> <p>Let’s create a responsive header component with more features:</p> <ul> <li>The header will have a logo, a navigation menu, and an email contact icon.</li> <li>The logo will be aligned to the left for screen sizes greater than <code>600px</code> and centered for smaller screen sizes.</li> <li>The navigation menu will be aligned next to the logo for screen sizes greater than <code>600px</code> and hidden for smaller screen sizes.</li> <li>A menu icon will appear and be aligned to the left for screen sizes smaller than <code>600px</code> and hidden for larger screen sizes.</li> <li>The menu icon is just a placeholder for this example and has no functionality, but in a real application, it will open a navigation drawer.</li> </ul> <pre class="grvsc-container grvsc-has-line-highlighting default-dark" data-language="jsx" data-index="7"><code class="grvsc-code"><span class="grvsc-line"><span class="grvsc-source"><span class="mtk15">import</span><span class="mtk1"> </span><span class="mtk4">*</span><span class="mtk1"> </span><span class="mtk15">as</span><span class="mtk1"> </span><span class="mtk12">React</span><span class="mtk1"> </span><span class="mtk15">from</span><span class="mtk1"> </span><span class="mtk8">&#39;react&#39;</span><span class="mtk1">;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk15">import</span><span class="mtk1"> </span><span class="mtk12">Typography</span><span class="mtk1"> </span><span class="mtk15">from</span><span class="mtk1"> </span><span class="mtk8">&#39;@mui/material/Typography&#39;</span><span class="mtk1">;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk15">import</span><span class="mtk1"> { </span><span class="mtk12">Stack</span><span class="mtk1">, </span><span class="mtk12">Toolbar</span><span class="mtk1">, </span><span class="mtk12">AppBar</span><span class="mtk1">, </span><span class="mtk12">Container</span><span class="mtk1">, </span><span class="mtk12">Box</span><span class="mtk1"> } </span><span class="mtk15">from</span><span class="mtk1"> </span><span class="mtk8">&#39;@mui/material&#39;</span><span class="mtk1">;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk15">import</span><span class="mtk1"> </span><span class="mtk12">EmailIcon</span><span class="mtk1"> </span><span class="mtk15">from</span><span class="mtk1"> </span><span class="mtk8">&#39;@mui/icons-material/Email&#39;</span><span class="mtk1">;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk15">import</span><span class="mtk1"> </span><span class="mtk12">LogoDev</span><span class="mtk1"> </span><span class="mtk15">from</span><span class="mtk1"> </span><span class="mtk8">&#39;@mui/icons-material/LogoDev &#39;</span><span class="mtk1">;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk15">import</span><span class="mtk1"> </span><span class="mtk12">MenuIcon</span><span class="mtk1"> </span><span class="mtk15">from</span><span class="mtk1"> </span><span class="mtk8">&#39;@mui/icons-material/Menu&#39;</span><span class="mtk1">;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk4">function</span><span class="mtk1"> </span><span class="mtk11">ResponsiveHeader</span><span class="mtk1">() {</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk15">return</span><span class="mtk1"> (</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk17">&lt;</span><span class="mtk10">AppBar</span><span class="mtk1"> </span><span class="mtk12">position</span><span class="mtk1">=</span><span class="mtk8">&quot;static&quot;</span><span class="mtk17">&gt;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk17">&lt;</span><span class="mtk10">Container</span><span class="mtk17">&gt;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk17">&lt;</span><span class="mtk10">Toolbar</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">disableGutters</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">sx</span><span class="mtk1">=</span><span class="mtk4">{</span><span class="mtk1">{</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">justifyContent:</span><span class="mtk1"> </span><span class="mtk8">&#39;space-between&#39;</span><span class="mtk1">,</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> }</span><span class="mtk4">}</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk17">&gt;</span></span></span> <span class="grvsc-line grvsc-line-highlighted"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk17">&lt;</span><span class="mtk10">MenuIcon</span><span class="mtk1"> </span><span class="mtk12">sx</span><span class="mtk1">=</span><span class="mtk4">{</span><span class="mtk1">{ </span><span class="mtk12">display:</span><span class="mtk1"> { </span><span class="mtk12">xs:</span><span class="mtk1"> </span><span class="mtk8">&#39;block&#39;</span><span class="mtk1">, </span><span class="mtk12">sm:</span><span class="mtk1"> </span><span class="mtk8">&#39;none&#39;</span><span class="mtk1"> } }</span><span class="mtk4">}</span><span class="mtk1"> </span><span class="mtk17">/&gt;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk17">&lt;</span><span class="mtk10">Stack</span><span class="mtk1"> </span><span class="mtk12">direction</span><span class="mtk1">=</span><span class="mtk8">&quot;row&quot;</span><span class="mtk1"> </span><span class="mtk12">alignItems</span><span class="mtk1">=</span><span class="mtk8">&quot;center&quot;</span><span class="mtk17">&gt;</span></span></span> <span class="grvsc-line grvsc-line-highlighted"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk17">&lt;</span><span class="mtk10">LogoDev</span><span class="mtk1"> </span><span class="mtk12">sx</span><span class="mtk1">=</span><span class="mtk4">{</span><span class="mtk1">{ </span><span class="mtk12">mr:</span><span class="mtk1"> </span><span class="mtk7">1</span><span class="mtk1">, </span><span class="mtk12">fontSize:</span><span class="mtk1"> { </span><span class="mtk12">xs:</span><span class="mtk1"> </span><span class="mtk8">&#39;2rem&#39;</span><span class="mtk1">, </span><span class="mtk12">sm:</span><span class="mtk1"> </span><span class="mtk8">&#39;2.6rem&#39;</span><span class="mtk1"> } }</span><span class="mtk4">}</span><span class="mtk1"> </span><span class="mtk17">/&gt;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk17">&lt;</span><span class="mtk10">Typography</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">variant</span><span class="mtk1">=</span><span class="mtk8">&quot;h6&quot;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">sx</span><span class="mtk1">=</span><span class="mtk4">{</span><span class="mtk1">{</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">mr:</span><span class="mtk1"> </span><span class="mtk7">2</span><span class="mtk1">,</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">fontWeight:</span><span class="mtk1"> </span><span class="mtk7">700</span><span class="mtk1">,</span></span></span> <span class="grvsc-line grvsc-line-highlighted"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">letterSpacing:</span><span class="mtk1"> { </span><span class="mtk12">xs:</span><span class="mtk1"> </span><span class="mtk8">&#39;0.1rem&#39;</span><span class="mtk1">, </span><span class="mtk12">sm:</span><span class="mtk1"> </span><span class="mtk8">&#39;0.2rem&#39;</span><span class="mtk1"> },</span></span></span> <span class="grvsc-line grvsc-line-highlighted"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">fontSize:</span><span class="mtk1"> { </span><span class="mtk12">xs:</span><span class="mtk1"> </span><span class="mtk8">&#39;1rem&#39;</span><span class="mtk1">, </span><span class="mtk12">sm:</span><span class="mtk1"> </span><span class="mtk8">&#39;1.2rem&#39;</span><span class="mtk1"> },</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> }</span><span class="mtk4">}</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk17">&gt;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> LOGO</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk17">&lt;/</span><span class="mtk10">Typography</span><span class="mtk17">&gt;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk17">&lt;</span><span class="mtk10">Stack</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">direction</span><span class="mtk1">=</span><span class="mtk8">&quot;row&quot;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">alignItems</span><span class="mtk1">=</span><span class="mtk8">&quot;center&quot;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">gap</span><span class="mtk1">=</span><span class="mtk4">{</span><span class="mtk7">2</span><span class="mtk4">}</span></span></span> <span class="grvsc-line grvsc-line-highlighted"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">sx</span><span class="mtk1">=</span><span class="mtk4">{</span><span class="mtk1">{ </span><span class="mtk12">display:</span><span class="mtk1"> { </span><span class="mtk12">xs:</span><span class="mtk1"> </span><span class="mtk8">&#39;none&#39;</span><span class="mtk1">, </span><span class="mtk12">sm:</span><span class="mtk1"> </span><span class="mtk8">&#39;flex&#39;</span><span class="mtk1"> } }</span><span class="mtk4">}</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk17">&gt;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk17">&lt;</span><span class="mtk10">Typography</span><span class="mtk17">&gt;</span><span class="mtk1">Home</span><span class="mtk17">&lt;/</span><span class="mtk10">Typography</span><span class="mtk17">&gt;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk17">&lt;</span><span class="mtk10">Typography</span><span class="mtk17">&gt;</span><span class="mtk1">About</span><span class="mtk17">&lt;/</span><span class="mtk10">Typography</span><span class="mtk17">&gt;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk17">&lt;</span><span class="mtk10">Typography</span><span class="mtk17">&gt;</span><span class="mtk1">Blog</span><span class="mtk17">&lt;/</span><span class="mtk10">Typography</span><span class="mtk17">&gt;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk17">&lt;/</span><span class="mtk10">Stack</span><span class="mtk17">&gt;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk17">&lt;/</span><span class="mtk10">Stack</span><span class="mtk17">&gt;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk17">&lt;</span><span class="mtk10">EmailIcon</span><span class="mtk1"> </span><span class="mtk17">/&gt;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk17">&lt;/</span><span class="mtk10">Toolbar</span><span class="mtk17">&gt;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk17">&lt;/</span><span class="mtk10">Container</span><span class="mtk17">&gt;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk17">&lt;/</span><span class="mtk10">AppBar</span><span class="mtk17">&gt;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> );</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1">}</span></span></span> <span class="grvsc-line"><span class="grvsc-source"></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk15">export</span><span class="mtk1"> </span><span class="mtk15">default</span><span class="mtk1"> </span><span class="mtk12">ResponsiveHeader</span><span class="mtk1">;</span></span></span></code></pre> <div id="MuiBreakPointTwo" data-code data-height="220px" data-resize style="display:flex;justify-content: center; background: #f3f3f3"></div> <h2 id="summary" style="position:relative;"><a href="#summary" aria-label="summary permalink" class="anchor before"><svg aria-hidden="true" focusable="false" height="16" version="1.1" viewBox="0 0 16 16" width="16"><path fill-rule="evenodd" d="M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z"></path></svg></a>Summary</h2> <p>In this tutorial, we learned how to use and customize MUI breakpoints to create responsive designs. While MUI provides a simple way to add breakpoints using the <code>theme.breakpoints</code> object, we can also use the <code>sx</code> shortcut syntax or <code>useMediaQuery</code> hook to access the breakpoints. Additionally, we can customize the breakpoints values by using a <code>createTheme</code> object for other screen sizes.</p> <p>Bye for now 👋</p> <style class="grvsc-styles"> .grvsc-container { overflow: auto; position: relative; -webkit-overflow-scrolling: touch; padding-top: 1rem; padding-top: var(--grvsc-padding-top, var(--grvsc-padding-v, 1rem)); padding-bottom: 1rem; padding-bottom: var(--grvsc-padding-bottom, var(--grvsc-padding-v, 1rem)); border-radius: 8px; border-radius: var(--grvsc-border-radius, 8px); font-feature-settings: normal; line-height: 1.4; } .grvsc-code { display: table; } .grvsc-line { display: table-row; box-sizing: border-box; width: 100%; position: relative; } .grvsc-line > * { position: relative; } .grvsc-gutter-pad { display: table-cell; padding-left: 0.75rem; padding-left: calc(var(--grvsc-padding-left, var(--grvsc-padding-h, 1.5rem)) / 2); } .grvsc-gutter { display: table-cell; -webkit-user-select: none; -moz-user-select: none; user-select: none; } .grvsc-gutter::before { content: attr(data-content); } .grvsc-source { display: table-cell; padding-left: 1.5rem; padding-left: var(--grvsc-padding-left, var(--grvsc-padding-h, 1.5rem)); padding-right: 1.5rem; padding-right: var(--grvsc-padding-right, var(--grvsc-padding-h, 1.5rem)); } .grvsc-source:empty::after { content: ' '; -webkit-user-select: none; -moz-user-select: none; user-select: none; } .grvsc-gutter + .grvsc-source { padding-left: 0.75rem; padding-left: calc(var(--grvsc-padding-left, var(--grvsc-padding-h, 1.5rem)) / 2); } /* Line transformer styles */ .grvsc-has-line-highlighting > .grvsc-code > .grvsc-line::before { content: ' '; position: absolute; width: 100%; } .grvsc-line-diff-add::before { background-color: var(--grvsc-line-diff-add-background-color, rgba(0, 255, 60, 0.2)); } .grvsc-line-diff-del::before { background-color: var(--grvsc-line-diff-del-background-color, rgba(255, 0, 20, 0.2)); } .grvsc-line-number { padding: 0 2px; text-align: right; opacity: 0.7; } .default-dark { background-color: #1E1E1E; color: #D4D4D4; } .default-dark .mtk17 { color: #808080; } .default-dark .mtk10 { color: #4EC9B0; } .default-dark .mtk1 { color: #D4D4D4; } .default-dark .mtk12 { color: #9CDCFE; } .default-dark .mtk4 { color: #569CD6; } .default-dark .mtk8 { color: #CE9178; } .default-dark .mtk11 { color: #DCDCAA; } .default-dark .mtk15 { color: #C586C0; } .default-dark .mtk7 { color: #B5CEA8; } .default-dark .grvsc-line-highlighted::before { background-color: var(--grvsc-line-highlighted-background-color, rgba(255, 255, 255, 0.1)); box-shadow: inset var(--grvsc-line-highlighted-border-width, 4px) 0 0 0 var(--grvsc-line-highlighted-border-color, rgba(255, 255, 255, 0.5)); } </style><![CDATA[How to Create Global Styles in Material UI (MUI)]]>https://muhimasri.commui-global-styleshttps://muhimasri.commui-global-styles<p>In every application, specifically modern front-end apps, we tend to encapsulate styles to a specific component. This great practice helps us avoid style collisions and keep the codebase clean and maintainable. But in certain scenarios, we need to create global styles that can be applied to elements across the entire application. For example, we might need to reset the default styles of the <code>&#x3C;body></code> tag or create a global theme that all components can use, and so on.</p> <p>In this tutorial, we will explore different techniques for creating and applying MUI global styles.</p> <h2 id="customizing-the-theme" style="position:relative;"><a href="#customizing-the-theme" aria-label="customizing the theme permalink" class="anchor before"><svg aria-hidden="true" focusable="false" height="16" version="1.1" viewBox="0 0 16 16" width="16"><path fill-rule="evenodd" d="M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z"></path></svg></a>Customizing the theme</h2> <p>The first and most common way to create global styles in MUI is by customizing the theme. The theme is a global object containing all the application styles and configurations. All components use it and can be accessed from anywhere in the application. We’ve covered the theme in more detail in <a href="https://muhimasri.com/blogs/how-to-customize-theme-and-colors-in-material-ui/">this tutorial</a>.</p> <p>Let’s create a simple app with a few unstyled components and see the initial result.</p> <pre class="grvsc-container default-dark" data-language="jsx" data-index="0"><code class="grvsc-code"><span class="grvsc-line"><span class="grvsc-source"><span class="mtk15">import</span><span class="mtk1"> </span><span class="mtk12">React</span><span class="mtk1"> </span><span class="mtk15">from</span><span class="mtk1"> </span><span class="mtk8">&quot;react&quot;</span><span class="mtk1">;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk15">import</span><span class="mtk1"> { </span><span class="mtk12">Typography</span><span class="mtk1">, </span><span class="mtk12">Button</span><span class="mtk1">, </span><span class="mtk12">Box</span><span class="mtk1"> } </span><span class="mtk15">from</span><span class="mtk1"> </span><span class="mtk8">&quot;@mui/material&quot;</span><span class="mtk1">;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk4">function</span><span class="mtk1"> </span><span class="mtk11">App</span><span class="mtk1">() {</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk15">return</span><span class="mtk1"> (</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk17">&lt;</span><span class="mtk10">Box</span><span class="mtk17">&gt;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk17">&lt;</span><span class="mtk10">Typography</span><span class="mtk1"> </span><span class="mtk12">variant</span><span class="mtk1">=</span><span class="mtk8">&quot;h1&quot;</span><span class="mtk17">&gt;</span><span class="mtk1">Hello, World!</span><span class="mtk17">&lt;/</span><span class="mtk10">Typography</span><span class="mtk17">&gt;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk17">&lt;</span><span class="mtk10">Typography</span><span class="mtk1"> </span><span class="mtk12">variant</span><span class="mtk1">=</span><span class="mtk8">&quot;p&quot;</span><span class="mtk17">&gt;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> This is a paragraph of text that should be affected by the global</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> styles.</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk17">&lt;/</span><span class="mtk10">Typography</span><span class="mtk17">&gt;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk17">&lt;</span><span class="mtk10">Button</span><span class="mtk1"> </span><span class="mtk12">variant</span><span class="mtk1">=</span><span class="mtk8">&quot;contained&quot;</span><span class="mtk1"> </span><span class="mtk12">color</span><span class="mtk1">=</span><span class="mtk8">&quot;primary&quot;</span><span class="mtk17">&gt;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> A Styled Button Contained</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk17">&lt;/</span><span class="mtk10">Button</span><span class="mtk17">&gt;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk17">&lt;</span><span class="mtk10">Button</span><span class="mtk1"> </span><span class="mtk12">variant</span><span class="mtk1">=</span><span class="mtk8">&quot;outlined&quot;</span><span class="mtk1"> </span><span class="mtk12">color</span><span class="mtk1">=</span><span class="mtk8">&quot;secondary&quot;</span><span class="mtk17">&gt;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> A Styled Button Outlined</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk17">&lt;/</span><span class="mtk10">Button</span><span class="mtk17">&gt;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk4">{</span><span class="mtk3">/* Other components go here */</span><span class="mtk4">}</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk17">&lt;/</span><span class="mtk10">Box</span><span class="mtk17">&gt;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> );</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1">}</span></span></span> <span class="grvsc-line"><span class="grvsc-source"></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk15">export</span><span class="mtk1"> </span><span class="mtk15">default</span><span class="mtk1"> </span><span class="mtk12">App</span></span></span></code></pre> <p><span class="gatsby-resp-image-wrapper" style="position: relative; display: block; margin-left: auto; margin-right: auto; max-width: 720px; " > <a class="gatsby-resp-image-link" href="/static/a03645f56826fa22a798bb62dbafee2e/5caea/theme-unstyled.png" style="display: block" target="_blank" rel="noopener" > <span class="gatsby-resp-image-background-image" style="padding-bottom: 39.44444444444444%; position: relative; bottom: 0; left: 0; background-image: url('data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABQAAAAICAYAAAD5nd/tAAAACXBIWXMAABnWAAAZ1gEY0crtAAABvElEQVR42q2Q204TURSG52WMd54ufQffSBNavPBGxHhRq6kJh1YMmqAVMGoEQtuooZYWOzGIzoHODHPqYaa0hWn7uZl64AFcyZe9/z9r/StZkuM4hGFAs9nkrHzfR1W1+D8ajf56uq4LX8WxbYbn/P5ggO/5KIpCNBwiZbNZFubnyOaeks+/Zvn5MrOz9ylsb7OzU44Hy+Uy6XSaVCpFLpelUCywtrbK40dp3r57TyaTYWFxkbDbRVp5ucLnTx+ZmblHMplkToRPJRK8yudZWnpGFA1RlR88FIEvxLK7om9ra5Pk9G3W11dF2BMxM0+pVOTk9BSp3WoyGPTptFsYukLLd2N05YBD9SeWZYrQCMs08TyPdquFLMs4rksQdDAMg3pdphME8Ymk8nebjV2NomyxWdPYqKgU6yalb0cU6g0+CH2gGXi2i3FoYBqWuFkT+8imoTewLRvP9eKlZyXdeLDPxVs1rib3uDRV43JijyvTX7kmuH5H5sLNKm++eNA9IbCP6QpCZ8Kx2yMwQnrtvogaTwL3rS4VLaSmh1QFu1oQv1U9iL2K0EEvivvHw/GE0Tl+6z8ljcf/xP+oX2qBN/WQ3yXeAAAAAElFTkSuQmCC'); background-size: cover; display: block;" ></span> <img class="gatsby-resp-image-image" alt="MUI theme styles" title="" src="/static/a03645f56826fa22a798bb62dbafee2e/37523/theme-unstyled.png" srcset="/static/a03645f56826fa22a798bb62dbafee2e/e9ff0/theme-unstyled.png 180w, /static/a03645f56826fa22a798bb62dbafee2e/f21e7/theme-unstyled.png 360w, /static/a03645f56826fa22a798bb62dbafee2e/37523/theme-unstyled.png 720w, /static/a03645f56826fa22a798bb62dbafee2e/5caea/theme-unstyled.png 996w" sizes="(max-width: 720px) 100vw, 720px" style="width:100%;height:100%;margin:0;vertical-align:middle;position:absolute;top:0;left:0;" loading="lazy" decoding="async" /> </a> </span></p> <p>In the following example, we’ll demonstrate how to use <code>createTheme</code> and <code>ThemeProvider</code> to set global styles that affect all instances of <code>Typography</code> and <code>Button</code> components.</p> <pre class="grvsc-container grvsc-has-line-highlighting default-dark" data-language="jsx" data-index="1"><code class="grvsc-code"><span class="grvsc-line"><span class="grvsc-source"><span class="mtk15">import</span><span class="mtk1"> </span><span class="mtk12">React</span><span class="mtk1"> </span><span class="mtk15">from</span><span class="mtk1"> </span><span class="mtk8">&quot;react&quot;</span><span class="mtk1">;</span></span></span> <span class="grvsc-line grvsc-line-highlighted"><span class="grvsc-source"><span class="mtk15">import</span><span class="mtk1"> { </span><span class="mtk12">createTheme</span><span class="mtk1">, </span><span class="mtk12">ThemeProvider</span><span class="mtk1">, </span><span class="mtk12">Typography</span><span class="mtk1">, </span><span class="mtk12">Button</span><span class="mtk1">, </span><span class="mtk12">Box</span><span class="mtk1"> } </span><span class="mtk15">from</span><span class="mtk1"> </span><span class="mtk8">&quot;@mui/material&quot;</span><span class="mtk1">;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk3">// Create a theme instance with global overrides.</span></span></span> <span class="grvsc-line grvsc-line-highlighted"><span class="grvsc-source"><span class="mtk4">const</span><span class="mtk1"> </span><span class="mtk12">theme</span><span class="mtk1"> = </span><span class="mtk11">createTheme</span><span class="mtk1">({</span></span></span> <span class="grvsc-line grvsc-line-highlighted"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">components:</span><span class="mtk1"> {</span></span></span> <span class="grvsc-line grvsc-line-highlighted"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">MuiTypography:</span><span class="mtk1"> {</span></span></span> <span class="grvsc-line grvsc-line-highlighted"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">styleOverrides:</span><span class="mtk1"> {</span></span></span> <span class="grvsc-line grvsc-line-highlighted"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">root:</span><span class="mtk1"> {</span></span></span> <span class="grvsc-line grvsc-line-highlighted"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">fontFamily:</span><span class="mtk1"> </span><span class="mtk8">&quot;Comic Sans MS, sans-serif&quot;</span></span></span> <span class="grvsc-line grvsc-line-highlighted"><span class="grvsc-source"><span class="mtk1"> },</span></span></span> <span class="grvsc-line grvsc-line-highlighted"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">h1:</span><span class="mtk1"> {</span></span></span> <span class="grvsc-line grvsc-line-highlighted"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">fontSize:</span><span class="mtk1"> </span><span class="mtk8">&quot;2.5rem&quot;</span><span class="mtk1">,</span></span></span> <span class="grvsc-line grvsc-line-highlighted"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">color:</span><span class="mtk1"> </span><span class="mtk8">&quot;green&quot;</span></span></span> <span class="grvsc-line grvsc-line-highlighted"><span class="grvsc-source"><span class="mtk1"> },</span></span></span> <span class="grvsc-line grvsc-line-highlighted"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">p:</span><span class="mtk1"> {</span></span></span> <span class="grvsc-line grvsc-line-highlighted"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">fontSize:</span><span class="mtk1"> </span><span class="mtk8">&quot;1.4rem&quot;</span></span></span> <span class="grvsc-line grvsc-line-highlighted"><span class="grvsc-source"><span class="mtk1"> }</span></span></span> <span class="grvsc-line grvsc-line-highlighted"><span class="grvsc-source"><span class="mtk1"> }</span></span></span> <span class="grvsc-line grvsc-line-highlighted"><span class="grvsc-source"><span class="mtk1"> },</span></span></span> <span class="grvsc-line grvsc-line-highlighted"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">MuiButton:</span><span class="mtk1"> {</span></span></span> <span class="grvsc-line grvsc-line-highlighted"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">styleOverrides:</span><span class="mtk1"> {</span></span></span> <span class="grvsc-line grvsc-line-highlighted"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">root:</span><span class="mtk1"> {</span></span></span> <span class="grvsc-line grvsc-line-highlighted"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">borderRadius:</span><span class="mtk1"> </span><span class="mtk8">&quot;8px&quot;</span><span class="mtk1">,</span></span></span> <span class="grvsc-line grvsc-line-highlighted"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">textTransform:</span><span class="mtk1"> </span><span class="mtk8">&quot;none&quot;</span><span class="mtk1">,</span></span></span> <span class="grvsc-line grvsc-line-highlighted"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">fontSize:</span><span class="mtk1"> </span><span class="mtk8">&quot;1.4rem&quot;</span></span></span> <span class="grvsc-line grvsc-line-highlighted"><span class="grvsc-source"><span class="mtk1"> }</span></span></span> <span class="grvsc-line grvsc-line-highlighted"><span class="grvsc-source"><span class="mtk1"> }</span></span></span> <span class="grvsc-line grvsc-line-highlighted"><span class="grvsc-source"><span class="mtk1"> }</span></span></span> <span class="grvsc-line grvsc-line-highlighted"><span class="grvsc-source"><span class="mtk1"> }</span></span></span> <span class="grvsc-line grvsc-line-highlighted"><span class="grvsc-source"><span class="mtk1">});</span></span></span> <span class="grvsc-line"><span class="grvsc-source"></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk4">function</span><span class="mtk1"> </span><span class="mtk11">App</span><span class="mtk1">() {</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk15">return</span><span class="mtk1"> (</span></span></span> <span class="grvsc-line grvsc-line-highlighted"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk17">&lt;</span><span class="mtk10">ThemeProvider</span><span class="mtk1"> </span><span class="mtk12">theme</span><span class="mtk1">=</span><span class="mtk4">{</span><span class="mtk12">theme</span><span class="mtk4">}</span><span class="mtk17">&gt;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk17">&lt;</span><span class="mtk10">Box</span><span class="mtk17">&gt;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk17">&lt;</span><span class="mtk10">Typography</span><span class="mtk1"> </span><span class="mtk12">variant</span><span class="mtk1">=</span><span class="mtk8">&quot;h1&quot;</span><span class="mtk17">&gt;</span><span class="mtk1">Hello, World!</span><span class="mtk17">&lt;/</span><span class="mtk10">Typography</span><span class="mtk17">&gt;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk17">&lt;</span><span class="mtk10">Typography</span><span class="mtk1"> </span><span class="mtk12">variant</span><span class="mtk1">=</span><span class="mtk8">&quot;p&quot;</span><span class="mtk17">&gt;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> This is a paragraph of text that should be affected by the global</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> styles.</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk17">&lt;/</span><span class="mtk10">Typography</span><span class="mtk17">&gt;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk17">&lt;</span><span class="mtk10">Button</span><span class="mtk1"> </span><span class="mtk12">variant</span><span class="mtk1">=</span><span class="mtk8">&quot;contained&quot;</span><span class="mtk1"> </span><span class="mtk12">color</span><span class="mtk1">=</span><span class="mtk8">&quot;primary&quot;</span><span class="mtk17">&gt;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> A Styled Button Contained</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk17">&lt;/</span><span class="mtk10">Button</span><span class="mtk17">&gt;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk17">&lt;</span><span class="mtk10">Button</span><span class="mtk1"> </span><span class="mtk12">variant</span><span class="mtk1">=</span><span class="mtk8">&quot;outlined&quot;</span><span class="mtk1"> </span><span class="mtk12">color</span><span class="mtk1">=</span><span class="mtk8">&quot;secondary&quot;</span><span class="mtk17">&gt;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> A Styled Button Outlined</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk17">&lt;/</span><span class="mtk10">Button</span><span class="mtk17">&gt;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk4">{</span><span class="mtk3">/* Other components go here */</span><span class="mtk4">}</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk17">&lt;/</span><span class="mtk10">Box</span><span class="mtk17">&gt;</span></span></span> <span class="grvsc-line grvsc-line-highlighted"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk17">&lt;/</span><span class="mtk10">ThemeProvider</span><span class="mtk17">&gt;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> );</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1">}</span></span></span> <span class="grvsc-line"><span class="grvsc-source"></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk15">export</span><span class="mtk1"> </span><span class="mtk15">default</span><span class="mtk1"> </span><span class="mtk12">App</span><span class="mtk1">;</span></span></span></code></pre> <p><span class="gatsby-resp-image-wrapper" style="position: relative; display: block; margin-left: auto; margin-right: auto; max-width: 720px; " > <a class="gatsby-resp-image-link" href="/static/44bfdb1c0997f6d9faf86449d28af257/b2982/theme-styled.png" style="display: block" target="_blank" rel="noopener" > <span class="gatsby-resp-image-background-image" style="padding-bottom: 25.555555555555554%; position: relative; bottom: 0; left: 0; background-image: url('data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABQAAAAFCAYAAABFA8wzAAAACXBIWXMAABJ0AAASdAHeZh94AAAA9ElEQVR42o2QTUvDQBRF81fdVBeKFFz6PwR3okXFtS6kCCJCaakItVhSbBLTpm2G6VeSSY01x5noMoJ3ONz73oM3zFitoM2998DtW515uqDu3PHoN3iedrju3yCVxCjX5z+yfNmjF7bpjpuIpctAdHidtBgtbJpuA7mSpKkiTuKCRGlMjo0nRFFUZKXUz8LDK5fqmUP1pM/W0RPbxy8c1Bz2dN21JbOhYDgIGHuTgpETMA1C5EwShmGBEAIpJXmeY+1felT0wt0LT/POTk37uUvl1MX2E1htSGXGxzwjW36y1nmz/vr7yfz+UJnMjWVj0y/D6BtcunJru+l/zAAAAABJRU5ErkJggg=='); background-size: cover; display: block;" ></span> <img class="gatsby-resp-image-image" alt="MUI theme styles" title="" src="/static/44bfdb1c0997f6d9faf86449d28af257/37523/theme-styled.png" srcset="/static/44bfdb1c0997f6d9faf86449d28af257/e9ff0/theme-styled.png 180w, /static/44bfdb1c0997f6d9faf86449d28af257/f21e7/theme-styled.png 360w, /static/44bfdb1c0997f6d9faf86449d28af257/37523/theme-styled.png 720w, /static/44bfdb1c0997f6d9faf86449d28af257/b2982/theme-styled.png 729w" sizes="(max-width: 720px) 100vw, 720px" style="width:100%;height:100%;margin:0;vertical-align:middle;position:absolute;top:0;left:0;" loading="lazy" decoding="async" /> </a> </span></p> <p>What we just did only works for MUI components that are rendered inside <code>ThemeProvider</code>. If we want to apply styles to other HTML elements such as <code>&#x3C;body></code> and <code>&#x3C;html></code>, we need to use <code>CssBaseline</code> component. This component is used to apply a baseline or reset styles to the document for cross-browser consistency, and it will allow us to style the <code>&#x3C;body></code> and <code>&#x3C;html></code> elements.</p> <pre class="grvsc-container grvsc-has-line-highlighting default-dark" data-language="jsx" data-index="2"><code class="grvsc-code"><span class="grvsc-line"><span class="grvsc-source"><span class="mtk15">import</span><span class="mtk1"> </span><span class="mtk12">React</span><span class="mtk1"> </span><span class="mtk15">from</span><span class="mtk1"> </span><span class="mtk8">&quot;react&quot;</span><span class="mtk1">;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk15">import</span><span class="mtk1"> {</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">createTheme</span><span class="mtk1">,</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">ThemeProvider</span><span class="mtk1">,</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">Typography</span><span class="mtk1">,</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">Button</span><span class="mtk1">,</span></span></span> <span class="grvsc-line grvsc-line-highlighted"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">CssBaseline</span><span class="mtk1">,</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">Box</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1">} </span><span class="mtk15">from</span><span class="mtk1"> </span><span class="mtk8">&quot;@mui/material&quot;</span><span class="mtk1">;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk3">// Create a theme instance with global overrides.</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk4">const</span><span class="mtk1"> </span><span class="mtk12">theme</span><span class="mtk1"> = </span><span class="mtk11">createTheme</span><span class="mtk1">({</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">components:</span><span class="mtk1"> {</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">MuiTypography:</span><span class="mtk1"> {</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">styleOverrides:</span><span class="mtk1"> {</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">root:</span><span class="mtk1"> {</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">fontFamily:</span><span class="mtk1"> </span><span class="mtk8">&quot;Comic Sans MS, sans-serif&quot;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> },</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">h1:</span><span class="mtk1"> {</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">fontSize:</span><span class="mtk1"> </span><span class="mtk8">&quot;2.5rem&quot;</span><span class="mtk1">,</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">color:</span><span class="mtk1"> </span><span class="mtk8">&quot;green&quot;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> },</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">p:</span><span class="mtk1"> {</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">fontSize:</span><span class="mtk1"> </span><span class="mtk8">&quot;1.4rem&quot;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> }</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> }</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> },</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">MuiButton:</span><span class="mtk1"> {</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">styleOverrides:</span><span class="mtk1"> {</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">root:</span><span class="mtk1"> {</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">borderRadius:</span><span class="mtk1"> </span><span class="mtk8">&quot;8px&quot;</span><span class="mtk1">,</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">textTransform:</span><span class="mtk1"> </span><span class="mtk8">&quot;none&quot;</span><span class="mtk1">,</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">fontSize:</span><span class="mtk1"> </span><span class="mtk8">&quot;1.4rem&quot;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> }</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> }</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> },</span></span></span> <span class="grvsc-line grvsc-line-highlighted"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">MuiCssBaseline:</span><span class="mtk1"> {</span></span></span> <span class="grvsc-line grvsc-line-highlighted"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">styleOverrides:</span><span class="mtk1"> {</span></span></span> <span class="grvsc-line grvsc-line-highlighted"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">html:</span><span class="mtk1"> {</span></span></span> <span class="grvsc-line grvsc-line-highlighted"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">fontSize:</span><span class="mtk1"> </span><span class="mtk8">&quot;62.5%&quot;</span></span></span> <span class="grvsc-line grvsc-line-highlighted"><span class="grvsc-source"><span class="mtk1"> }</span></span></span> <span class="grvsc-line grvsc-line-highlighted"><span class="grvsc-source"><span class="mtk1"> }</span></span></span> <span class="grvsc-line grvsc-line-highlighted"><span class="grvsc-source"><span class="mtk1"> }</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> }</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1">});</span></span></span> <span class="grvsc-line"><span class="grvsc-source"></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk4">function</span><span class="mtk1"> </span><span class="mtk11">App</span><span class="mtk1">() {</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk15">return</span><span class="mtk1"> (</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk17">&lt;</span><span class="mtk10">ThemeProvider</span><span class="mtk1"> </span><span class="mtk12">theme</span><span class="mtk1">=</span><span class="mtk4">{</span><span class="mtk12">theme</span><span class="mtk4">}</span><span class="mtk17">&gt;</span></span></span> <span class="grvsc-line grvsc-line-highlighted"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk17">&lt;</span><span class="mtk10">CssBaseline</span><span class="mtk1"> </span><span class="mtk17">/&gt;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk17">&lt;</span><span class="mtk10">Box</span><span class="mtk17">&gt;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk17">&lt;</span><span class="mtk10">Typography</span><span class="mtk1"> </span><span class="mtk12">variant</span><span class="mtk1">=</span><span class="mtk8">&quot;h1&quot;</span><span class="mtk17">&gt;</span><span class="mtk1">Hello, World!</span><span class="mtk17">&lt;/</span><span class="mtk10">Typography</span><span class="mtk17">&gt;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk17">&lt;</span><span class="mtk10">Typography</span><span class="mtk1"> </span><span class="mtk12">variant</span><span class="mtk1">=</span><span class="mtk8">&quot;p&quot;</span><span class="mtk17">&gt;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> This is a paragraph of text that should be affected by the global</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> styles.</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk17">&lt;/</span><span class="mtk10">Typography</span><span class="mtk17">&gt;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk17">&lt;</span><span class="mtk10">Button</span><span class="mtk1"> </span><span class="mtk12">variant</span><span class="mtk1">=</span><span class="mtk8">&quot;contained&quot;</span><span class="mtk1"> </span><span class="mtk12">color</span><span class="mtk1">=</span><span class="mtk8">&quot;primary&quot;</span><span class="mtk17">&gt;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> A Styled Button Contained</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk17">&lt;/</span><span class="mtk10">Button</span><span class="mtk17">&gt;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk17">&lt;</span><span class="mtk10">Button</span><span class="mtk1"> </span><span class="mtk12">variant</span><span class="mtk1">=</span><span class="mtk8">&quot;outlined&quot;</span><span class="mtk1"> </span><span class="mtk12">color</span><span class="mtk1">=</span><span class="mtk8">&quot;secondary&quot;</span><span class="mtk17">&gt;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> A Styled Button Outlined</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk17">&lt;/</span><span class="mtk10">Button</span><span class="mtk17">&gt;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk4">{</span><span class="mtk3">/* Other components go here */</span><span class="mtk4">}</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk17">&lt;/</span><span class="mtk10">Box</span><span class="mtk17">&gt;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk17">&lt;/</span><span class="mtk10">ThemeProvider</span><span class="mtk17">&gt;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> );</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1">}</span></span></span> <span class="grvsc-line"><span class="grvsc-source"></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk15">export</span><span class="mtk1"> </span><span class="mtk15">default</span><span class="mtk1"> </span><span class="mtk12">App</span><span class="mtk1">;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"></span></span></code></pre> <p>In the above example, we reduced the default font size of the <code>&#x3C;html></code> element to <code>62.5%</code>, equivalent to <code>10px</code>. It’s a common technique used to make the entire document’s font size relative to the browser’s default font size.</p> <h2 id="using-globalstyles-component" style="position:relative;"><a href="#using-globalstyles-component" aria-label="using globalstyles component permalink" class="anchor before"><svg aria-hidden="true" focusable="false" height="16" version="1.1" viewBox="0 0 16 16" width="16"><path fill-rule="evenodd" d="M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z"></path></svg></a>Using GlobalStyles Component</h2> <p>The <code>GlobalStyles</code> component is used for injecting global CSS into the document. This is particularly helpful when we want to style HTML elements that are not directly handled by MUI components or for creating our own custom CSS reset.</p> <p>In the following example, we’ll create a new global object called <code>globalStyles</code> and use it to style the <code>&#x3C;body></code> and <code>&#x3C;html></code> elements.</p> <pre class="grvsc-container grvsc-has-line-highlighting default-dark" data-language="jsx" data-index="3"><code class="grvsc-code"><span class="grvsc-line"><span class="grvsc-source"><span class="mtk15">import</span><span class="mtk1"> </span><span class="mtk12">React</span><span class="mtk1"> </span><span class="mtk15">from</span><span class="mtk1"> </span><span class="mtk8">&quot;react&quot;</span><span class="mtk1">;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk15">import</span><span class="mtk1"> {</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">createTheme</span><span class="mtk1">,</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">ThemeProvider</span><span class="mtk1">,</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">Typography</span><span class="mtk1">,</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">Button</span><span class="mtk1">,</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">CssBaseline</span><span class="mtk1">,</span></span></span> <span class="grvsc-line grvsc-line-highlighted"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">GlobalStyles</span><span class="mtk1">,</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">Box</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1">} </span><span class="mtk15">from</span><span class="mtk1"> </span><span class="mtk8">&quot;@mui/material&quot;</span><span class="mtk1">;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk3">// Create a theme instance with global overrides.</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk4">const</span><span class="mtk1"> </span><span class="mtk12">theme</span><span class="mtk1"> = </span><span class="mtk11">createTheme</span><span class="mtk1">({</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> ...</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1">});</span></span></span> <span class="grvsc-line"><span class="grvsc-source"></span></span> <span class="grvsc-line grvsc-line-highlighted"><span class="grvsc-source"><span class="mtk4">const</span><span class="mtk1"> </span><span class="mtk11">globalStyles</span><span class="mtk1"> = (</span></span></span> <span class="grvsc-line grvsc-line-highlighted"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk17">&lt;</span><span class="mtk10">GlobalStyles</span></span></span> <span class="grvsc-line grvsc-line-highlighted"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">styles</span><span class="mtk1">=</span><span class="mtk4">{</span><span class="mtk1">(</span><span class="mtk12">theme</span><span class="mtk1">) </span><span class="mtk4">=&gt;</span><span class="mtk1"> ({</span></span></span> <span class="grvsc-line grvsc-line-highlighted"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">html:</span><span class="mtk1"> {</span></span></span> <span class="grvsc-line grvsc-line-highlighted"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">height:</span><span class="mtk1"> </span><span class="mtk8">&quot;100%&quot;</span><span class="mtk1">,</span></span></span> <span class="grvsc-line grvsc-line-highlighted"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">fontSize:</span><span class="mtk1"> </span><span class="mtk8">&quot;62.5%&quot;</span></span></span> <span class="grvsc-line grvsc-line-highlighted"><span class="grvsc-source"><span class="mtk1"> },</span></span></span> <span class="grvsc-line grvsc-line-highlighted"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">body:</span><span class="mtk1"> {</span></span></span> <span class="grvsc-line grvsc-line-highlighted"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">margin:</span><span class="mtk1"> </span><span class="mtk7">0</span><span class="mtk1">,</span></span></span> <span class="grvsc-line grvsc-line-highlighted"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">padding:</span><span class="mtk1"> </span><span class="mtk12">theme</span><span class="mtk1">.</span><span class="mtk11">spacing</span><span class="mtk1">(</span><span class="mtk7">2</span><span class="mtk1">),</span></span></span> <span class="grvsc-line grvsc-line-highlighted"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">backgroundColor:</span><span class="mtk1"> </span><span class="mtk12">theme</span><span class="mtk1">.</span><span class="mtk12">palette</span><span class="mtk1">.</span><span class="mtk12">background</span><span class="mtk1">.</span><span class="mtk12">default</span><span class="mtk1">,</span></span></span> <span class="grvsc-line grvsc-line-highlighted"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">color:</span><span class="mtk1"> </span><span class="mtk12">theme</span><span class="mtk1">.</span><span class="mtk12">palette</span><span class="mtk1">.</span><span class="mtk12">text</span><span class="mtk1">.</span><span class="mtk12">primary</span><span class="mtk1">,</span></span></span> <span class="grvsc-line grvsc-line-highlighted"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">fontFamily:</span><span class="mtk1"> </span><span class="mtk12">theme</span><span class="mtk1">.</span><span class="mtk12">typography</span><span class="mtk1">.</span><span class="mtk12">fontFamily</span></span></span> <span class="grvsc-line grvsc-line-highlighted"><span class="grvsc-source"><span class="mtk1"> }</span></span></span> <span class="grvsc-line grvsc-line-highlighted"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk3">// ... You can add more global styles here</span></span></span> <span class="grvsc-line grvsc-line-highlighted"><span class="grvsc-source"><span class="mtk1"> })</span><span class="mtk4">}</span></span></span> <span class="grvsc-line grvsc-line-highlighted"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk17">/&gt;</span></span></span> <span class="grvsc-line grvsc-line-highlighted"><span class="grvsc-source"><span class="mtk1">);</span></span></span> <span class="grvsc-line"><span class="grvsc-source"></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk4">function</span><span class="mtk1"> </span><span class="mtk11">App</span><span class="mtk1">() {</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk15">return</span><span class="mtk1"> (</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk17">&lt;</span><span class="mtk10">ThemeProvider</span><span class="mtk1"> </span><span class="mtk12">theme</span><span class="mtk1">=</span><span class="mtk4">{</span><span class="mtk12">theme</span><span class="mtk4">}</span><span class="mtk17">&gt;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk17">&lt;</span><span class="mtk10">CssBaseline</span><span class="mtk1"> </span><span class="mtk17">/&gt;</span></span></span> <span class="grvsc-line grvsc-line-highlighted"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk4">{</span><span class="mtk12">globalStyles</span><span class="mtk4">}</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk17">&lt;</span><span class="mtk10">Box</span><span class="mtk17">&gt;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk17">&lt;</span><span class="mtk10">Typography</span><span class="mtk1"> </span><span class="mtk12">variant</span><span class="mtk1">=</span><span class="mtk8">&quot;h1&quot;</span><span class="mtk17">&gt;</span><span class="mtk1">Hello, World!</span><span class="mtk17">&lt;/</span><span class="mtk10">Typography</span><span class="mtk17">&gt;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk17">&lt;</span><span class="mtk10">Typography</span><span class="mtk1"> </span><span class="mtk12">variant</span><span class="mtk1">=</span><span class="mtk8">&quot;p&quot;</span><span class="mtk17">&gt;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> This is a paragraph of text that should be affected by the global</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> styles.</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk17">&lt;/</span><span class="mtk10">Typography</span><span class="mtk17">&gt;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk17">&lt;</span><span class="mtk10">Button</span><span class="mtk1"> </span><span class="mtk12">variant</span><span class="mtk1">=</span><span class="mtk8">&quot;contained&quot;</span><span class="mtk1"> </span><span class="mtk12">color</span><span class="mtk1">=</span><span class="mtk8">&quot;primary&quot;</span><span class="mtk17">&gt;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> A Styled Button Contained</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk17">&lt;/</span><span class="mtk10">Button</span><span class="mtk17">&gt;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk17">&lt;</span><span class="mtk10">Button</span><span class="mtk1"> </span><span class="mtk12">variant</span><span class="mtk1">=</span><span class="mtk8">&quot;outlined&quot;</span><span class="mtk1"> </span><span class="mtk12">color</span><span class="mtk1">=</span><span class="mtk8">&quot;secondary&quot;</span><span class="mtk17">&gt;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> A Styled Button Outlined</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk17">&lt;/</span><span class="mtk10">Button</span><span class="mtk17">&gt;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk4">{</span><span class="mtk3">/* Other components go here */</span><span class="mtk4">}</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk17">&lt;/</span><span class="mtk10">Box</span><span class="mtk17">&gt;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk17">&lt;/</span><span class="mtk10">ThemeProvider</span><span class="mtk17">&gt;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> );</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1">}</span></span></span> <span class="grvsc-line"><span class="grvsc-source"></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk15">export</span><span class="mtk1"> </span><span class="mtk15">default</span><span class="mtk1"> </span><span class="mtk12">App</span><span class="mtk1">;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"></span></span></code></pre> <p>If we want to style MUI components, we can use CSS selectors to target them. For example, we can use the following selector to style all MUI <code>Button</code> components.</p> <pre class="grvsc-container default-dark" data-language="jsx" data-index="4"><code class="grvsc-code"><span class="grvsc-line"><span class="grvsc-source"><span class="mtk4">const</span><span class="mtk1"> </span><span class="mtk11">globalStyles</span><span class="mtk1"> = (</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk17">&lt;</span><span class="mtk10">GlobalStyles</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">styles</span><span class="mtk1">=</span><span class="mtk4">{</span><span class="mtk1">(</span><span class="mtk12">theme</span><span class="mtk1">) </span><span class="mtk4">=&gt;</span><span class="mtk1"> ({</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> ...</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk8">&quot;.MuiButton-root&quot;</span><span class="mtk1">: {</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">margin:</span><span class="mtk1"> </span><span class="mtk12">theme</span><span class="mtk1">.</span><span class="mtk11">spacing</span><span class="mtk1">(</span><span class="mtk7">1</span><span class="mtk1">)</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> }</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> })</span><span class="mtk4">}</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk17">/&gt;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1">);</span></span></span></code></pre> <p>But in general, <code>createTheme</code> is a better approach for styling MUI components as it provides a more intuitive API to override styles.</p> <p>However, <code>GlobalStyles</code> would be a better option for styling elements outside the MUI components tree, especially if we create a custom CSS reset.</p> <h2 id="styling-parentroot-component" style="position:relative;"><a href="#styling-parentroot-component" aria-label="styling parentroot component permalink" class="anchor before"><svg aria-hidden="true" focusable="false" height="16" version="1.1" viewBox="0 0 16 16" width="16"><path fill-rule="evenodd" d="M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z"></path></svg></a>Styling Parent/Root Component</h2> <p>Another way to create global styles is through the parent or root component, which is an excellent approach if we want to style a subset of components or apply a common layout to all pages in the application.</p> <p>In the following example, we’ll create a boxed layout component with a maximum width of <code>1200px</code> centered horizontally along with other global styles.</p> <pre class="grvsc-container grvsc-has-line-highlighting default-dark" data-language="jsx" data-index="5"><code class="grvsc-code"><span class="grvsc-line"><span class="grvsc-source"><span class="mtk15">import</span><span class="mtk1"> </span><span class="mtk12">React</span><span class="mtk1"> </span><span class="mtk15">from</span><span class="mtk1"> </span><span class="mtk8">&quot;react&quot;</span><span class="mtk1">;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk15">import</span><span class="mtk1"> {</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">createTheme</span><span class="mtk1">,</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">ThemeProvider</span><span class="mtk1">,</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">Typography</span><span class="mtk1">,</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">Button</span><span class="mtk1">,</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">CssBaseline</span><span class="mtk1">,</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">Box</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1">} </span><span class="mtk15">from</span><span class="mtk1"> </span><span class="mtk8">&quot;@mui/material&quot;</span><span class="mtk1">;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk3">// Create a theme instance with global overrides.</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk4">const</span><span class="mtk1"> </span><span class="mtk12">theme</span><span class="mtk1"> = </span><span class="mtk11">createTheme</span><span class="mtk1">({</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> ...</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1">});</span></span></span> <span class="grvsc-line"><span class="grvsc-source"></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk4">const</span><span class="mtk1"> </span><span class="mtk11">globalStyles</span><span class="mtk1"> = (</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> ...</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1">);</span></span></span> <span class="grvsc-line"><span class="grvsc-source"></span></span> <span class="grvsc-line grvsc-line-highlighted"><span class="grvsc-source"><span class="mtk4">const</span><span class="mtk1"> </span><span class="mtk11">Layout</span><span class="mtk1"> = ({ </span><span class="mtk12">children</span><span class="mtk1"> }) </span><span class="mtk4">=&gt;</span><span class="mtk1"> {</span></span></span> <span class="grvsc-line grvsc-line-highlighted"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk15">return</span><span class="mtk1"> (</span></span></span> <span class="grvsc-line grvsc-line-highlighted"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk17">&lt;</span><span class="mtk10">Box</span></span></span> <span class="grvsc-line grvsc-line-highlighted"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">sx</span><span class="mtk1">=</span><span class="mtk4">{</span><span class="mtk1">{</span></span></span> <span class="grvsc-line grvsc-line-highlighted"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk11">padding</span><span class="mtk12">:</span><span class="mtk1"> (</span><span class="mtk12">theme</span><span class="mtk1">) </span><span class="mtk4">=&gt;</span><span class="mtk1"> </span><span class="mtk12">theme</span><span class="mtk1">.</span><span class="mtk11">spacing</span><span class="mtk1">(</span><span class="mtk7">2</span><span class="mtk1">),</span></span></span> <span class="grvsc-line grvsc-line-highlighted"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">maxWidth:</span><span class="mtk1"> </span><span class="mtk8">&quot;1200px&quot;</span><span class="mtk1">,</span></span></span> <span class="grvsc-line grvsc-line-highlighted"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">margin:</span><span class="mtk1"> </span><span class="mtk8">&quot;0 auto&quot;</span><span class="mtk1">,</span></span></span> <span class="grvsc-line grvsc-line-highlighted"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">border:</span><span class="mtk1"> </span><span class="mtk8">&quot;1px solid #ccc&quot;</span><span class="mtk1">,</span></span></span> <span class="grvsc-line grvsc-line-highlighted"><span class="grvsc-source"><span class="mtk1"> }</span><span class="mtk4">}</span></span></span> <span class="grvsc-line grvsc-line-highlighted"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk17">&gt;</span></span></span> <span class="grvsc-line grvsc-line-highlighted"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk4">{</span><span class="mtk12">children</span><span class="mtk4">}</span></span></span> <span class="grvsc-line grvsc-line-highlighted"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk17">&lt;/</span><span class="mtk10">Box</span><span class="mtk17">&gt;</span></span></span> <span class="grvsc-line grvsc-line-highlighted"><span class="grvsc-source"><span class="mtk1"> );</span></span></span> <span class="grvsc-line grvsc-line-highlighted"><span class="grvsc-source"><span class="mtk1">};</span></span></span> <span class="grvsc-line"><span class="grvsc-source"></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk4">function</span><span class="mtk1"> </span><span class="mtk11">App</span><span class="mtk1">() {</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk15">return</span><span class="mtk1"> (</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk17">&lt;</span><span class="mtk10">ThemeProvider</span><span class="mtk1"> </span><span class="mtk12">theme</span><span class="mtk1">=</span><span class="mtk4">{</span><span class="mtk12">theme</span><span class="mtk4">}</span><span class="mtk17">&gt;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk17">&lt;</span><span class="mtk10">CssBaseline</span><span class="mtk1"> </span><span class="mtk17">/&gt;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk4">{</span><span class="mtk12">globalStyles</span><span class="mtk4">}</span></span></span> <span class="grvsc-line grvsc-line-highlighted"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk17">&lt;</span><span class="mtk10">Layout</span><span class="mtk17">&gt;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk17">&lt;</span><span class="mtk10">Typography</span><span class="mtk1"> </span><span class="mtk12">variant</span><span class="mtk1">=</span><span class="mtk8">&quot;h1&quot;</span><span class="mtk17">&gt;</span><span class="mtk1">Hello, World!</span><span class="mtk17">&lt;/</span><span class="mtk10">Typography</span><span class="mtk17">&gt;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk17">&lt;</span><span class="mtk10">Typography</span><span class="mtk1"> </span><span class="mtk12">variant</span><span class="mtk1">=</span><span class="mtk8">&quot;p&quot;</span><span class="mtk17">&gt;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> This is a paragraph of text that should be affected by the global</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> styles.</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk17">&lt;/</span><span class="mtk10">Typography</span><span class="mtk17">&gt;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk17">&lt;</span><span class="mtk10">Button</span><span class="mtk1"> </span><span class="mtk12">variant</span><span class="mtk1">=</span><span class="mtk8">&quot;contained&quot;</span><span class="mtk1"> </span><span class="mtk12">color</span><span class="mtk1">=</span><span class="mtk8">&quot;primary&quot;</span><span class="mtk17">&gt;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> A Styled Button Contained</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk17">&lt;/</span><span class="mtk10">Button</span><span class="mtk17">&gt;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk17">&lt;</span><span class="mtk10">Button</span><span class="mtk1"> </span><span class="mtk12">variant</span><span class="mtk1">=</span><span class="mtk8">&quot;outlined&quot;</span><span class="mtk1"> </span><span class="mtk12">color</span><span class="mtk1">=</span><span class="mtk8">&quot;secondary&quot;</span><span class="mtk17">&gt;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> A Styled Button Outlined</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk17">&lt;/</span><span class="mtk10">Button</span><span class="mtk17">&gt;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk4">{</span><span class="mtk3">/* Other components go here */</span><span class="mtk4">}</span></span></span> <span class="grvsc-line grvsc-line-highlighted"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk17">&lt;/</span><span class="mtk10">Layout</span><span class="mtk17">&gt;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk17">&lt;/</span><span class="mtk10">ThemeProvider</span><span class="mtk17">&gt;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> );</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1">}</span></span></span> <span class="grvsc-line"><span class="grvsc-source"></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk15">export</span><span class="mtk1"> </span><span class="mtk15">default</span><span class="mtk1"> </span><span class="mtk12">App</span><span class="mtk1">;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"></span></span></code></pre> <p>We can still use CSS selectors to target MUI components globally, as in the previous section.</p> <pre class="grvsc-container default-dark" data-language="jsx" data-index="6"><code class="grvsc-code"><span class="grvsc-line"><span class="grvsc-source"><span class="mtk4">const</span><span class="mtk1"> </span><span class="mtk11">Layout</span><span class="mtk1"> = ({ </span><span class="mtk12">children</span><span class="mtk1"> }) </span><span class="mtk4">=&gt;</span><span class="mtk1"> {</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk15">return</span><span class="mtk1"> (</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk17">&lt;</span><span class="mtk10">Box</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">sx</span><span class="mtk1">=</span><span class="mtk4">{</span><span class="mtk1">{</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> ...</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk8">&quot;.MuiButton-root&quot;</span><span class="mtk1">: {</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">margin:</span><span class="mtk1"> </span><span class="mtk12">theme</span><span class="mtk1">.</span><span class="mtk11">spacing</span><span class="mtk1">(</span><span class="mtk7">1</span><span class="mtk1">)</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> }</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> }</span><span class="mtk4">}</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk17">&gt;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk4">{</span><span class="mtk12">children</span><span class="mtk4">}</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk17">&lt;/</span><span class="mtk10">Box</span><span class="mtk17">&gt;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> );</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1">};</span></span></span></code></pre> <h2 id="conclusion--complete-code" style="position:relative;"><a href="#conclusion--complete-code" aria-label="conclusion complete code permalink" class="anchor before"><svg aria-hidden="true" focusable="false" height="16" version="1.1" viewBox="0 0 16 16" width="16"><path fill-rule="evenodd" d="M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z"></path></svg></a>Conclusion &#x26; Complete Code</h2> <p>Looking at the different techniques we explored in this tutorial, we can see that there is no single way to create global styles in MUI, but the best approach is to use them all!</p> <p>Each has its use cases and benefits. For example, we can use the <code>createTheme</code> to create and override styles that all MUI components can use. Then, we can use the <code>GlobalStyles</code> component to style elements outside the MUI components tree. Finally, we can use the parent/root component to create a common layout for all pages.</p> <p>Here is the complete code for all the examples in this tutorial.</p> <div data-stackblitz="mui-global-styles"> <button>Run Code</button> </div> <p>Bye for now 👋</p> <style class="grvsc-styles"> .grvsc-container { overflow: auto; position: relative; -webkit-overflow-scrolling: touch; padding-top: 1rem; padding-top: var(--grvsc-padding-top, var(--grvsc-padding-v, 1rem)); padding-bottom: 1rem; padding-bottom: var(--grvsc-padding-bottom, var(--grvsc-padding-v, 1rem)); border-radius: 8px; border-radius: var(--grvsc-border-radius, 8px); font-feature-settings: normal; line-height: 1.4; } .grvsc-code { display: table; } .grvsc-line { display: table-row; box-sizing: border-box; width: 100%; position: relative; } .grvsc-line > * { position: relative; } .grvsc-gutter-pad { display: table-cell; padding-left: 0.75rem; padding-left: calc(var(--grvsc-padding-left, var(--grvsc-padding-h, 1.5rem)) / 2); } .grvsc-gutter { display: table-cell; -webkit-user-select: none; -moz-user-select: none; user-select: none; } .grvsc-gutter::before { content: attr(data-content); } .grvsc-source { display: table-cell; padding-left: 1.5rem; padding-left: var(--grvsc-padding-left, var(--grvsc-padding-h, 1.5rem)); padding-right: 1.5rem; padding-right: var(--grvsc-padding-right, var(--grvsc-padding-h, 1.5rem)); } .grvsc-source:empty::after { content: ' '; -webkit-user-select: none; -moz-user-select: none; user-select: none; } .grvsc-gutter + .grvsc-source { padding-left: 0.75rem; padding-left: calc(var(--grvsc-padding-left, var(--grvsc-padding-h, 1.5rem)) / 2); } /* Line transformer styles */ .grvsc-has-line-highlighting > .grvsc-code > .grvsc-line::before { content: ' '; position: absolute; width: 100%; } .grvsc-line-diff-add::before { background-color: var(--grvsc-line-diff-add-background-color, rgba(0, 255, 60, 0.2)); } .grvsc-line-diff-del::before { background-color: var(--grvsc-line-diff-del-background-color, rgba(255, 0, 20, 0.2)); } .grvsc-line-number { padding: 0 2px; text-align: right; opacity: 0.7; } .default-dark { background-color: #1E1E1E; color: #D4D4D4; } .default-dark .mtk15 { color: #C586C0; } .default-dark .mtk1 { color: #D4D4D4; } .default-dark .mtk12 { color: #9CDCFE; } .default-dark .mtk8 { color: #CE9178; } .default-dark .mtk4 { color: #569CD6; } .default-dark .mtk11 { color: #DCDCAA; } .default-dark .mtk17 { color: #808080; } .default-dark .mtk10 { color: #4EC9B0; } .default-dark .mtk3 { color: #6A9955; } .default-dark .mtk7 { color: #B5CEA8; } .default-dark .grvsc-line-highlighted::before { background-color: var(--grvsc-line-highlighted-background-color, rgba(255, 255, 255, 0.1)); box-shadow: inset var(--grvsc-line-highlighted-border-width, 4px) 0 0 0 var(--grvsc-line-highlighted-border-color, rgba(255, 255, 255, 0.5)); } </style><![CDATA[[Part 4] Read and Write Table Data with API Requests using React Tanstack]]>https://muhimasri.comreact-table-api-requestshttps://muhimasri.comreact-table-api-requests<p>In the previous parts of this series, we learned how to create an editable dynamic table, add and remove rows dynamically, and validate input fields and rows. So far, we have been working with the table data in an object array. In this part, we will learn how to read and write table data with API requests using <a href="https://www.npmjs.com/package/json-server">JSON Server</a> and <a href="https://swr.vercel.app/">SWR</a>.</p> <ul> <li>JSON Server is a fake REST API that we can use to test our API requests.</li> <li>SWR is a React hook for data fetching that makes it easy to fetch and revalidate data.</li> </ul> <h2 id="setup-and-install-dependencies" style="position:relative;"><a href="#setup-and-install-dependencies" aria-label="setup and install dependencies permalink" class="anchor before"><svg aria-hidden="true" focusable="false" height="16" version="1.1" viewBox="0 0 16 16" width="16"><path fill-rule="evenodd" d="M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z"></path></svg></a>Setup and install dependencies</h2> <p>Before we get started, let’s install the dependencies we need for this part.</p> <pre class="grvsc-container default-dark" data-language="bash" data-index="0"><code class="grvsc-code"><span class="grvsc-line"><span class="grvsc-source"><span class="mtk3"># Install JSON Server</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1">npm install -g json-server</span></span></span> <span class="grvsc-line"><span class="grvsc-source"></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk3"># Install SWR</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1">npm install swr</span></span></span></code></pre> <p>For JSON Server to work, we need to create a <code>db.json</code> file. This file will contain the data we want to fetch and update. In our case, it will be the list of students.</p> <p>Let’s create a new <code>db.json</code> file in the <code>src/Table</code> folder and add the following data</p> <pre class="grvsc-container default-dark" data-language="json" data-index="1"><code class="grvsc-code"><span class="grvsc-line"><span class="grvsc-source"><span class="mtk1">{</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">&quot;students&quot;</span><span class="mtk1">: [</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> {</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">&quot;id&quot;</span><span class="mtk1">: </span><span class="mtk7">1</span><span class="mtk1">,</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">&quot;studentNumber&quot;</span><span class="mtk1">: </span><span class="mtk7">1111</span><span class="mtk1">,</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">&quot;name&quot;</span><span class="mtk1">: </span><span class="mtk8">&quot;Bahar Constantia&quot;</span><span class="mtk1">,</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">&quot;dateOfBirth&quot;</span><span class="mtk1">: </span><span class="mtk8">&quot;1984-01-04&quot;</span><span class="mtk1">,</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">&quot;major&quot;</span><span class="mtk1">: </span><span class="mtk8">&quot;Computer Science&quot;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> },</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> {</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">&quot;id&quot;</span><span class="mtk1">: </span><span class="mtk7">2</span><span class="mtk1">,</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">&quot;studentNumber&quot;</span><span class="mtk1">: </span><span class="mtk7">2222</span><span class="mtk1">,</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">&quot;name&quot;</span><span class="mtk1">: </span><span class="mtk8">&quot;Harold Nona&quot;</span><span class="mtk1">,</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">&quot;dateOfBirth&quot;</span><span class="mtk1">: </span><span class="mtk8">&quot;1961-05-10&quot;</span><span class="mtk1">,</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">&quot;major&quot;</span><span class="mtk1">: </span><span class="mtk8">&quot;Communications&quot;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> },</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> {</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">&quot;id&quot;</span><span class="mtk1">: </span><span class="mtk7">3</span><span class="mtk1">,</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">&quot;studentNumber&quot;</span><span class="mtk1">: </span><span class="mtk7">3333</span><span class="mtk1">,</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">&quot;name&quot;</span><span class="mtk1">: </span><span class="mtk8">&quot;Raginolf Arnulf&quot;</span><span class="mtk1">,</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">&quot;dateOfBirth&quot;</span><span class="mtk1">: </span><span class="mtk8">&quot;1991-10-12&quot;</span><span class="mtk1">,</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">&quot;major&quot;</span><span class="mtk1">: </span><span class="mtk8">&quot;Business&quot;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> },</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> {</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">&quot;id&quot;</span><span class="mtk1">: </span><span class="mtk7">4</span><span class="mtk1">,</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">&quot;studentNumber&quot;</span><span class="mtk1">: </span><span class="mtk7">4444</span><span class="mtk1">,</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">&quot;name&quot;</span><span class="mtk1">: </span><span class="mtk8">&quot;Marvyn Wendi&quot;</span><span class="mtk1">,</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">&quot;dateOfBirth&quot;</span><span class="mtk1">: </span><span class="mtk8">&quot;1978-09-24&quot;</span><span class="mtk1">,</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">&quot;major&quot;</span><span class="mtk1">: </span><span class="mtk8">&quot;Psychology&quot;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> }</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> ]</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1">}</span></span></span></code></pre> <p>Notice that we added a new <code>id</code> field to each student object. This field will be used as a unique identifier for JSON Server to update and delete data. We also changed the <code>studentId</code> field to <code>studentNumber</code> to distinguish it from the <code>id</code> field.</p> <p>To get the JSON Server up and running, we need to run the following command in the terminal.</p> <pre class="grvsc-container default-dark" data-language="bash" data-index="2"><code class="grvsc-code"><span class="grvsc-line"><span class="grvsc-source"><span class="mtk1">json-server --watch ./src/Table/db.json --port 5000</span></span></span></code></pre> <p>This will run a server on port 5000 and serve the data in the <code>db.json</code> file. We can access the data by visiting <a href="http://localhost:5000/students">http://localhost:5000/students</a>.</p> <p><span class="gatsby-resp-image-wrapper" style="position: relative; display: block; margin-left: auto; margin-right: auto; max-width: 720px; " > <a class="gatsby-resp-image-link" href="/static/65fb728cca1b3f83d20a9998969895e6/0fe46/json-server.png" style="display: block" target="_blank" rel="noopener" > <span class="gatsby-resp-image-background-image" style="padding-bottom: 64.99999999999999%; position: relative; bottom: 0; left: 0; background-image: url('data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABQAAAANCAYAAACpUE5eAAAACXBIWXMAACToAAAk6AGCYwUcAAABO0lEQVR42p1TSW7DMBDLP4rGm3ZrtZO4bpzAbv//JnbktuihlygHYjQwTJEz1OFymZARY8I4nuF9gHUeWpuncGBcou0EmpZDCA4uFeqWoaL+2BCqDnXDHsaBC0VkgpoO6xrxuSV8vAfMY8A2D/BKlREyrtAxiaw0JQNrNaLRSEZhcnTudRmhVD0yabZtraL5GUgpwIRERZe8HAsta2N3sqrusP1YXmeP+zlgnRI0ETdtAaHSdleYZ9n3kqqAJmWGqiOlnHFUTSFhnmHbcYqOoeg4BJqdoAiovkddF1t2O2Fu7reA+0LbffNYBocbwZZu+c8yqSKLLSNQBhkpfi3M4D+F80yqlojzYBCDw2mMRP4EYVaYN7lcPebJ4UpzXE8e1+Qg2PcrKsphtpt/qmpGT43tNX/Mz+73/Ci+AMU2dlekLTwVAAAAAElFTkSuQmCC'); background-size: cover; display: block;" ></span> <img class="gatsby-resp-image-image" alt="JSON Server" title="" src="/static/65fb728cca1b3f83d20a9998969895e6/37523/json-server.png" srcset="/static/65fb728cca1b3f83d20a9998969895e6/e9ff0/json-server.png 180w, /static/65fb728cca1b3f83d20a9998969895e6/f21e7/json-server.png 360w, /static/65fb728cca1b3f83d20a9998969895e6/37523/json-server.png 720w, /static/65fb728cca1b3f83d20a9998969895e6/302a4/json-server.png 1080w, /static/65fb728cca1b3f83d20a9998969895e6/07a9c/json-server.png 1440w, /static/65fb728cca1b3f83d20a9998969895e6/0fe46/json-server.png 2507w" sizes="(max-width: 720px) 100vw, 720px" style="width:100%;height:100%;margin:0;vertical-align:middle;position:absolute;top:0;left:0;" loading="lazy" decoding="async" /> </a> </span></p> <p>An alternative way to running two servers (React and JSON Server) separately in two terminals is to use <a href="https://www.npmjs.com/package/concurrently">Concurrently</a>. It’s a package that allows us to run multiple commands concurrently.</p> <p>First, let’s install the package.</p> <pre class="grvsc-container default-dark" data-language="bash" data-index="3"><code class="grvsc-code"><span class="grvsc-line"><span class="grvsc-source"><span class="mtk1">npm install concurrently</span></span></span></code></pre> <p>Then, we need to add a new script to the <code>package.json</code> file to enable us to run both servers concurrently.</p> <pre class="grvsc-container default-dark" data-language="json" data-index="4"><code class="grvsc-code"><span class="grvsc-line"><span class="grvsc-source"><span class="mtk8">&quot;scripts&quot;</span><span class="mtk1">: {</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">&quot;vite&quot;</span><span class="mtk1">: </span><span class="mtk8">&quot;vite&quot;</span><span class="mtk1">,</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">&quot;jsonserver&quot;</span><span class="mtk1">: </span><span class="mtk8">&quot;json-server ./src/Table/db.json --watch --port 5000&quot;</span><span class="mtk1">,</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">&quot;dev&quot;</span><span class="mtk1">: </span><span class="mtk8">&quot;concurrently </span><span class="mtk6">\&quot;</span><span class="mtk8">npm run jsonserver</span><span class="mtk6">\&quot;</span><span class="mtk8"> </span><span class="mtk6">\&quot;</span><span class="mtk8">npm run vite</span><span class="mtk6">\&quot;</span><span class="mtk8">&quot;</span><span class="mtk1">,</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk14">...</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1">}</span></span></span></code></pre> <p>Now, when running the project normally using <code>npm run dev</code>, both servers will run simultaneously.</p> <h2 id="fetch-data-using-swr" style="position:relative;"><a href="#fetch-data-using-swr" aria-label="fetch data using swr permalink" class="anchor before"><svg aria-hidden="true" focusable="false" height="16" version="1.1" viewBox="0 0 16 16" width="16"><path fill-rule="evenodd" d="M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z"></path></svg></a>Fetch data using SWR</h2> <p>Now that we have the JSON Server running let’s start working with the API requests.</p> <p>Before we start, we need to make a few changes to accommodate the new data structure.</p> <ol> <li>The <code>Student</code> type interface in <code>data.ts</code> must be updated to match the data in the <code>db.json</code> file.</li> </ol> <pre class="grvsc-container grvsc-has-line-highlighting default-dark" data-language="ts" data-index="5"><code class="grvsc-code"><span class="grvsc-line"><span class="grvsc-source"><span class="mtk15">export</span><span class="mtk1"> </span><span class="mtk4">type</span><span class="mtk1"> </span><span class="mtk10">Student</span><span class="mtk1"> = {</span></span></span> <span class="grvsc-line grvsc-line-highlighted"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">id</span><span class="mtk1">: </span><span class="mtk10">number</span></span></span> <span class="grvsc-line grvsc-line-highlighted"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">studentNumber</span><span class="mtk1">: </span><span class="mtk10">number</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">name</span><span class="mtk1">: </span><span class="mtk10">string</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">dateOfBirth</span><span class="mtk1">: </span><span class="mtk10">string</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">major</span><span class="mtk1">: </span><span class="mtk10">string</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1">}</span></span></span></code></pre> <ol start="2"> <li>Since the data is now stored in a JSON file, we don’t require the <code>data</code> object array in <code>data.ts</code> anymore. We only need the <code>Student</code> type interface. To make the code cleaner, let’s move the <code>Student</code> type to a new <code>types.ts</code> file in the “Table” folder. So now the <code>/data</code> reference in the <code>Table</code> component will be changed to <code>/types</code>.</li> </ol> <pre class="grvsc-container default-dark" data-language="tsx" data-index="6"><code class="grvsc-code"><span class="grvsc-line"><span class="grvsc-source"><span class="mtk15">import</span><span class="mtk1"> { </span><span class="mtk12">Student</span><span class="mtk1"> } </span><span class="mtk15">from</span><span class="mtk1"> </span><span class="mtk8">&#39;./types&#39;</span><span class="mtk1">;</span></span></span></code></pre> <ol start="3"> <li>The <code>columns</code> array in <code>columns.ts</code> needs to be updated to match the new <code>Student</code> type interface</li> </ol> <pre class="grvsc-container grvsc-has-line-highlighting default-dark" data-language="ts" data-index="7"><code class="grvsc-code"><span class="grvsc-line"><span class="grvsc-source"><span class="mtk1">...</span></span></span> <span class="grvsc-line grvsc-line-highlighted"><span class="grvsc-source"><span class="mtk15">import</span><span class="mtk1"> { </span><span class="mtk12">Student</span><span class="mtk1"> } </span><span class="mtk15">from</span><span class="mtk1"> </span><span class="mtk8">&#39;./types&#39;</span><span class="mtk1">;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1">...</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk15">export</span><span class="mtk1"> </span><span class="mtk4">const</span><span class="mtk1"> </span><span class="mtk12">columns</span><span class="mtk1"> = [</span></span></span> <span class="grvsc-line grvsc-line-highlighted"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">columnHelper</span><span class="mtk1">.</span><span class="mtk11">accessor</span><span class="mtk1">(</span><span class="mtk8">&#39;studentNumber&#39;</span><span class="mtk1">, {</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">header:</span><span class="mtk1"> </span><span class="mtk8">&#39;Student Id&#39;</span><span class="mtk1">,</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">cell:</span><span class="mtk1"> </span><span class="mtk12">TableCell</span><span class="mtk1">,</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">meta:</span><span class="mtk1"> {</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">type:</span><span class="mtk1"> </span><span class="mtk8">&#39;number&#39;</span><span class="mtk1">,</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> },</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> }),</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> ...</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1">]</span></span></span></code></pre> <p>We’re all set with the changes. Let’s start fetching the data.</p> <p>First, we will create a new <code>useStudents</code> hook. This hook will be responsible for fetching the data and other operations related to the students using the <code>useSWR</code>. Here are few things to note:</p> <ol> <li>When using <code>useSWR</code> hook, it accepts two parameters. The first parameter is the URL that will be used to fetch the data. In our case, it will be <code>http://localhost:5000/students</code>. The second parameter is the <code>getRequest</code> function that will be used to fetch the data.</li> <li>The <code>useStudents</code> hook will expose the student’s <code>data</code> array, <code>isValidating</code> variable to the component that uses it. <code>isValidating</code> will be used to know if the data is being fetched. It’s similar to <code>isLoading</code>, but it’s triggered on mutations as well.</li> </ol> <pre class="grvsc-container default-dark" data-language="ts" data-index="8"><code class="grvsc-code"><span class="grvsc-line"><span class="grvsc-source"><span class="mtk15">import</span><span class="mtk1"> </span><span class="mtk12">useSWR</span><span class="mtk1"> </span><span class="mtk15">from</span><span class="mtk1"> </span><span class="mtk8">&#39;swr&#39;</span><span class="mtk1">;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk4">const</span><span class="mtk1"> </span><span class="mtk12">url</span><span class="mtk1"> = </span><span class="mtk8">&#39;http://localhost:5000/students&#39;</span><span class="mtk1">;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk4">async</span><span class="mtk1"> </span><span class="mtk4">function</span><span class="mtk1"> </span><span class="mtk11">getRequest</span><span class="mtk1">() {</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk4">const</span><span class="mtk1"> </span><span class="mtk12">response</span><span class="mtk1"> = </span><span class="mtk15">await</span><span class="mtk1"> </span><span class="mtk11">fetch</span><span class="mtk1">(</span><span class="mtk12">url</span><span class="mtk1">);</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk15">return</span><span class="mtk1"> </span><span class="mtk12">response</span><span class="mtk1">.</span><span class="mtk11">json</span><span class="mtk1">();</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1">}</span></span></span> <span class="grvsc-line"><span class="grvsc-source"></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk15">export</span><span class="mtk1"> </span><span class="mtk15">default</span><span class="mtk1"> </span><span class="mtk4">function</span><span class="mtk1"> </span><span class="mtk11">useStudents</span><span class="mtk1">() {</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk4">const</span><span class="mtk1"> { </span><span class="mtk12">data</span><span class="mtk1">, </span><span class="mtk12">isValidating</span><span class="mtk1"> } = </span><span class="mtk11">useSWR</span><span class="mtk1">(</span><span class="mtk12">url</span><span class="mtk1">, </span><span class="mtk12">getRequest</span><span class="mtk1">);</span></span></span> <span class="grvsc-line"><span class="grvsc-source"></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk15">return</span><span class="mtk1"> {</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">data:</span><span class="mtk1"> </span><span class="mtk12">data</span><span class="mtk1"> ?? [],</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">isValidating</span><span class="mtk1">,</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> };</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1">}</span></span></span></code></pre> <p>Then, we will use the <code>useStudents</code> hook in the <code>Table</code> component to fetch the data, replacing the <code>originalData</code> array we had in the previous parts.</p> <p>A quick recap, the <code>originalData</code> array is the array that contains the original data and is used to initialize the <code>data</code> array. The reason we had to do this is because we need to keep the previous data in case the user cancels the changes. Now, since the <code>originalData</code> is coming from the server, we can remove the one we had before.</p> <pre class="grvsc-container default-dark" data-language="jsx" data-index="9"><code class="grvsc-code"><span class="grvsc-line"><span class="grvsc-source"><span class="mtk15">import</span><span class="mtk1"> { </span><span class="mtk12">useEffect</span><span class="mtk1">, </span><span class="mtk12">useState</span><span class="mtk1"> } </span><span class="mtk15">from</span><span class="mtk1"> </span><span class="mtk8">&quot;react&quot;</span><span class="mtk1">;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1">...</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk15">import</span><span class="mtk1"> </span><span class="mtk12">useStudents</span><span class="mtk1"> </span><span class="mtk15">from</span><span class="mtk1"> </span><span class="mtk8">&quot;./useStudents&quot;</span><span class="mtk1">;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk15">export</span><span class="mtk1"> </span><span class="mtk4">const</span><span class="mtk1"> </span><span class="mtk11">Table</span><span class="mtk1"> = () </span><span class="mtk4">=&gt;</span><span class="mtk1"> {</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk4">const</span><span class="mtk1"> { </span><span class="mtk12">data</span><span class="mtk1">: </span><span class="mtk12">originalData</span><span class="mtk1">, </span><span class="mtk12">isValidating</span><span class="mtk1"> } = </span><span class="mtk11">useStudents</span><span class="mtk1">();</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk4">const</span><span class="mtk1"> [</span><span class="mtk12">data</span><span class="mtk1">, </span><span class="mtk12">setData</span><span class="mtk1">] = </span><span class="mtk11">useState</span><span class="mtk1">&lt;</span><span class="mtk10">Student</span><span class="mtk1">[]&gt;([]);</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk4">const</span><span class="mtk1"> [</span><span class="mtk12">editedRows</span><span class="mtk1">, </span><span class="mtk12">setEditedRows</span><span class="mtk1">] = </span><span class="mtk11">useState</span><span class="mtk1">({});</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk4">const</span><span class="mtk1"> [</span><span class="mtk12">validRows</span><span class="mtk1">, </span><span class="mtk12">setValidRows</span><span class="mtk1">] = </span><span class="mtk11">useState</span><span class="mtk1">({});</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk11">useEffect</span><span class="mtk1">(() </span><span class="mtk4">=&gt;</span><span class="mtk1"> {</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk15">if</span><span class="mtk1"> (</span><span class="mtk12">isValidating</span><span class="mtk1">) </span><span class="mtk15">return</span><span class="mtk1">;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk11">setData</span><span class="mtk1">([...</span><span class="mtk12">originalData</span><span class="mtk1">]);</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> }, [</span><span class="mtk12">isValidating</span><span class="mtk1">]);</span></span></span> <span class="grvsc-line"><span class="grvsc-source"></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> ...</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1">};</span></span></span></code></pre> <p>And since we don’t know when the data will be ready, we had to add a <code>useEffect</code> hook to update the <code>data</code> array when the <code>originalData</code> changes. That’s when the <code>isValidating</code> variable comes in handy. It will be <code>true</code> when the data is being fetched and <code>false</code> when it is ready.</p> <p>Of course, we can always add a loading indicator to improve the user experience, but this is out of the scope of this tutorial.</p> <p>Now, if we run the project and open the browser network tab, we will see that the data is being fetched from the server.</p> <video width="720" height="400" autoplay loop muted preload="none"> <source src="/01d7795887fe86e6f9c740608e32a5ee/get-api.mp4" type="video/mp4"> </video> <p><em>Note: Other parts of the code might be borken at this point, this is expected and will be fixed in the next steps. We can always comment out the errors if it’s stopping us from running the project.</em></p> <h2 id="update-data" style="position:relative;"><a href="#update-data" aria-label="update data permalink" class="anchor before"><svg aria-hidden="true" focusable="false" height="16" version="1.1" viewBox="0 0 16 16" width="16"><path fill-rule="evenodd" d="M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z"></path></svg></a>Update data</h2> <p>Updating a table row requires a new <code>PUT</code> request to the server with few additional steps:</p> <ol> <li>The update function requires two parameters. The first parameter is the <code>id</code> of the row that will be updated. The second parameter is row data that needs to be updated.</li> <li>We need to expose the update function from the <code>useStudents</code> hook so the <code>Table</code> component can use it.</li> <li>After updating the data, we need to trigger a <code>mutate</code> function to update the <code>originalData</code> array. The <code>mutate</code> is a built-in function in SWR that allows us to sync and revalidate the data.</li> </ol> <pre class="grvsc-container grvsc-has-line-highlighting default-dark" data-language="ts" data-index="10"><code class="grvsc-code"><span class="grvsc-line"><span class="grvsc-source"><span class="mtk15">import</span><span class="mtk1"> </span><span class="mtk12">useSWR</span><span class="mtk1">, { </span><span class="mtk12">mutate</span><span class="mtk1"> } </span><span class="mtk15">from</span><span class="mtk1"> </span><span class="mtk8">&#39;swr&#39;</span><span class="mtk1">;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk15">import</span><span class="mtk1"> { </span><span class="mtk12">Student</span><span class="mtk1"> } </span><span class="mtk15">from</span><span class="mtk1"> </span><span class="mtk8">&#39;./types&#39;</span><span class="mtk1">;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk4">const</span><span class="mtk1"> </span><span class="mtk12">url</span><span class="mtk1"> = </span><span class="mtk8">&#39;http://localhost:5000/students&#39;</span><span class="mtk1">;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"></span></span> <span class="grvsc-line grvsc-line-highlighted"><span class="grvsc-source"><span class="mtk4">async</span><span class="mtk1"> </span><span class="mtk4">function</span><span class="mtk1"> </span><span class="mtk11">updateRequest</span><span class="mtk1">(</span><span class="mtk12">id</span><span class="mtk1">: </span><span class="mtk10">number</span><span class="mtk1">, </span><span class="mtk12">data</span><span class="mtk1">: </span><span class="mtk10">Student</span><span class="mtk1">) {</span></span></span> <span class="grvsc-line grvsc-line-highlighted"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk4">const</span><span class="mtk1"> </span><span class="mtk12">response</span><span class="mtk1"> = </span><span class="mtk15">await</span><span class="mtk1"> </span><span class="mtk11">fetch</span><span class="mtk1">(</span><span class="mtk8">`</span><span class="mtk4">${</span><span class="mtk12">url</span><span class="mtk4">}</span><span class="mtk8">/</span><span class="mtk4">${</span><span class="mtk12">id</span><span class="mtk4">}</span><span class="mtk8">`</span><span class="mtk1">, {</span></span></span> <span class="grvsc-line grvsc-line-highlighted"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">method:</span><span class="mtk1"> </span><span class="mtk8">&#39;PUT&#39;</span><span class="mtk1">,</span></span></span> <span class="grvsc-line grvsc-line-highlighted"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">headers:</span><span class="mtk1"> {</span></span></span> <span class="grvsc-line grvsc-line-highlighted"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk8">&#39;Content-Type&#39;</span><span class="mtk12">:</span><span class="mtk1"> </span><span class="mtk8">&#39;application/json&#39;</span><span class="mtk1">,</span></span></span> <span class="grvsc-line grvsc-line-highlighted"><span class="grvsc-source"><span class="mtk1"> },</span></span></span> <span class="grvsc-line grvsc-line-highlighted"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">body:</span><span class="mtk1"> </span><span class="mtk10">JSON</span><span class="mtk1">.</span><span class="mtk11">stringify</span><span class="mtk1">(</span><span class="mtk12">data</span><span class="mtk1">),</span></span></span> <span class="grvsc-line grvsc-line-highlighted"><span class="grvsc-source"><span class="mtk1"> });</span></span></span> <span class="grvsc-line grvsc-line-highlighted"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk15">return</span><span class="mtk1"> </span><span class="mtk12">response</span><span class="mtk1">.</span><span class="mtk11">json</span><span class="mtk1">();</span></span></span> <span class="grvsc-line grvsc-line-highlighted"><span class="grvsc-source"><span class="mtk1">}</span></span></span> <span class="grvsc-line"><span class="grvsc-source"></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk4">async</span><span class="mtk1"> </span><span class="mtk4">function</span><span class="mtk1"> </span><span class="mtk11">getRequest</span><span class="mtk1">() {</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk4">const</span><span class="mtk1"> </span><span class="mtk12">response</span><span class="mtk1"> = </span><span class="mtk15">await</span><span class="mtk1"> </span><span class="mtk11">fetch</span><span class="mtk1">(</span><span class="mtk12">url</span><span class="mtk1">);</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk15">return</span><span class="mtk1"> </span><span class="mtk12">response</span><span class="mtk1">.</span><span class="mtk11">json</span><span class="mtk1">();</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1">}</span></span></span> <span class="grvsc-line"><span class="grvsc-source"></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk15">export</span><span class="mtk1"> </span><span class="mtk15">default</span><span class="mtk1"> </span><span class="mtk4">function</span><span class="mtk1"> </span><span class="mtk11">useStudents</span><span class="mtk1">() {</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk4">const</span><span class="mtk1"> { </span><span class="mtk12">data</span><span class="mtk1">, </span><span class="mtk12">isValidating</span><span class="mtk1"> } = </span><span class="mtk11">useSWR</span><span class="mtk1">(</span><span class="mtk12">url</span><span class="mtk1">, </span><span class="mtk12">getRequest</span><span class="mtk1">);</span></span></span> <span class="grvsc-line"><span class="grvsc-source"></span></span> <span class="grvsc-line grvsc-line-highlighted"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk4">const</span><span class="mtk1"> </span><span class="mtk11">updateRow</span><span class="mtk1"> = </span><span class="mtk4">async</span><span class="mtk1"> (</span><span class="mtk12">id</span><span class="mtk1">: </span><span class="mtk10">number</span><span class="mtk1">, </span><span class="mtk12">postData</span><span class="mtk1">: </span><span class="mtk10">Student</span><span class="mtk1">) </span><span class="mtk4">=&gt;</span><span class="mtk1"> {</span></span></span> <span class="grvsc-line grvsc-line-highlighted"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk15">await</span><span class="mtk1"> </span><span class="mtk11">updateRequest</span><span class="mtk1">(</span><span class="mtk12">id</span><span class="mtk1">, </span><span class="mtk12">postData</span><span class="mtk1">);</span></span></span> <span class="grvsc-line grvsc-line-highlighted"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk11">mutate</span><span class="mtk1">(</span><span class="mtk12">url</span><span class="mtk1">);</span></span></span> <span class="grvsc-line grvsc-line-highlighted"><span class="grvsc-source"><span class="mtk1"> };</span></span></span> <span class="grvsc-line"><span class="grvsc-source"></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk15">return</span><span class="mtk1"> {</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">data:</span><span class="mtk1"> </span><span class="mtk12">data</span><span class="mtk1"> ?? [],</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">isValidating</span><span class="mtk1">,</span></span></span> <span class="grvsc-line grvsc-line-highlighted"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">updateRow</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> };</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1">}</span></span></span> <span class="grvsc-line"><span class="grvsc-source"></span></span></code></pre> <p>In the <code>Table</code> compoennt, we have two functions that updates the data. The first one is the <code>updateData</code> that is triggered on cell input change, and it updates the <code>data</code> array at the specified row index. The second is the <code>revertData</code>, which is triggered when the user clicks the cancel/save button, and it either reverts the changes or keeps them and updates the <code>originalData</code>. Here is the current code we have from the previous parts.</p> <pre class="grvsc-container default-dark" data-language="tsx" data-index="11"><code class="grvsc-code"><span class="grvsc-line"><span class="grvsc-source"><span class="mtk4">const</span><span class="mtk1"> </span><span class="mtk12">table</span><span class="mtk1"> = </span><span class="mtk11">useReactTable</span><span class="mtk1">({</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> ...</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">revertData</span><span class="mtk1">: (</span><span class="mtk12">rowIndex</span><span class="mtk1">: </span><span class="mtk10">number</span><span class="mtk1">, </span><span class="mtk12">revert</span><span class="mtk1">: </span><span class="mtk10">boolean</span><span class="mtk1">) </span><span class="mtk4">=&gt;</span><span class="mtk1"> {</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk15">if</span><span class="mtk1"> (</span><span class="mtk12">revert</span><span class="mtk1">) {</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk11">setData</span><span class="mtk1">((</span><span class="mtk12">old</span><span class="mtk1">) </span><span class="mtk4">=&gt;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">old</span><span class="mtk1">.</span><span class="mtk11">map</span><span class="mtk1">((</span><span class="mtk12">row</span><span class="mtk1">, </span><span class="mtk12">index</span><span class="mtk1">) </span><span class="mtk4">=&gt;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">index</span><span class="mtk1"> === </span><span class="mtk12">rowIndex</span><span class="mtk1"> ? </span><span class="mtk12">originalData</span><span class="mtk1">[</span><span class="mtk12">rowIndex</span><span class="mtk1">] : </span><span class="mtk12">row</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> )</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> );</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> } </span><span class="mtk15">else</span><span class="mtk1"> {</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk11">setOriginalData</span><span class="mtk1">((</span><span class="mtk12">old</span><span class="mtk1">) </span><span class="mtk4">=&gt;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">old</span><span class="mtk1">.</span><span class="mtk11">map</span><span class="mtk1">((</span><span class="mtk12">row</span><span class="mtk1">, </span><span class="mtk12">index</span><span class="mtk1">) </span><span class="mtk4">=&gt;</span><span class="mtk1"> (</span><span class="mtk12">index</span><span class="mtk1"> === </span><span class="mtk12">rowIndex</span><span class="mtk1"> ? </span><span class="mtk12">data</span><span class="mtk1">[</span><span class="mtk12">rowIndex</span><span class="mtk1">] : </span><span class="mtk12">row</span><span class="mtk1">))</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> );</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> }</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> },</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> ...</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> }</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1">)</span></span></span></code></pre> <p>Now, since we need to update the data on the server, we will change the code above and create a separate function called <code>updateRow</code> that will trigger the <code>updateRow</code> function from the <code>useStudents</code> hook.</p> <pre class="grvsc-container default-dark" data-language="tsx" data-index="12"><code class="grvsc-code"><span class="grvsc-line"><span class="grvsc-source"><span class="mtk1">...</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk15">export</span><span class="mtk1"> </span><span class="mtk4">const</span><span class="mtk1"> </span><span class="mtk11">Table</span><span class="mtk1"> = () </span><span class="mtk4">=&gt;</span><span class="mtk1"> {</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk4">const</span><span class="mtk1"> { </span><span class="mtk12">data</span><span class="mtk1">: </span><span class="mtk12">originalData</span><span class="mtk1">, </span><span class="mtk12">isValidating</span><span class="mtk1">, </span><span class="mtk12">updateRow</span><span class="mtk1"> } = </span><span class="mtk11">useStudents</span><span class="mtk1">();</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> ...</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk4">const</span><span class="mtk1"> </span><span class="mtk12">table</span><span class="mtk1"> = </span><span class="mtk11">useReactTable</span><span class="mtk1">({</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> ...</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">revertData</span><span class="mtk1">: (</span><span class="mtk12">rowIndex</span><span class="mtk1">: </span><span class="mtk10">number</span><span class="mtk1">) </span><span class="mtk4">=&gt;</span><span class="mtk1"> {</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk11">setData</span><span class="mtk1">((</span><span class="mtk12">old</span><span class="mtk1">) </span><span class="mtk4">=&gt;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">old</span><span class="mtk1">.</span><span class="mtk11">map</span><span class="mtk1">((</span><span class="mtk12">row</span><span class="mtk1">, </span><span class="mtk12">index</span><span class="mtk1">) </span><span class="mtk4">=&gt;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">index</span><span class="mtk1"> === </span><span class="mtk12">rowIndex</span><span class="mtk1"> ? </span><span class="mtk12">originalData</span><span class="mtk1">[</span><span class="mtk12">rowIndex</span><span class="mtk1">] : </span><span class="mtk12">row</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> )</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> );</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> },</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk11">updateRow</span><span class="mtk12">:</span><span class="mtk1"> (</span><span class="mtk12">rowIndex</span><span class="mtk1">: </span><span class="mtk10">number</span><span class="mtk1">) </span><span class="mtk4">=&gt;</span><span class="mtk1"> {</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk11">updateRow</span><span class="mtk1">(</span><span class="mtk12">data</span><span class="mtk1">[</span><span class="mtk12">rowIndex</span><span class="mtk1">].</span><span class="mtk12">id</span><span class="mtk1">, </span><span class="mtk12">data</span><span class="mtk1">[</span><span class="mtk12">rowIndex</span><span class="mtk1">]);</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> },</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> ...</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> })</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1">}</span></span></span></code></pre> <p>Notice that the <code>setOriginalData</code> function is no longer needed since we are updating the data on the server, which in return will automatically update the <code>originalData</code> array.</p> <p>Lastly, in the <code>EditCell</code> component, we need to update the <code>setEditedRows</code> to include the <code>updateRow</code> function for the save button.</p> <pre class="grvsc-container grvsc-has-line-highlighting default-dark" data-language="tsx" data-index="13"><code class="grvsc-code"><span class="grvsc-line"><span class="grvsc-source"><span class="mtk1">...</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk15">export</span><span class="mtk1"> </span><span class="mtk4">const</span><span class="mtk1"> </span><span class="mtk11">EditCell</span><span class="mtk1"> = ({ </span><span class="mtk12">row</span><span class="mtk1">, </span><span class="mtk12">table</span><span class="mtk1"> }) </span><span class="mtk4">=&gt;</span><span class="mtk1"> {</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> ...</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk4">const</span><span class="mtk1"> </span><span class="mtk11">setEditedRows</span><span class="mtk1"> = (</span><span class="mtk12">e</span><span class="mtk1">: </span><span class="mtk10">MouseEvent</span><span class="mtk1">&lt;</span><span class="mtk10">HTMLButtonElement</span><span class="mtk1">&gt;) </span><span class="mtk4">=&gt;</span><span class="mtk1"> {</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk4">const</span><span class="mtk1"> </span><span class="mtk12">elName</span><span class="mtk1"> = </span><span class="mtk12">e</span><span class="mtk1">.</span><span class="mtk12">currentTarget</span><span class="mtk1">.</span><span class="mtk12">name</span><span class="mtk1">;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">meta</span><span class="mtk1">?.</span><span class="mtk11">setEditedRows</span><span class="mtk1">((</span><span class="mtk12">old</span><span class="mtk1">: []) </span><span class="mtk4">=&gt;</span><span class="mtk1"> ({</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> ...</span><span class="mtk12">old</span><span class="mtk1">,</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">[row.id]:</span><span class="mtk1"> !</span><span class="mtk12">old</span><span class="mtk1">[</span><span class="mtk12">row</span><span class="mtk1">.</span><span class="mtk12">id</span><span class="mtk1">],</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> }));</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk15">if</span><span class="mtk1"> (</span><span class="mtk12">elName</span><span class="mtk1"> !== </span><span class="mtk8">&quot;edit&quot;</span><span class="mtk1">) {</span></span></span> <span class="grvsc-line grvsc-line-highlighted"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">e</span><span class="mtk1">.</span><span class="mtk12">currentTarget</span><span class="mtk1">.</span><span class="mtk12">name</span><span class="mtk1"> === </span><span class="mtk8">&quot;cancel&quot;</span><span class="mtk1"> ? </span><span class="mtk12">meta</span><span class="mtk1">?.</span><span class="mtk11">revertData</span><span class="mtk1">(</span><span class="mtk12">row</span><span class="mtk1">.</span><span class="mtk12">index</span><span class="mtk1">) : </span><span class="mtk12">meta</span><span class="mtk1">?.</span><span class="mtk11">updateRow</span><span class="mtk1">(</span><span class="mtk12">row</span><span class="mtk1">.</span><span class="mtk12">index</span><span class="mtk1">);</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> }</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> };</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> ...</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1">};</span></span></span></code></pre> <p>Below is a video of the update process with the network tab open to demonstrate the API request.</p> <video width="720" height="400" autoplay loop muted preload="none"> <source src="/c830ae09427a0b51f50fdf03b200042b/put-api.mp4" type="video/mp4"> </video> <h2 id="create-data" style="position:relative;"><a href="#create-data" aria-label="create data permalink" class="anchor before"><svg aria-hidden="true" focusable="false" height="16" version="1.1" viewBox="0 0 16 16" width="16"><path fill-rule="evenodd" d="M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z"></path></svg></a>Create data</h2> <p>Adding a new row is similar to the updating approach except that the API request will be a <code>POST</code> method.</p> <p>Let’s create two functions, one for the API request and the other for the hook that will be used in the <code>Table</code> component.</p> <pre class="grvsc-container grvsc-has-line-highlighting default-dark" data-language="ts" data-index="14"><code class="grvsc-code"><span class="grvsc-line"><span class="grvsc-source"><span class="mtk15">import</span><span class="mtk1"> </span><span class="mtk12">useSWR</span><span class="mtk1">, { </span><span class="mtk12">mutate</span><span class="mtk1"> } </span><span class="mtk15">from</span><span class="mtk1"> </span><span class="mtk8">&#39;swr&#39;</span><span class="mtk1">;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk15">import</span><span class="mtk1"> { </span><span class="mtk12">Student</span><span class="mtk1"> } </span><span class="mtk15">from</span><span class="mtk1"> </span><span class="mtk8">&#39;./types&#39;</span><span class="mtk1">;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk4">const</span><span class="mtk1"> </span><span class="mtk12">url</span><span class="mtk1"> = </span><span class="mtk8">&#39;http://localhost:5000/students&#39;</span><span class="mtk1">;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk4">async</span><span class="mtk1"> </span><span class="mtk4">function</span><span class="mtk1"> </span><span class="mtk11">updateRequest</span><span class="mtk1">(</span><span class="mtk12">id</span><span class="mtk1">: </span><span class="mtk10">number</span><span class="mtk1">, </span><span class="mtk12">data</span><span class="mtk1">: </span><span class="mtk10">Student</span><span class="mtk1">) {</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk4">const</span><span class="mtk1"> </span><span class="mtk12">response</span><span class="mtk1"> = </span><span class="mtk15">await</span><span class="mtk1"> </span><span class="mtk11">fetch</span><span class="mtk1">(</span><span class="mtk8">`</span><span class="mtk4">${</span><span class="mtk12">url</span><span class="mtk4">}</span><span class="mtk8">/</span><span class="mtk4">${</span><span class="mtk12">id</span><span class="mtk4">}</span><span class="mtk8">`</span><span class="mtk1">, {</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">method:</span><span class="mtk1"> </span><span class="mtk8">&#39;PUT&#39;</span><span class="mtk1">,</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">headers:</span><span class="mtk1"> {</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk8">&#39;Content-Type&#39;</span><span class="mtk12">:</span><span class="mtk1"> </span><span class="mtk8">&#39;application/json&#39;</span><span class="mtk1">,</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> },</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">body:</span><span class="mtk1"> </span><span class="mtk10">JSON</span><span class="mtk1">.</span><span class="mtk11">stringify</span><span class="mtk1">(</span><span class="mtk12">data</span><span class="mtk1">),</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> });</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk15">return</span><span class="mtk1"> </span><span class="mtk12">response</span><span class="mtk1">.</span><span class="mtk11">json</span><span class="mtk1">();</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1">}</span></span></span> <span class="grvsc-line"><span class="grvsc-source"></span></span> <span class="grvsc-line grvsc-line-highlighted"><span class="grvsc-source"><span class="mtk4">async</span><span class="mtk1"> </span><span class="mtk4">function</span><span class="mtk1"> </span><span class="mtk11">addRequest</span><span class="mtk1">(</span><span class="mtk12">data</span><span class="mtk1">: </span><span class="mtk10">Student</span><span class="mtk1">) {</span></span></span> <span class="grvsc-line grvsc-line-highlighted"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk4">const</span><span class="mtk1"> </span><span class="mtk12">response</span><span class="mtk1"> = </span><span class="mtk15">await</span><span class="mtk1"> </span><span class="mtk11">fetch</span><span class="mtk1">(</span><span class="mtk12">url</span><span class="mtk1">, {</span></span></span> <span class="grvsc-line grvsc-line-highlighted"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">method:</span><span class="mtk1"> </span><span class="mtk8">&#39;POST&#39;</span><span class="mtk1">,</span></span></span> <span class="grvsc-line grvsc-line-highlighted"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">headers:</span><span class="mtk1"> {</span></span></span> <span class="grvsc-line grvsc-line-highlighted"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk8">&#39;Content-Type&#39;</span><span class="mtk12">:</span><span class="mtk1"> </span><span class="mtk8">&#39;application/json&#39;</span><span class="mtk1">,</span></span></span> <span class="grvsc-line grvsc-line-highlighted"><span class="grvsc-source"><span class="mtk1"> },</span></span></span> <span class="grvsc-line grvsc-line-highlighted"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">body:</span><span class="mtk1"> </span><span class="mtk10">JSON</span><span class="mtk1">.</span><span class="mtk11">stringify</span><span class="mtk1">(</span><span class="mtk12">data</span><span class="mtk1">),</span></span></span> <span class="grvsc-line grvsc-line-highlighted"><span class="grvsc-source"><span class="mtk1"> });</span></span></span> <span class="grvsc-line grvsc-line-highlighted"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk15">return</span><span class="mtk1"> </span><span class="mtk12">response</span><span class="mtk1">.</span><span class="mtk11">json</span><span class="mtk1">();</span></span></span> <span class="grvsc-line grvsc-line-highlighted"><span class="grvsc-source"><span class="mtk1">}</span></span></span> <span class="grvsc-line"><span class="grvsc-source"></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk4">async</span><span class="mtk1"> </span><span class="mtk4">function</span><span class="mtk1"> </span><span class="mtk11">getRequest</span><span class="mtk1">() {</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk4">const</span><span class="mtk1"> </span><span class="mtk12">response</span><span class="mtk1"> = </span><span class="mtk15">await</span><span class="mtk1"> </span><span class="mtk11">fetch</span><span class="mtk1">(</span><span class="mtk12">url</span><span class="mtk1">);</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk15">return</span><span class="mtk1"> </span><span class="mtk12">response</span><span class="mtk1">.</span><span class="mtk11">json</span><span class="mtk1">();</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1">}</span></span></span> <span class="grvsc-line"><span class="grvsc-source"></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk15">export</span><span class="mtk1"> </span><span class="mtk15">default</span><span class="mtk1"> </span><span class="mtk4">function</span><span class="mtk1"> </span><span class="mtk11">useStudents</span><span class="mtk1">() {</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk4">const</span><span class="mtk1"> { </span><span class="mtk12">data</span><span class="mtk1">, </span><span class="mtk12">isValidating</span><span class="mtk1"> } = </span><span class="mtk11">useSWR</span><span class="mtk1">(</span><span class="mtk12">url</span><span class="mtk1">, </span><span class="mtk12">getRequest</span><span class="mtk1">);</span></span></span> <span class="grvsc-line"><span class="grvsc-source"></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk4">const</span><span class="mtk1"> </span><span class="mtk11">updateRow</span><span class="mtk1"> = </span><span class="mtk4">async</span><span class="mtk1"> (</span><span class="mtk12">id</span><span class="mtk1">: </span><span class="mtk10">number</span><span class="mtk1">, </span><span class="mtk12">postData</span><span class="mtk1">: </span><span class="mtk10">Student</span><span class="mtk1">) </span><span class="mtk4">=&gt;</span><span class="mtk1"> {</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk15">await</span><span class="mtk1"> </span><span class="mtk11">updateRequest</span><span class="mtk1">(</span><span class="mtk12">id</span><span class="mtk1">, </span><span class="mtk12">postData</span><span class="mtk1">);</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk11">mutate</span><span class="mtk1">(</span><span class="mtk12">url</span><span class="mtk1">);</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> };</span></span></span> <span class="grvsc-line"><span class="grvsc-source"></span></span> <span class="grvsc-line grvsc-line-highlighted"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk4">const</span><span class="mtk1"> </span><span class="mtk11">addRow</span><span class="mtk1"> = </span><span class="mtk4">async</span><span class="mtk1"> (</span><span class="mtk12">postData</span><span class="mtk1">: </span><span class="mtk10">Student</span><span class="mtk1">) </span><span class="mtk4">=&gt;</span><span class="mtk1"> {</span></span></span> <span class="grvsc-line grvsc-line-highlighted"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk15">await</span><span class="mtk1"> </span><span class="mtk11">addRequest</span><span class="mtk1">(</span><span class="mtk12">postData</span><span class="mtk1">);</span></span></span> <span class="grvsc-line grvsc-line-highlighted"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk11">mutate</span><span class="mtk1">(</span><span class="mtk12">url</span><span class="mtk1">);</span></span></span> <span class="grvsc-line grvsc-line-highlighted"><span class="grvsc-source"><span class="mtk1"> };</span></span></span> <span class="grvsc-line"><span class="grvsc-source"></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk15">return</span><span class="mtk1"> {</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">data:</span><span class="mtk1"> </span><span class="mtk12">data</span><span class="mtk1"> ?? [],</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">isValidating</span><span class="mtk1">,</span></span></span> <span class="grvsc-line grvsc-line-highlighted"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">addRow</span><span class="mtk1">,</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">updateRow</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> };</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1">}</span></span></span></code></pre> <p>Previously, in the <code>Table</code> component, we used to update both <code>data</code> and <code>originalData</code> with newly added rows.</p> <pre class="grvsc-container grvsc-has-line-highlighting default-dark" data-language="tsx" data-index="15"><code class="grvsc-code"><span class="grvsc-line"><span class="grvsc-source"><span class="mtk4">const</span><span class="mtk1"> </span><span class="mtk12">table</span><span class="mtk1"> = </span><span class="mtk11">useReactTable</span><span class="mtk1">({</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> ...</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">addRow</span><span class="mtk1">: () </span><span class="mtk4">=&gt;</span><span class="mtk1"> {</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk4">const</span><span class="mtk1"> </span><span class="mtk12">newRow</span><span class="mtk1">: </span><span class="mtk10">Student</span><span class="mtk1"> = {</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">studentId:</span><span class="mtk1"> </span><span class="mtk10">Math</span><span class="mtk1">.</span><span class="mtk11">floor</span><span class="mtk1">(</span><span class="mtk10">Math</span><span class="mtk1">.</span><span class="mtk11">random</span><span class="mtk1">() * </span><span class="mtk7">10000</span><span class="mtk1">),</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">name:</span><span class="mtk1"> </span><span class="mtk8">&quot;&quot;</span><span class="mtk1">,</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">dateOfBirth:</span><span class="mtk1"> </span><span class="mtk8">&quot;&quot;</span><span class="mtk1">,</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">major:</span><span class="mtk1"> </span><span class="mtk8">&quot;&quot;</span><span class="mtk1">,</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> };</span></span></span> <span class="grvsc-line grvsc-line-highlighted"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk4">const</span><span class="mtk1"> </span><span class="mtk11">setFunc</span><span class="mtk1"> = (</span><span class="mtk12">old</span><span class="mtk1">: </span><span class="mtk10">Student</span><span class="mtk1">[]) </span><span class="mtk4">=&gt;</span><span class="mtk1"> [...</span><span class="mtk12">old</span><span class="mtk1">, </span><span class="mtk12">newRow</span><span class="mtk1">];</span></span></span> <span class="grvsc-line grvsc-line-highlighted"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk11">setData</span><span class="mtk1">(</span><span class="mtk12">setFunc</span><span class="mtk1">);</span></span></span> <span class="grvsc-line grvsc-line-highlighted"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk11">setOriginalData</span><span class="mtk1">(</span><span class="mtk12">setFunc</span><span class="mtk1">);</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> },</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> ...</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1">})</span></span></span></code></pre> <p>Now, since we are adding the data to the server, we only need to trigger the <code>addRow</code> function from the <code>useStudents</code> hook. We don’t need any of the <code>set</code> functions anymore because after the adding request, the <code>mutate</code> function will update the <code>originalData</code> array and consequently, the <code>useEffect</code> hook will update the <code>data</code> array.</p> <pre class="grvsc-container default-dark" data-language="tsx" data-index="16"><code class="grvsc-code"><span class="grvsc-line"><span class="grvsc-source"><span class="mtk1">...</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk15">export</span><span class="mtk1"> </span><span class="mtk4">const</span><span class="mtk1"> </span><span class="mtk11">Table</span><span class="mtk1"> = () </span><span class="mtk4">=&gt;</span><span class="mtk1"> {</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk4">const</span><span class="mtk1"> { </span><span class="mtk12">data</span><span class="mtk1">: </span><span class="mtk12">originalData</span><span class="mtk1">, </span><span class="mtk12">isValidating</span><span class="mtk1">, </span><span class="mtk12">addRow</span><span class="mtk1">, </span><span class="mtk12">updateRow</span><span class="mtk1"> } = </span><span class="mtk11">useStudents</span><span class="mtk1">();</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> ...</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk4">const</span><span class="mtk1"> </span><span class="mtk12">table</span><span class="mtk1"> = </span><span class="mtk11">useReactTable</span><span class="mtk1">({</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> ...</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">addRow</span><span class="mtk1">: () </span><span class="mtk4">=&gt;</span><span class="mtk1"> {</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk4">const</span><span class="mtk1"> </span><span class="mtk12">id</span><span class="mtk1"> = </span><span class="mtk10">Math</span><span class="mtk1">.</span><span class="mtk11">floor</span><span class="mtk1">(</span><span class="mtk10">Math</span><span class="mtk1">.</span><span class="mtk11">random</span><span class="mtk1">() * </span><span class="mtk7">10000</span><span class="mtk1">);</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk4">const</span><span class="mtk1"> </span><span class="mtk12">newRow</span><span class="mtk1">: </span><span class="mtk10">Student</span><span class="mtk1"> = {</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">id</span><span class="mtk1">,</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">studentNumber:</span><span class="mtk1"> </span><span class="mtk12">id</span><span class="mtk1">,</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">name:</span><span class="mtk1"> </span><span class="mtk8">&quot;&quot;</span><span class="mtk1">,</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">dateOfBirth:</span><span class="mtk1"> </span><span class="mtk8">&quot;&quot;</span><span class="mtk1">,</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">major:</span><span class="mtk1"> </span><span class="mtk8">&quot;&quot;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> };</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk11">addRow</span><span class="mtk1">(</span><span class="mtk12">newRow</span><span class="mtk1">);</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> },</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> ...</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> })</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> ...</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1">}</span></span></span></code></pre> <p>Additionally, we added an <code>id</code> field to the <code>newRow</code> object. Below is a video of the add process with the network tab open to demonstrate the API request.</p> <video width="720" height="400" autoplay loop muted preload="none"> <source src="/703d56554b9b9065befdaab7916960e3/post-api.mp4" type="video/mp4"> </video> <h2 id="delete-data" style="position:relative;"><a href="#delete-data" aria-label="delete data permalink" class="anchor before"><svg aria-hidden="true" focusable="false" height="16" version="1.1" viewBox="0 0 16 16" width="16"><path fill-rule="evenodd" d="M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z"></path></svg></a>Delete data</h2> <p>At this point, we have the <code>useStudents</code> hook responsible for fetching, updating, and adding data. The last thing we need to do is to add the delete functionality.</p> <p>Let’s create a new function called <code>deleteRequest</code> that will be responsible for the API request and then add it to the <code>useStudents</code> hook.</p> <pre class="grvsc-container grvsc-has-line-highlighting default-dark" data-language="tsx" data-index="17"><code class="grvsc-code"><span class="grvsc-line"><span class="grvsc-source"><span class="mtk15">import</span><span class="mtk1"> </span><span class="mtk12">useSWR</span><span class="mtk1">, { </span><span class="mtk12">mutate</span><span class="mtk1"> } </span><span class="mtk15">from</span><span class="mtk1"> </span><span class="mtk8">&#39;swr&#39;</span><span class="mtk1">;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk15">import</span><span class="mtk1"> { </span><span class="mtk12">Student</span><span class="mtk1"> } </span><span class="mtk15">from</span><span class="mtk1"> </span><span class="mtk8">&#39;./types&#39;</span><span class="mtk1">;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk4">const</span><span class="mtk1"> </span><span class="mtk12">url</span><span class="mtk1"> = </span><span class="mtk8">&#39;http://localhost:5000/students&#39;</span><span class="mtk1">;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk4">async</span><span class="mtk1"> </span><span class="mtk4">function</span><span class="mtk1"> </span><span class="mtk11">updateRequest</span><span class="mtk1">(</span><span class="mtk12">id</span><span class="mtk1">: </span><span class="mtk10">number</span><span class="mtk1">, </span><span class="mtk12">data</span><span class="mtk1">: </span><span class="mtk10">Student</span><span class="mtk1">) {</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk4">const</span><span class="mtk1"> </span><span class="mtk12">response</span><span class="mtk1"> = </span><span class="mtk15">await</span><span class="mtk1"> </span><span class="mtk11">fetch</span><span class="mtk1">(</span><span class="mtk8">`</span><span class="mtk4">${</span><span class="mtk12">url</span><span class="mtk4">}</span><span class="mtk8">/</span><span class="mtk4">${</span><span class="mtk12">id</span><span class="mtk4">}</span><span class="mtk8">`</span><span class="mtk1">, {</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">method:</span><span class="mtk1"> </span><span class="mtk8">&#39;PUT&#39;</span><span class="mtk1">,</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">headers:</span><span class="mtk1"> {</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk8">&#39;Content-Type&#39;</span><span class="mtk12">:</span><span class="mtk1"> </span><span class="mtk8">&#39;application/json&#39;</span><span class="mtk1">,</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> },</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">body:</span><span class="mtk1"> </span><span class="mtk10">JSON</span><span class="mtk1">.</span><span class="mtk11">stringify</span><span class="mtk1">(</span><span class="mtk12">data</span><span class="mtk1">),</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> });</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk15">return</span><span class="mtk1"> </span><span class="mtk12">response</span><span class="mtk1">.</span><span class="mtk11">json</span><span class="mtk1">();</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1">}</span></span></span> <span class="grvsc-line"><span class="grvsc-source"></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk4">async</span><span class="mtk1"> </span><span class="mtk4">function</span><span class="mtk1"> </span><span class="mtk11">addRequest</span><span class="mtk1">(</span><span class="mtk12">data</span><span class="mtk1">: </span><span class="mtk10">Student</span><span class="mtk1">) {</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk4">const</span><span class="mtk1"> </span><span class="mtk12">response</span><span class="mtk1"> = </span><span class="mtk15">await</span><span class="mtk1"> </span><span class="mtk11">fetch</span><span class="mtk1">(</span><span class="mtk12">url</span><span class="mtk1">, {</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">method:</span><span class="mtk1"> </span><span class="mtk8">&#39;POST&#39;</span><span class="mtk1">,</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">headers:</span><span class="mtk1"> {</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk8">&#39;Content-Type&#39;</span><span class="mtk12">:</span><span class="mtk1"> </span><span class="mtk8">&#39;application/json&#39;</span><span class="mtk1">,</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> },</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">body:</span><span class="mtk1"> </span><span class="mtk10">JSON</span><span class="mtk1">.</span><span class="mtk11">stringify</span><span class="mtk1">(</span><span class="mtk12">data</span><span class="mtk1">),</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> });</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk15">return</span><span class="mtk1"> </span><span class="mtk12">response</span><span class="mtk1">.</span><span class="mtk11">json</span><span class="mtk1">();</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1">}</span></span></span> <span class="grvsc-line"><span class="grvsc-source"></span></span> <span class="grvsc-line grvsc-line-highlighted"><span class="grvsc-source"><span class="mtk4">async</span><span class="mtk1"> </span><span class="mtk4">function</span><span class="mtk1"> </span><span class="mtk11">deleteRequest</span><span class="mtk1">(</span><span class="mtk12">id</span><span class="mtk1">: </span><span class="mtk10">number</span><span class="mtk1">) {</span></span></span> <span class="grvsc-line grvsc-line-highlighted"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk4">const</span><span class="mtk1"> </span><span class="mtk12">response</span><span class="mtk1"> = </span><span class="mtk15">await</span><span class="mtk1"> </span><span class="mtk11">fetch</span><span class="mtk1">(</span><span class="mtk8">`</span><span class="mtk4">${</span><span class="mtk12">url</span><span class="mtk4">}</span><span class="mtk8">/</span><span class="mtk4">${</span><span class="mtk12">id</span><span class="mtk4">}</span><span class="mtk8">`</span><span class="mtk1">, {</span></span></span> <span class="grvsc-line grvsc-line-highlighted"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">method:</span><span class="mtk1"> </span><span class="mtk8">&#39;DELETE&#39;</span><span class="mtk1">,</span></span></span> <span class="grvsc-line grvsc-line-highlighted"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">headers:</span><span class="mtk1"> {</span></span></span> <span class="grvsc-line grvsc-line-highlighted"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk8">&#39;Content-Type&#39;</span><span class="mtk12">:</span><span class="mtk1"> </span><span class="mtk8">&#39;application/json&#39;</span><span class="mtk1">,</span></span></span> <span class="grvsc-line grvsc-line-highlighted"><span class="grvsc-source"><span class="mtk1"> }</span></span></span> <span class="grvsc-line grvsc-line-highlighted"><span class="grvsc-source"><span class="mtk1"> });</span></span></span> <span class="grvsc-line grvsc-line-highlighted"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk15">return</span><span class="mtk1"> </span><span class="mtk12">response</span><span class="mtk1">.</span><span class="mtk11">json</span><span class="mtk1">();</span></span></span> <span class="grvsc-line grvsc-line-highlighted"><span class="grvsc-source"><span class="mtk1">}</span></span></span> <span class="grvsc-line"><span class="grvsc-source"></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk4">async</span><span class="mtk1"> </span><span class="mtk4">function</span><span class="mtk1"> </span><span class="mtk11">getRequest</span><span class="mtk1">() {</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk4">const</span><span class="mtk1"> </span><span class="mtk12">response</span><span class="mtk1"> = </span><span class="mtk15">await</span><span class="mtk1"> </span><span class="mtk11">fetch</span><span class="mtk1">(</span><span class="mtk12">url</span><span class="mtk1">);</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk15">return</span><span class="mtk1"> </span><span class="mtk12">response</span><span class="mtk1">.</span><span class="mtk11">json</span><span class="mtk1">();</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1">}</span></span></span> <span class="grvsc-line"><span class="grvsc-source"></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk15">export</span><span class="mtk1"> </span><span class="mtk15">default</span><span class="mtk1"> </span><span class="mtk4">function</span><span class="mtk1"> </span><span class="mtk11">useStudents</span><span class="mtk1">() {</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk4">const</span><span class="mtk1"> { </span><span class="mtk12">data</span><span class="mtk1">, </span><span class="mtk12">isValidating</span><span class="mtk1"> } = </span><span class="mtk11">useSWR</span><span class="mtk1">(</span><span class="mtk12">url</span><span class="mtk1">, </span><span class="mtk12">getRequest</span><span class="mtk1">);</span></span></span> <span class="grvsc-line"><span class="grvsc-source"></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk4">const</span><span class="mtk1"> </span><span class="mtk11">updateRow</span><span class="mtk1"> = </span><span class="mtk4">async</span><span class="mtk1"> (</span><span class="mtk12">id</span><span class="mtk1">: </span><span class="mtk10">number</span><span class="mtk1">, </span><span class="mtk12">postData</span><span class="mtk1">: </span><span class="mtk10">Student</span><span class="mtk1">) </span><span class="mtk4">=&gt;</span><span class="mtk1"> {</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk15">await</span><span class="mtk1"> </span><span class="mtk11">updateRequest</span><span class="mtk1">(</span><span class="mtk12">id</span><span class="mtk1">, </span><span class="mtk12">postData</span><span class="mtk1">);</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk11">mutate</span><span class="mtk1">(</span><span class="mtk12">url</span><span class="mtk1">);</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> };</span></span></span> <span class="grvsc-line"><span class="grvsc-source"></span></span> <span class="grvsc-line grvsc-line-highlighted"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk4">const</span><span class="mtk1"> </span><span class="mtk11">deleteRow</span><span class="mtk1"> = </span><span class="mtk4">async</span><span class="mtk1"> (</span><span class="mtk12">id</span><span class="mtk1">: </span><span class="mtk10">number</span><span class="mtk1">) </span><span class="mtk4">=&gt;</span><span class="mtk1"> {</span></span></span> <span class="grvsc-line grvsc-line-highlighted"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk15">await</span><span class="mtk1"> </span><span class="mtk11">deleteRequest</span><span class="mtk1">(</span><span class="mtk12">id</span><span class="mtk1">);</span></span></span> <span class="grvsc-line grvsc-line-highlighted"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk11">mutate</span><span class="mtk1">(</span><span class="mtk12">url</span><span class="mtk1">);</span></span></span> <span class="grvsc-line grvsc-line-highlighted"><span class="grvsc-source"><span class="mtk1"> };</span></span></span> <span class="grvsc-line"><span class="grvsc-source"></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk4">const</span><span class="mtk1"> </span><span class="mtk11">addRow</span><span class="mtk1"> = </span><span class="mtk4">async</span><span class="mtk1"> (</span><span class="mtk12">postData</span><span class="mtk1">: </span><span class="mtk10">Student</span><span class="mtk1">) </span><span class="mtk4">=&gt;</span><span class="mtk1"> {</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk15">await</span><span class="mtk1"> </span><span class="mtk11">addRequest</span><span class="mtk1">(</span><span class="mtk12">postData</span><span class="mtk1">);</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk11">mutate</span><span class="mtk1">(</span><span class="mtk12">url</span><span class="mtk1">);</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> };</span></span></span> <span class="grvsc-line"><span class="grvsc-source"></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk15">return</span><span class="mtk1"> {</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">data:</span><span class="mtk1"> </span><span class="mtk12">data</span><span class="mtk1"> ?? [],</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">isValidating</span><span class="mtk1">,</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">addRow</span><span class="mtk1">,</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">updateRow</span><span class="mtk1">,</span></span></span> <span class="grvsc-line grvsc-line-highlighted"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">deleteRow</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> };</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1">}</span></span></span></code></pre> <p>Then, in the <code>Table</code> component, similar to the previous step, we’re removing the <code>set</code> functions and triggering the <code>deleteRow</code> function from the <code>useStudents</code> hook.</p> <pre class="grvsc-container default-dark" data-language="tsx" data-index="18"><code class="grvsc-code"><span class="grvsc-line"><span class="grvsc-source"><span class="mtk1">...</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk15">export</span><span class="mtk1"> </span><span class="mtk4">const</span><span class="mtk1"> </span><span class="mtk11">Table</span><span class="mtk1"> = () </span><span class="mtk4">=&gt;</span><span class="mtk1"> {</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk4">const</span><span class="mtk1"> { </span><span class="mtk12">data</span><span class="mtk1">: </span><span class="mtk12">originalData</span><span class="mtk1">, </span><span class="mtk12">isValidating</span><span class="mtk1">, </span><span class="mtk12">addRow</span><span class="mtk1">, </span><span class="mtk12">updateRow</span><span class="mtk1">, </span><span class="mtk12">deleteRow</span><span class="mtk1"> } = </span><span class="mtk11">useStudents</span><span class="mtk1">();</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> ...</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk4">const</span><span class="mtk1"> </span><span class="mtk12">table</span><span class="mtk1"> = </span><span class="mtk11">useReactTable</span><span class="mtk1">({</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> ...</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">removeRow</span><span class="mtk1">: (</span><span class="mtk12">rowIndex</span><span class="mtk1">: </span><span class="mtk10">number</span><span class="mtk1">) </span><span class="mtk4">=&gt;</span><span class="mtk1"> {</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk11">deleteRow</span><span class="mtk1">(</span><span class="mtk12">data</span><span class="mtk1">[</span><span class="mtk12">rowIndex</span><span class="mtk1">].</span><span class="mtk12">id</span><span class="mtk1">);</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> },</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> ...</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> })</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> ...</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1">}</span></span></span></code></pre> <p>Lastly, since we enabled removing multiple rows in the previous part, we need to update the <code>removeSelectedRows</code> function to loop through each row and trigger the <code>deleteRow</code> function.</p> <pre class="grvsc-container default-dark" data-language="tsx" data-index="19"><code class="grvsc-code"><span class="grvsc-line"><span class="grvsc-source"><span class="mtk1">...</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk15">export</span><span class="mtk1"> </span><span class="mtk4">const</span><span class="mtk1"> </span><span class="mtk11">Table</span><span class="mtk1"> = () </span><span class="mtk4">=&gt;</span><span class="mtk1"> {</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk4">const</span><span class="mtk1"> { </span><span class="mtk12">data</span><span class="mtk1">: </span><span class="mtk12">originalData</span><span class="mtk1">, </span><span class="mtk12">isValidating</span><span class="mtk1">, </span><span class="mtk12">addRow</span><span class="mtk1">, </span><span class="mtk12">updateRow</span><span class="mtk1">, </span><span class="mtk12">deleteRow</span><span class="mtk1"> } = </span><span class="mtk11">useStudents</span><span class="mtk1">();</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> ...</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk4">const</span><span class="mtk1"> </span><span class="mtk12">table</span><span class="mtk1"> = </span><span class="mtk11">useReactTable</span><span class="mtk1">({</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> ...</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">removeRow</span><span class="mtk1">: (</span><span class="mtk12">rowIndex</span><span class="mtk1">: </span><span class="mtk10">number</span><span class="mtk1">) </span><span class="mtk4">=&gt;</span><span class="mtk1"> {</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk11">deleteRow</span><span class="mtk1">(</span><span class="mtk12">data</span><span class="mtk1">[</span><span class="mtk12">rowIndex</span><span class="mtk1">].</span><span class="mtk12">id</span><span class="mtk1">);</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> },</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk11">removeSelectedRows</span><span class="mtk12">:</span><span class="mtk1"> (</span><span class="mtk12">selectedRows</span><span class="mtk1">: </span><span class="mtk10">number</span><span class="mtk1">[]) </span><span class="mtk4">=&gt;</span><span class="mtk1"> {</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">selectedRows</span><span class="mtk1">.</span><span class="mtk11">forEach</span><span class="mtk1">((</span><span class="mtk12">rowIndex</span><span class="mtk1">) </span><span class="mtk4">=&gt;</span><span class="mtk1"> {</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk11">deleteRow</span><span class="mtk1">(</span><span class="mtk12">data</span><span class="mtk1">[</span><span class="mtk12">rowIndex</span><span class="mtk1">].</span><span class="mtk12">id</span><span class="mtk1">);</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> });</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> },</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> ...</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> })</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> ...</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1">}</span></span></span></code></pre> <p>Below is a video of the delete process with the network tab open to demonstrate the API request.</p> <video width="720" height="400" autoplay loop muted preload="none"> <source src="/3260ffaf8a30f22f4ba4998293299a4a/delete-all-api.mp4" type="video/mp4"> </video> <h2 id="complete-code" style="position:relative;"><a href="#complete-code" aria-label="complete code permalink" class="anchor before"><svg aria-hidden="true" focusable="false" height="16" version="1.1" viewBox="0 0 16 16" width="16"><path fill-rule="evenodd" d="M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z"></path></svg></a>Complete code</h2> <p>The complete code is available in <a href="https://github.com/muhimasri/react-editable-table">this repository</a>. If you liked the tutorial, please <a href="https://github.com/muhimasri/react-editable-table/stargazers">star the repository</a>, and feel free to request new features!</p> <h2 id="summary" style="position:relative;"><a href="#summary" aria-label="summary permalink" class="anchor before"><svg aria-hidden="true" focusable="false" height="16" version="1.1" viewBox="0 0 16 16" width="16"><path fill-rule="evenodd" d="M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z"></path></svg></a>Summary</h2> <p>In this part, we learned how to read and write table data with API requests using React Tanstack. We used JSON Server to create a fake REST API and SWR to fetch and revalidate data. We also learned how to update, add, and delete data from the server.</p> <p>Bye for now 👋</p> <style class="grvsc-styles"> .grvsc-container { overflow: auto; position: relative; -webkit-overflow-scrolling: touch; padding-top: 1rem; padding-top: var(--grvsc-padding-top, var(--grvsc-padding-v, 1rem)); padding-bottom: 1rem; padding-bottom: var(--grvsc-padding-bottom, var(--grvsc-padding-v, 1rem)); border-radius: 8px; border-radius: var(--grvsc-border-radius, 8px); font-feature-settings: normal; line-height: 1.4; } .grvsc-code { display: table; } .grvsc-line { display: table-row; box-sizing: border-box; width: 100%; position: relative; } .grvsc-line > * { position: relative; } .grvsc-gutter-pad { display: table-cell; padding-left: 0.75rem; padding-left: calc(var(--grvsc-padding-left, var(--grvsc-padding-h, 1.5rem)) / 2); } .grvsc-gutter { display: table-cell; -webkit-user-select: none; -moz-user-select: none; user-select: none; } .grvsc-gutter::before { content: attr(data-content); } .grvsc-source { display: table-cell; padding-left: 1.5rem; padding-left: var(--grvsc-padding-left, var(--grvsc-padding-h, 1.5rem)); padding-right: 1.5rem; padding-right: var(--grvsc-padding-right, var(--grvsc-padding-h, 1.5rem)); } .grvsc-source:empty::after { content: ' '; -webkit-user-select: none; -moz-user-select: none; user-select: none; } .grvsc-gutter + .grvsc-source { padding-left: 0.75rem; padding-left: calc(var(--grvsc-padding-left, var(--grvsc-padding-h, 1.5rem)) / 2); } /* Line transformer styles */ .grvsc-has-line-highlighting > .grvsc-code > .grvsc-line::before { content: ' '; position: absolute; width: 100%; } .grvsc-line-diff-add::before { background-color: var(--grvsc-line-diff-add-background-color, rgba(0, 255, 60, 0.2)); } .grvsc-line-diff-del::before { background-color: var(--grvsc-line-diff-del-background-color, rgba(255, 0, 20, 0.2)); } .grvsc-line-number { padding: 0 2px; text-align: right; opacity: 0.7; } .default-dark { background-color: #1E1E1E; color: #D4D4D4; } .default-dark .mtk3 { color: #6A9955; } .default-dark .mtk1 { color: #D4D4D4; } .default-dark .mtk12 { color: #9CDCFE; } .default-dark .mtk7 { color: #B5CEA8; } .default-dark .mtk8 { color: #CE9178; } .default-dark .mtk6 { color: #D7BA7D; } .default-dark .mtk14 { color: #F44747; } .default-dark .mtk15 { color: #C586C0; } .default-dark .mtk4 { color: #569CD6; } .default-dark .mtk10 { color: #4EC9B0; } .default-dark .mtk11 { color: #DCDCAA; } .default-dark .grvsc-line-highlighted::before { background-color: var(--grvsc-line-highlighted-background-color, rgba(255, 255, 255, 0.1)); box-shadow: inset var(--grvsc-line-highlighted-border-width, 4px) 0 0 0 var(--grvsc-line-highlighted-border-color, rgba(255, 255, 255, 0.5)); } </style><![CDATA[[Part 3] Validate Table Rows and Fields Using React Tanstack]]>https://muhimasri.comvalidate-react-tablehttps://muhimasri.comvalidate-react-table<p>In the <a href="/blogs/add-remove-react-table-rows/">previous part</a>, we learned how to add and remove table rows using React Tanstack. In this part, we will learn how to validate table rows and fields such as required input, date, select, and other custom validations.</p> <p>Below is a short video of how we want the table to look and behave at the end of this tutorial:</p> <video width="720" height="400" autoplay loop muted preload="none"> <source src="/117bf2cad5b6126c4f0b36fd4b08059f/validate-table-rows.mp4" type="video/mp4"> </video> <p><em>As we continue building upon the same code from the previous part, it’s recommended that you go through previous parts to understand how the code structure works as we will not be explaining it here. You can navigate to any part using the table of contents.</em></p> <h2 id="input-validation" style="position:relative;"><a href="#input-validation" aria-label="input validation permalink" class="anchor before"><svg aria-hidden="true" focusable="false" height="16" version="1.1" viewBox="0 0 16 16" width="16"><path fill-rule="evenodd" d="M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z"></path></svg></a>Input Validation</h2> <p>In this section, we will utilize the native HTML5 input validation. We will use the <code>required</code> attribute to validate the required fields. We will also use the <code>pattern</code> attribute to validate more complex scenarios.</p> <h3 id="required-fields" style="position:relative;"><a href="#required-fields" aria-label="required fields permalink" class="anchor before"><svg aria-hidden="true" focusable="false" height="16" version="1.1" viewBox="0 0 16 16" width="16"><path fill-rule="evenodd" d="M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z"></path></svg></a>Required Fields</h3> <p>Adding <code>required</code> attribute is a straightforward way to validate the required fields. The attribute is a boolean, meaning it does not require a value. It only needs to be present in the element to validate the field.</p> <p>We can add it directly to the input element in the <code>TableCell</code> component.</p> <pre class="grvsc-container grvsc-has-line-highlighting default-dark" data-language="jsx" data-index="0"><code class="grvsc-code"><span class="grvsc-line"><span class="grvsc-source"><span class="mtk17">&lt;</span><span class="mtk4">input</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">value</span><span class="mtk1">=</span><span class="mtk4">{</span><span class="mtk12">value</span><span class="mtk4">}</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">onChange</span><span class="mtk1">=</span><span class="mtk4">{</span><span class="mtk12">e</span><span class="mtk1"> </span><span class="mtk4">=&gt;</span><span class="mtk1"> </span><span class="mtk11">setValue</span><span class="mtk1">(</span><span class="mtk12">e</span><span class="mtk1">.</span><span class="mtk12">target</span><span class="mtk1">.</span><span class="mtk12">value</span><span class="mtk1">)</span><span class="mtk4">}</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">onBlur</span><span class="mtk1">=</span><span class="mtk4">{</span><span class="mtk12">onBlur</span><span class="mtk4">}</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">type</span><span class="mtk1">=</span><span class="mtk4">{</span><span class="mtk12">columnMeta</span><span class="mtk1">?.</span><span class="mtk12">type</span><span class="mtk1"> || </span><span class="mtk8">&quot;text&quot;</span><span class="mtk4">}</span></span></span> <span class="grvsc-line grvsc-line-highlighted"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">required</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk17">/&gt;</span></span></span></code></pre> <p>Also, when the validation is triggered, an <code>:invalid</code> pseudo-class will be added to the input element. We can use this pseudo-class to style the input element.</p> <pre class="grvsc-container default-dark" data-language="css" data-index="1"><code class="grvsc-code"><span class="grvsc-line"><span class="grvsc-source"><span class="mtk6">input:invalid</span><span class="mtk1"> {</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">border</span><span class="mtk1">: </span><span class="mtk7">2px</span><span class="mtk1"> </span><span class="mtk8">solid</span><span class="mtk1"> </span><span class="mtk8">red</span><span class="mtk1">;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1">}</span></span></span></code></pre> <p>Now, if we try the demo below, we will see that an empty field will be highlighted with a red border.</p> <div id="ValidateReactTableOne" data-code data-height="350px"></div> <p>The approach we used above is simple. However, it has a limitation. All fields will be validated, even the ones that are not required. To solve this problem, we will add a <code>required</code> property to the column definition in the <code>column.ts</code> file.</p> <pre class="grvsc-container grvsc-has-line-highlighting default-dark" data-language="ts" data-index="2"><code class="grvsc-code"><span class="grvsc-line"><span class="grvsc-source"><span class="mtk1">...</span></span></span> <span class="grvsc-line"><span class="grvsc-source"></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk15">export</span><span class="mtk1"> </span><span class="mtk4">const</span><span class="mtk1"> </span><span class="mtk12">columns</span><span class="mtk1"> = [</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> ...</span></span></span> <span class="grvsc-line"><span class="grvsc-source"></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">columnHelper</span><span class="mtk1">.</span><span class="mtk11">accessor</span><span class="mtk1">(</span><span class="mtk8">&#39;name&#39;</span><span class="mtk1">, {</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">header:</span><span class="mtk1"> </span><span class="mtk8">&#39;Full Name&#39;</span><span class="mtk1">,</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">cell:</span><span class="mtk1"> </span><span class="mtk12">TableCell</span><span class="mtk1">,</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">meta:</span><span class="mtk1"> {</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">type:</span><span class="mtk1"> </span><span class="mtk8">&#39;text&#39;</span><span class="mtk1">,</span></span></span> <span class="grvsc-line grvsc-line-highlighted"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">required:</span><span class="mtk1"> </span><span class="mtk4">true</span><span class="mtk1">,</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> },</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> })</span></span></span> <span class="grvsc-line"><span class="grvsc-source"></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1">...</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1">]</span></span></span></code></pre> <p>Then, in the <code>TableCell</code> component, we will check if the <code>required</code> property is present in the <code>columnMeta</code> object. This way, only the fields with the <code>required</code> property will be validated.</p> <pre class="grvsc-container grvsc-has-line-highlighting default-dark" data-language="jsx" data-index="3"><code class="grvsc-code"><span class="grvsc-line"><span class="grvsc-source"><span class="mtk1">...</span></span></span> <span class="grvsc-line"><span class="grvsc-source"></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk15">export</span><span class="mtk1"> </span><span class="mtk4">const</span><span class="mtk1"> </span><span class="mtk11">TableCell</span><span class="mtk1"> = ({ </span><span class="mtk12">getValue</span><span class="mtk1">, </span><span class="mtk12">row</span><span class="mtk1">, </span><span class="mtk12">column</span><span class="mtk1">, </span><span class="mtk12">table</span><span class="mtk1"> }) </span><span class="mtk4">=&gt;</span><span class="mtk1"> {</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> ...</span></span></span> <span class="grvsc-line"><span class="grvsc-source"></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk4">const</span><span class="mtk1"> </span><span class="mtk12">columnMeta</span><span class="mtk1"> = </span><span class="mtk12">column</span><span class="mtk1">.</span><span class="mtk12">columnDef</span><span class="mtk1">.</span><span class="mtk12">meta</span><span class="mtk1">;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> ...</span></span></span> <span class="grvsc-line"><span class="grvsc-source"></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk15">if</span><span class="mtk1"> (</span><span class="mtk12">tableMeta</span><span class="mtk1">?.</span><span class="mtk12">editedRows</span><span class="mtk1">[</span><span class="mtk12">row</span><span class="mtk1">.</span><span class="mtk12">id</span><span class="mtk1">]) {</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk15">return</span><span class="mtk1"> </span><span class="mtk12">columnMeta</span><span class="mtk1">?.</span><span class="mtk12">type</span><span class="mtk1"> === </span><span class="mtk8">&quot;select&quot;</span><span class="mtk1"> ? (</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk17">&lt;</span><span class="mtk4">select</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">onChange</span><span class="mtk1">=</span><span class="mtk4">{</span><span class="mtk12">onSelectChange</span><span class="mtk4">}</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">value</span><span class="mtk1">=</span><span class="mtk4">{</span><span class="mtk12">initialValue</span><span class="mtk4">}</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk17">&gt;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk4">{</span><span class="mtk12">columnMeta</span><span class="mtk1">?.</span><span class="mtk12">options</span><span class="mtk1">?.</span><span class="mtk11">map</span><span class="mtk1">((</span><span class="mtk12">option</span><span class="mtk1">: </span><span class="mtk10">Option</span><span class="mtk1">) </span><span class="mtk4">=&gt;</span><span class="mtk1"> (</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk17">&lt;</span><span class="mtk4">option</span><span class="mtk1"> </span><span class="mtk12">key</span><span class="mtk1">=</span><span class="mtk4">{</span><span class="mtk12">option</span><span class="mtk1">.</span><span class="mtk12">value</span><span class="mtk4">}</span><span class="mtk1"> </span><span class="mtk12">value</span><span class="mtk1">=</span><span class="mtk4">{</span><span class="mtk12">option</span><span class="mtk1">.</span><span class="mtk12">value</span><span class="mtk4">}</span><span class="mtk17">&gt;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk4">{</span><span class="mtk12">option</span><span class="mtk1">.</span><span class="mtk12">label</span><span class="mtk4">}</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk17">&lt;/</span><span class="mtk4">option</span><span class="mtk17">&gt;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> ))</span><span class="mtk4">}</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk17">&lt;/</span><span class="mtk4">select</span><span class="mtk17">&gt;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> ) : (</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk17">&lt;</span><span class="mtk4">input</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">value</span><span class="mtk1">=</span><span class="mtk4">{</span><span class="mtk12">value</span><span class="mtk4">}</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">onChange</span><span class="mtk1">=</span><span class="mtk4">{</span><span class="mtk1">(</span><span class="mtk12">e</span><span class="mtk1">) </span><span class="mtk4">=&gt;</span><span class="mtk1"> </span><span class="mtk11">setValue</span><span class="mtk1">(</span><span class="mtk12">e</span><span class="mtk1">.</span><span class="mtk12">target</span><span class="mtk1">.</span><span class="mtk12">value</span><span class="mtk1">)</span><span class="mtk4">}</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">onBlur</span><span class="mtk1">=</span><span class="mtk4">{</span><span class="mtk12">onBlur</span><span class="mtk4">}</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">type</span><span class="mtk1">=</span><span class="mtk4">{</span><span class="mtk12">columnMeta</span><span class="mtk1">?.</span><span class="mtk12">type</span><span class="mtk1"> || </span><span class="mtk8">&quot;text&quot;</span><span class="mtk4">}</span></span></span> <span class="grvsc-line grvsc-line-highlighted"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">required</span><span class="mtk1">=</span><span class="mtk4">{</span><span class="mtk12">columnMeta</span><span class="mtk1">?.</span><span class="mtk12">required</span><span class="mtk4">}</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk17">/&gt;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> );</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> }</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk15">return</span><span class="mtk1"> </span><span class="mtk17">&lt;</span><span class="mtk4">span</span><span class="mtk17">&gt;</span><span class="mtk4">{</span><span class="mtk12">value</span><span class="mtk4">}</span><span class="mtk17">&lt;/</span><span class="mtk4">span</span><span class="mtk17">&gt;</span><span class="mtk1">;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1">};</span></span></span> <span class="grvsc-line"><span class="grvsc-source"></span></span></code></pre> <div id="ValidateReactTableTwo" data-code data-height="350px"></div> <p>The above demo shows how the <code>required</code> property is only triggered on the “name” field.</p> <h3 id="select-validation" style="position:relative;"><a href="#select-validation" aria-label="select validation permalink" class="anchor before"><svg aria-hidden="true" focusable="false" height="16" version="1.1" viewBox="0 0 16 16" width="16"><path fill-rule="evenodd" d="M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z"></path></svg></a>Select Validation</h3> <p>The select validation is similar to the previous validation. We will use the <code>required</code> attribute to validate the <code>select</code> field, but we must add an empty option to the select element to make it work. Also, we will use the <code>:invalid</code> pseudo-class to style the <code>select</code> element.</p> <pre class="grvsc-container grvsc-has-line-highlighting default-dark" data-language="ts" data-index="4"><code class="grvsc-code"><span class="grvsc-line"><span class="grvsc-source"><span class="mtk1">...</span></span></span> <span class="grvsc-line"><span class="grvsc-source"></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk15">export</span><span class="mtk1"> </span><span class="mtk4">const</span><span class="mtk1"> </span><span class="mtk12">columns</span><span class="mtk1"> = [</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> ...</span></span></span> <span class="grvsc-line"><span class="grvsc-source"></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">columnHelper</span><span class="mtk1">.</span><span class="mtk11">accessor</span><span class="mtk1">(</span><span class="mtk8">&#39;major&#39;</span><span class="mtk1">, {</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">header:</span><span class="mtk1"> </span><span class="mtk8">&#39;Major&#39;</span><span class="mtk1">,</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">cell:</span><span class="mtk1"> </span><span class="mtk12">TableCell</span><span class="mtk1">,</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">meta:</span><span class="mtk1"> {</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">type:</span><span class="mtk1"> </span><span class="mtk8">&#39;select&#39;</span><span class="mtk1">,</span></span></span> <span class="grvsc-line grvsc-line-highlighted"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">required:</span><span class="mtk1"> </span><span class="mtk4">true</span><span class="mtk1">,</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">options:</span><span class="mtk1"> [</span></span></span> <span class="grvsc-line grvsc-line-highlighted"><span class="grvsc-source"><span class="mtk1"> { </span><span class="mtk12">value:</span><span class="mtk1"> </span><span class="mtk8">&#39;&#39;</span><span class="mtk1">, </span><span class="mtk12">label:</span><span class="mtk1"> </span><span class="mtk8">&#39;Select&#39;</span><span class="mtk1"> },</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> { </span><span class="mtk12">value:</span><span class="mtk1"> </span><span class="mtk8">&#39;Computer Science&#39;</span><span class="mtk1">, </span><span class="mtk12">label:</span><span class="mtk1"> </span><span class="mtk8">&#39;Computer Science&#39;</span><span class="mtk1"> },</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> { </span><span class="mtk12">value:</span><span class="mtk1"> </span><span class="mtk8">&#39;Communications&#39;</span><span class="mtk1">, </span><span class="mtk12">label:</span><span class="mtk1"> </span><span class="mtk8">&#39;Communications&#39;</span><span class="mtk1"> },</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> { </span><span class="mtk12">value:</span><span class="mtk1"> </span><span class="mtk8">&#39;Business&#39;</span><span class="mtk1">, </span><span class="mtk12">label:</span><span class="mtk1"> </span><span class="mtk8">&#39;Business&#39;</span><span class="mtk1"> },</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> { </span><span class="mtk12">value:</span><span class="mtk1"> </span><span class="mtk8">&#39;Psychology&#39;</span><span class="mtk1">, </span><span class="mtk12">label:</span><span class="mtk1"> </span><span class="mtk8">&#39;Psychology&#39;</span><span class="mtk1"> },</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> ],</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> },</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> }),</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">columnHelper</span><span class="mtk1">.</span><span class="mtk11">display</span><span class="mtk1">({</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">id:</span><span class="mtk1"> </span><span class="mtk8">&#39;edit&#39;</span><span class="mtk1">,</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">cell:</span><span class="mtk1"> </span><span class="mtk12">EditCell</span><span class="mtk1">,</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> }),</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1">]</span></span></span> <span class="grvsc-line"><span class="grvsc-source"></span></span></code></pre> <pre class="grvsc-container grvsc-has-line-highlighting default-dark" data-language="jsx" data-index="5"><code class="grvsc-code"><span class="grvsc-line"><span class="grvsc-source"><span class="mtk1">...</span></span></span> <span class="grvsc-line"><span class="grvsc-source"></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk15">export</span><span class="mtk1"> </span><span class="mtk4">const</span><span class="mtk1"> </span><span class="mtk11">TableCell</span><span class="mtk1"> = ({ </span><span class="mtk12">getValue</span><span class="mtk1">, </span><span class="mtk12">row</span><span class="mtk1">, </span><span class="mtk12">column</span><span class="mtk1">, </span><span class="mtk12">table</span><span class="mtk1"> }) </span><span class="mtk4">=&gt;</span><span class="mtk1"> {</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> ...</span></span></span> <span class="grvsc-line"><span class="grvsc-source"></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk4">const</span><span class="mtk1"> </span><span class="mtk12">columnMeta</span><span class="mtk1"> = </span><span class="mtk12">column</span><span class="mtk1">.</span><span class="mtk12">columnDef</span><span class="mtk1">.</span><span class="mtk12">meta</span><span class="mtk1">;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> ...</span></span></span> <span class="grvsc-line"><span class="grvsc-source"></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk15">if</span><span class="mtk1"> (</span><span class="mtk12">tableMeta</span><span class="mtk1">?.</span><span class="mtk12">editedRows</span><span class="mtk1">[</span><span class="mtk12">row</span><span class="mtk1">.</span><span class="mtk12">id</span><span class="mtk1">]) {</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk15">return</span><span class="mtk1"> </span><span class="mtk12">columnMeta</span><span class="mtk1">?.</span><span class="mtk12">type</span><span class="mtk1"> === </span><span class="mtk8">&quot;select&quot;</span><span class="mtk1"> ? (</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk17">&lt;</span><span class="mtk4">select</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">onChange</span><span class="mtk1">=</span><span class="mtk4">{</span><span class="mtk12">onSelectChange</span><span class="mtk4">}</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">value</span><span class="mtk1">=</span><span class="mtk4">{</span><span class="mtk12">initialValue</span><span class="mtk4">}</span></span></span> <span class="grvsc-line grvsc-line-highlighted"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">required</span><span class="mtk1">=</span><span class="mtk4">{</span><span class="mtk12">columnMeta</span><span class="mtk1">?.</span><span class="mtk12">required</span><span class="mtk4">}</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk17">&gt;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk4">{</span><span class="mtk12">columnMeta</span><span class="mtk1">?.</span><span class="mtk12">options</span><span class="mtk1">?.</span><span class="mtk11">map</span><span class="mtk1">((</span><span class="mtk12">option</span><span class="mtk1">: </span><span class="mtk10">Option</span><span class="mtk1">) </span><span class="mtk4">=&gt;</span><span class="mtk1"> (</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk17">&lt;</span><span class="mtk4">option</span><span class="mtk1"> </span><span class="mtk12">key</span><span class="mtk1">=</span><span class="mtk4">{</span><span class="mtk12">option</span><span class="mtk1">.</span><span class="mtk12">value</span><span class="mtk4">}</span><span class="mtk1"> </span><span class="mtk12">value</span><span class="mtk1">=</span><span class="mtk4">{</span><span class="mtk12">option</span><span class="mtk1">.</span><span class="mtk12">value</span><span class="mtk4">}</span><span class="mtk17">&gt;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk4">{</span><span class="mtk12">option</span><span class="mtk1">.</span><span class="mtk12">label</span><span class="mtk4">}</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk17">&lt;/</span><span class="mtk4">option</span><span class="mtk17">&gt;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> ))</span><span class="mtk4">}</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk17">&lt;/</span><span class="mtk4">select</span><span class="mtk17">&gt;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> ) : (</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk17">&lt;</span><span class="mtk4">input</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">value</span><span class="mtk1">=</span><span class="mtk4">{</span><span class="mtk12">value</span><span class="mtk4">}</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">onChange</span><span class="mtk1">=</span><span class="mtk4">{</span><span class="mtk1">(</span><span class="mtk12">e</span><span class="mtk1">) </span><span class="mtk4">=&gt;</span><span class="mtk1"> </span><span class="mtk11">setValue</span><span class="mtk1">(</span><span class="mtk12">e</span><span class="mtk1">.</span><span class="mtk12">target</span><span class="mtk1">.</span><span class="mtk12">value</span><span class="mtk1">)</span><span class="mtk4">}</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">onBlur</span><span class="mtk1">=</span><span class="mtk4">{</span><span class="mtk12">onBlur</span><span class="mtk4">}</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">type</span><span class="mtk1">=</span><span class="mtk4">{</span><span class="mtk12">columnMeta</span><span class="mtk1">?.</span><span class="mtk12">type</span><span class="mtk1"> || </span><span class="mtk8">&quot;text&quot;</span><span class="mtk4">}</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">required</span><span class="mtk1">=</span><span class="mtk4">{</span><span class="mtk12">columnMeta</span><span class="mtk1">?.</span><span class="mtk12">required</span><span class="mtk4">}</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk17">/&gt;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> );</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> }</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk15">return</span><span class="mtk1"> </span><span class="mtk17">&lt;</span><span class="mtk4">span</span><span class="mtk17">&gt;</span><span class="mtk4">{</span><span class="mtk12">value</span><span class="mtk4">}</span><span class="mtk17">&lt;/</span><span class="mtk4">span</span><span class="mtk17">&gt;</span><span class="mtk1">;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1">};</span></span></span></code></pre> <pre class="grvsc-container default-dark" data-language="css" data-index="6"><code class="grvsc-code"><span class="grvsc-line"><span class="grvsc-source"><span class="mtk6">select:invalid</span><span class="mtk1">, </span><span class="mtk6">input:invalid</span><span class="mtk1"> {</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">border</span><span class="mtk1">: </span><span class="mtk7">2px</span><span class="mtk1"> </span><span class="mtk8">solid</span><span class="mtk1"> </span><span class="mtk8">red</span><span class="mtk1">;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1">}</span></span></span></code></pre> <p>Let’s test it in the demo below. When changing the “major” field to “Select”, we will see that the field will be highlighted with a red border.</p> <div id="ValidateReactTableThree" data-code data-height="350px"></div> <h3 id="pattern-validation" style="position:relative;"><a href="#pattern-validation" aria-label="pattern validation permalink" class="anchor before"><svg aria-hidden="true" focusable="false" height="16" version="1.1" viewBox="0 0 16 16" width="16"><path fill-rule="evenodd" d="M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z"></path></svg></a>Pattern Validation</h3> <p>The <code>pattern</code> validation uses regular expressions to validate the input field. A good example of this is the “name” field. We want to validate that the name only contains letters and spaces.</p> <p>Let’s introduce a new property called <code>pattern</code> in the <code>column.ts</code> file with a regex value.</p> <pre class="grvsc-container grvsc-has-line-highlighting default-dark" data-language="ts" data-index="7"><code class="grvsc-code"><span class="grvsc-line"><span class="grvsc-source"><span class="mtk1">...</span></span></span> <span class="grvsc-line"><span class="grvsc-source"></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk15">export</span><span class="mtk1"> </span><span class="mtk4">const</span><span class="mtk1"> </span><span class="mtk12">columns</span><span class="mtk1"> = [</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> ...</span></span></span> <span class="grvsc-line"><span class="grvsc-source"></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">columnHelper</span><span class="mtk1">.</span><span class="mtk11">accessor</span><span class="mtk1">(</span><span class="mtk8">&#39;name&#39;</span><span class="mtk1">, {</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">header:</span><span class="mtk1"> </span><span class="mtk8">&#39;Full Name&#39;</span><span class="mtk1">,</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">cell:</span><span class="mtk1"> </span><span class="mtk12">TableCell</span><span class="mtk1">,</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">meta:</span><span class="mtk1"> {</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">type:</span><span class="mtk1"> </span><span class="mtk8">&#39;text&#39;</span><span class="mtk1">,</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">required:</span><span class="mtk1"> </span><span class="mtk4">true</span><span class="mtk1">,</span></span></span> <span class="grvsc-line grvsc-line-highlighted"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">pattern:</span><span class="mtk1"> </span><span class="mtk8">&#39;^[a-zA-Z ]+$&#39;</span><span class="mtk1">,</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> },</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> }),</span></span></span> <span class="grvsc-line"><span class="grvsc-source"></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> ...</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1">]</span></span></span></code></pre> <p>Then, in the <code>TableCell</code> component, we will add the <code>pattern</code> property to the input element. The value will come from the <code>columnMeta</code> object.</p> <pre class="grvsc-container grvsc-has-line-highlighting default-dark" data-language="jsx" data-index="8"><code class="grvsc-code"><span class="grvsc-line"><span class="grvsc-source"><span class="mtk1">...</span></span></span> <span class="grvsc-line"><span class="grvsc-source"></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk15">export</span><span class="mtk1"> </span><span class="mtk4">const</span><span class="mtk1"> </span><span class="mtk11">TableCell</span><span class="mtk1"> = ({ </span><span class="mtk12">getValue</span><span class="mtk1">, </span><span class="mtk12">row</span><span class="mtk1">, </span><span class="mtk12">column</span><span class="mtk1">, </span><span class="mtk12">table</span><span class="mtk1"> }) </span><span class="mtk4">=&gt;</span><span class="mtk1"> {</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> ...</span></span></span> <span class="grvsc-line"><span class="grvsc-source"></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk4">const</span><span class="mtk1"> </span><span class="mtk12">columnMeta</span><span class="mtk1"> = </span><span class="mtk12">column</span><span class="mtk1">.</span><span class="mtk12">columnDef</span><span class="mtk1">.</span><span class="mtk12">meta</span><span class="mtk1">;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> ...</span></span></span> <span class="grvsc-line"><span class="grvsc-source"></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk15">if</span><span class="mtk1"> (</span><span class="mtk12">tableMeta</span><span class="mtk1">?.</span><span class="mtk12">editedRows</span><span class="mtk1">[</span><span class="mtk12">row</span><span class="mtk1">.</span><span class="mtk12">id</span><span class="mtk1">]) {</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk15">return</span><span class="mtk1"> </span><span class="mtk12">columnMeta</span><span class="mtk1">?.</span><span class="mtk12">type</span><span class="mtk1"> === </span><span class="mtk8">&quot;select&quot;</span><span class="mtk1"> ? (</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk17">&lt;</span><span class="mtk4">select</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">onChange</span><span class="mtk1">=</span><span class="mtk4">{</span><span class="mtk12">onSelectChange</span><span class="mtk4">}</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">value</span><span class="mtk1">=</span><span class="mtk4">{</span><span class="mtk12">initialValue</span><span class="mtk4">}</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">required</span><span class="mtk1">=</span><span class="mtk4">{</span><span class="mtk12">columnMeta</span><span class="mtk1">?.</span><span class="mtk12">required</span><span class="mtk4">}</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk17">&gt;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk4">{</span><span class="mtk12">columnMeta</span><span class="mtk1">?.</span><span class="mtk12">options</span><span class="mtk1">?.</span><span class="mtk11">map</span><span class="mtk1">((</span><span class="mtk12">option</span><span class="mtk1">: </span><span class="mtk10">Option</span><span class="mtk1">) </span><span class="mtk4">=&gt;</span><span class="mtk1"> (</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk17">&lt;</span><span class="mtk4">option</span><span class="mtk1"> </span><span class="mtk12">key</span><span class="mtk1">=</span><span class="mtk4">{</span><span class="mtk12">option</span><span class="mtk1">.</span><span class="mtk12">value</span><span class="mtk4">}</span><span class="mtk1"> </span><span class="mtk12">value</span><span class="mtk1">=</span><span class="mtk4">{</span><span class="mtk12">option</span><span class="mtk1">.</span><span class="mtk12">value</span><span class="mtk4">}</span><span class="mtk17">&gt;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk4">{</span><span class="mtk12">option</span><span class="mtk1">.</span><span class="mtk12">label</span><span class="mtk4">}</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk17">&lt;/</span><span class="mtk4">option</span><span class="mtk17">&gt;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> ))</span><span class="mtk4">}</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk17">&lt;/</span><span class="mtk4">select</span><span class="mtk17">&gt;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> ) : (</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk17">&lt;</span><span class="mtk4">input</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">value</span><span class="mtk1">=</span><span class="mtk4">{</span><span class="mtk12">value</span><span class="mtk4">}</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">onChange</span><span class="mtk1">=</span><span class="mtk4">{</span><span class="mtk1">(</span><span class="mtk12">e</span><span class="mtk1">) </span><span class="mtk4">=&gt;</span><span class="mtk1"> </span><span class="mtk11">setValue</span><span class="mtk1">(</span><span class="mtk12">e</span><span class="mtk1">.</span><span class="mtk12">target</span><span class="mtk1">.</span><span class="mtk12">value</span><span class="mtk1">)</span><span class="mtk4">}</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">onBlur</span><span class="mtk1">=</span><span class="mtk4">{</span><span class="mtk12">onBlur</span><span class="mtk4">}</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">type</span><span class="mtk1">=</span><span class="mtk4">{</span><span class="mtk12">columnMeta</span><span class="mtk1">?.</span><span class="mtk12">type</span><span class="mtk1"> || </span><span class="mtk8">&quot;text&quot;</span><span class="mtk4">}</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">required</span><span class="mtk1">=</span><span class="mtk4">{</span><span class="mtk12">columnMeta</span><span class="mtk1">?.</span><span class="mtk12">required</span><span class="mtk4">}</span></span></span> <span class="grvsc-line grvsc-line-highlighted"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">pattern</span><span class="mtk1">=</span><span class="mtk4">{</span><span class="mtk12">columnMeta</span><span class="mtk1">?.</span><span class="mtk12">pattern</span><span class="mtk4">}</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk17">/&gt;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> );</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> }</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk15">return</span><span class="mtk1"> </span><span class="mtk17">&lt;</span><span class="mtk4">span</span><span class="mtk17">&gt;</span><span class="mtk4">{</span><span class="mtk12">value</span><span class="mtk4">}</span><span class="mtk17">&lt;/</span><span class="mtk4">span</span><span class="mtk17">&gt;</span><span class="mtk1">;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1">};</span></span></span> <span class="grvsc-line"><span class="grvsc-source"></span></span></code></pre> <p>Now, in the demo below, we will see that the “name” field will be validated using the regex pattern and only accept letters and spaces.</p> <div id="ValidateReactTableFour" data-code data-height="350px"></div> <h2 id="display-validation-message" style="position:relative;"><a href="#display-validation-message" aria-label="display validation message permalink" class="anchor before"><svg aria-hidden="true" focusable="false" height="16" version="1.1" viewBox="0 0 16 16" width="16"><path fill-rule="evenodd" d="M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z"></path></svg></a>Display Validation Message</h2> <p>Previously, we added a red border to the input element when the validation was triggered, but we did not display any validation message.</p> <p>To display the validation message, we can use the <code>title</code> attribute of the input element to show the validation message when the user hovers over the input element.</p> <p>Then, we will need to add a new state to the <code>TableCell</code> component to store the validation message and a new function to set the value. Both <code>onBlur</code> and <code>onChange</code> events will trigger the function.</p> <p>Below is the full code of the <code>TableCell</code> component.</p> <pre class="grvsc-container grvsc-has-line-highlighting default-dark" data-language="jsx" data-index="9"><code class="grvsc-code"><span class="grvsc-line"><span class="grvsc-source"><span class="mtk1">...</span></span></span> <span class="grvsc-line"><span class="grvsc-source"></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk15">export</span><span class="mtk1"> </span><span class="mtk4">const</span><span class="mtk1"> </span><span class="mtk11">TableCell</span><span class="mtk1"> = ({ </span><span class="mtk12">getValue</span><span class="mtk1">, </span><span class="mtk12">row</span><span class="mtk1">, </span><span class="mtk12">column</span><span class="mtk1">, </span><span class="mtk12">table</span><span class="mtk1"> }) </span><span class="mtk4">=&gt;</span><span class="mtk1"> {</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk15">import</span><span class="mtk1"> { </span><span class="mtk12">useState</span><span class="mtk1">, </span><span class="mtk12">useEffect</span><span class="mtk1">, </span><span class="mtk12">ChangeEvent</span><span class="mtk1"> } </span><span class="mtk15">from</span><span class="mtk1"> </span><span class="mtk8">&quot;react&quot;</span><span class="mtk1">;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk15">import</span><span class="mtk1"> </span><span class="mtk8">&quot;./table.css&quot;</span><span class="mtk1">;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk4">type</span><span class="mtk1"> </span><span class="mtk10">Option</span><span class="mtk1"> = {</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">label</span><span class="mtk1">: </span><span class="mtk10">string</span><span class="mtk1">;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">value</span><span class="mtk1">: </span><span class="mtk10">string</span><span class="mtk1">;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1">};</span></span></span> <span class="grvsc-line"><span class="grvsc-source"></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk15">export</span><span class="mtk1"> </span><span class="mtk4">const</span><span class="mtk1"> </span><span class="mtk11">TableCell</span><span class="mtk1"> = ({ </span><span class="mtk12">getValue</span><span class="mtk1">, </span><span class="mtk12">row</span><span class="mtk1">, </span><span class="mtk12">column</span><span class="mtk1">, </span><span class="mtk12">table</span><span class="mtk1"> }) </span><span class="mtk4">=&gt;</span><span class="mtk1"> {</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk4">const</span><span class="mtk1"> </span><span class="mtk12">initialValue</span><span class="mtk1"> = </span><span class="mtk11">getValue</span><span class="mtk1">();</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk4">const</span><span class="mtk1"> </span><span class="mtk12">columnMeta</span><span class="mtk1"> = </span><span class="mtk12">column</span><span class="mtk1">.</span><span class="mtk12">columnDef</span><span class="mtk1">.</span><span class="mtk12">meta</span><span class="mtk1">;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk4">const</span><span class="mtk1"> </span><span class="mtk12">tableMeta</span><span class="mtk1"> = </span><span class="mtk12">table</span><span class="mtk1">.</span><span class="mtk12">options</span><span class="mtk1">.</span><span class="mtk12">meta</span><span class="mtk1">;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk4">const</span><span class="mtk1"> [</span><span class="mtk12">value</span><span class="mtk1">, </span><span class="mtk12">setValue</span><span class="mtk1">] = </span><span class="mtk11">useState</span><span class="mtk1">(</span><span class="mtk12">initialValue</span><span class="mtk1">);</span></span></span> <span class="grvsc-line grvsc-line-highlighted"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk4">const</span><span class="mtk1"> [</span><span class="mtk12">validationMessage</span><span class="mtk1">, </span><span class="mtk12">setValidationMessage</span><span class="mtk1">] = </span><span class="mtk11">useState</span><span class="mtk1">(</span><span class="mtk8">&quot;&quot;</span><span class="mtk1">);</span></span></span> <span class="grvsc-line"><span class="grvsc-source"></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk11">useEffect</span><span class="mtk1">(() </span><span class="mtk4">=&gt;</span><span class="mtk1"> {</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk11">setValue</span><span class="mtk1">(</span><span class="mtk12">initialValue</span><span class="mtk1">);</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> }, [</span><span class="mtk12">initialValue</span><span class="mtk1">]);</span></span></span> <span class="grvsc-line"><span class="grvsc-source"></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk4">const</span><span class="mtk1"> </span><span class="mtk11">onBlur</span><span class="mtk1"> = (</span><span class="mtk12">e</span><span class="mtk1">: </span><span class="mtk10">ChangeEvent</span><span class="mtk1">&lt;</span><span class="mtk10">HTMLInputElement</span><span class="mtk1">&gt;) </span><span class="mtk4">=&gt;</span><span class="mtk1"> {</span></span></span> <span class="grvsc-line grvsc-line-highlighted"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk11">displayValidationMessage</span><span class="mtk1">(</span><span class="mtk12">e</span><span class="mtk1">);</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">tableMeta</span><span class="mtk1">?.</span><span class="mtk11">updateData</span><span class="mtk1">(</span><span class="mtk12">row</span><span class="mtk1">.</span><span class="mtk12">index</span><span class="mtk1">, </span><span class="mtk12">column</span><span class="mtk1">.</span><span class="mtk12">id</span><span class="mtk1">, </span><span class="mtk12">value</span><span class="mtk1">);</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> };</span></span></span> <span class="grvsc-line"><span class="grvsc-source"></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk4">const</span><span class="mtk1"> </span><span class="mtk11">onSelectChange</span><span class="mtk1"> = (</span><span class="mtk12">e</span><span class="mtk1">: </span><span class="mtk10">ChangeEvent</span><span class="mtk1">&lt;</span><span class="mtk10">HTMLSelectElement</span><span class="mtk1">&gt;) </span><span class="mtk4">=&gt;</span><span class="mtk1"> {</span></span></span> <span class="grvsc-line grvsc-line-highlighted"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk11">displayValidationMessage</span><span class="mtk1">(</span><span class="mtk12">e</span><span class="mtk1">);</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk11">setValue</span><span class="mtk1">(</span><span class="mtk12">e</span><span class="mtk1">.</span><span class="mtk12">target</span><span class="mtk1">.</span><span class="mtk12">value</span><span class="mtk1">);</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">tableMeta</span><span class="mtk1">?.</span><span class="mtk11">updateData</span><span class="mtk1">(</span><span class="mtk12">row</span><span class="mtk1">.</span><span class="mtk12">index</span><span class="mtk1">, </span><span class="mtk12">column</span><span class="mtk1">.</span><span class="mtk12">id</span><span class="mtk1">, </span><span class="mtk12">e</span><span class="mtk1">.</span><span class="mtk12">target</span><span class="mtk1">.</span><span class="mtk12">value</span><span class="mtk1">);</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> };</span></span></span> <span class="grvsc-line"><span class="grvsc-source"></span></span> <span class="grvsc-line grvsc-line-highlighted"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk4">const</span><span class="mtk1"> </span><span class="mtk11">displayValidationMessage</span><span class="mtk1"> = &lt;</span></span></span> <span class="grvsc-line grvsc-line-highlighted"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk10">T</span><span class="mtk1"> </span><span class="mtk4">extends</span><span class="mtk1"> </span><span class="mtk10">HTMLInputElement</span><span class="mtk1"> | </span><span class="mtk10">HTMLSelectElement</span></span></span> <span class="grvsc-line grvsc-line-highlighted"><span class="grvsc-source"><span class="mtk1"> &gt;(</span></span></span> <span class="grvsc-line grvsc-line-highlighted"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">e</span><span class="mtk1">: </span><span class="mtk10">ChangeEvent</span><span class="mtk1">&lt;</span><span class="mtk10">T</span><span class="mtk1">&gt;</span></span></span> <span class="grvsc-line grvsc-line-highlighted"><span class="grvsc-source"><span class="mtk1"> ) </span><span class="mtk4">=&gt;</span><span class="mtk1"> {</span></span></span> <span class="grvsc-line grvsc-line-highlighted"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk15">if</span><span class="mtk1"> (</span><span class="mtk12">e</span><span class="mtk1">.</span><span class="mtk12">target</span><span class="mtk1">.</span><span class="mtk12">validity</span><span class="mtk1">.</span><span class="mtk12">valid</span><span class="mtk1">) {</span></span></span> <span class="grvsc-line grvsc-line-highlighted"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk11">setValidationMessage</span><span class="mtk1">(</span><span class="mtk8">&quot;&quot;</span><span class="mtk1">);</span></span></span> <span class="grvsc-line grvsc-line-highlighted"><span class="grvsc-source"><span class="mtk1"> } </span><span class="mtk15">else</span><span class="mtk1"> {</span></span></span> <span class="grvsc-line grvsc-line-highlighted"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk11">setValidationMessage</span><span class="mtk1">(</span><span class="mtk12">e</span><span class="mtk1">.</span><span class="mtk12">target</span><span class="mtk1">.</span><span class="mtk12">validationMessage</span><span class="mtk1">);</span></span></span> <span class="grvsc-line grvsc-line-highlighted"><span class="grvsc-source"><span class="mtk1"> }</span></span></span> <span class="grvsc-line grvsc-line-highlighted"><span class="grvsc-source"><span class="mtk1"> };</span></span></span> <span class="grvsc-line"><span class="grvsc-source"></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk15">if</span><span class="mtk1"> (</span><span class="mtk12">tableMeta</span><span class="mtk1">?.</span><span class="mtk12">editedRows</span><span class="mtk1">[</span><span class="mtk12">row</span><span class="mtk1">.</span><span class="mtk12">id</span><span class="mtk1">]) {</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk15">return</span><span class="mtk1"> </span><span class="mtk12">columnMeta</span><span class="mtk1">?.</span><span class="mtk12">type</span><span class="mtk1"> === </span><span class="mtk8">&quot;select&quot;</span><span class="mtk1"> ? (</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk17">&lt;</span><span class="mtk4">select</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">onChange</span><span class="mtk1">=</span><span class="mtk4">{</span><span class="mtk12">onSelectChange</span><span class="mtk4">}</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">value</span><span class="mtk1">=</span><span class="mtk4">{</span><span class="mtk12">initialValue</span><span class="mtk4">}</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">required</span><span class="mtk1">=</span><span class="mtk4">{</span><span class="mtk12">columnMeta</span><span class="mtk1">?.</span><span class="mtk12">required</span><span class="mtk4">}</span></span></span> <span class="grvsc-line grvsc-line-highlighted"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">title</span><span class="mtk1">=</span><span class="mtk4">{</span><span class="mtk12">validationMessage</span><span class="mtk4">}</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk17">&gt;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk4">{</span><span class="mtk12">columnMeta</span><span class="mtk1">?.</span><span class="mtk12">options</span><span class="mtk1">?.</span><span class="mtk11">map</span><span class="mtk1">((</span><span class="mtk12">option</span><span class="mtk1">: </span><span class="mtk10">Option</span><span class="mtk1">) </span><span class="mtk4">=&gt;</span><span class="mtk1"> (</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk17">&lt;</span><span class="mtk4">option</span><span class="mtk1"> </span><span class="mtk12">key</span><span class="mtk1">=</span><span class="mtk4">{</span><span class="mtk12">option</span><span class="mtk1">.</span><span class="mtk12">value</span><span class="mtk4">}</span><span class="mtk1"> </span><span class="mtk12">value</span><span class="mtk1">=</span><span class="mtk4">{</span><span class="mtk12">option</span><span class="mtk1">.</span><span class="mtk12">value</span><span class="mtk4">}</span><span class="mtk17">&gt;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk4">{</span><span class="mtk12">option</span><span class="mtk1">.</span><span class="mtk12">label</span><span class="mtk4">}</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk17">&lt;/</span><span class="mtk4">option</span><span class="mtk17">&gt;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> ))</span><span class="mtk4">}</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk17">&lt;/</span><span class="mtk4">select</span><span class="mtk17">&gt;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> ) : (</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk17">&lt;</span><span class="mtk4">input</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">value</span><span class="mtk1">=</span><span class="mtk4">{</span><span class="mtk12">value</span><span class="mtk4">}</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">onChange</span><span class="mtk1">=</span><span class="mtk4">{</span><span class="mtk1">(</span><span class="mtk12">e</span><span class="mtk1">) </span><span class="mtk4">=&gt;</span><span class="mtk1"> </span><span class="mtk11">setValue</span><span class="mtk1">(</span><span class="mtk12">e</span><span class="mtk1">.</span><span class="mtk12">target</span><span class="mtk1">.</span><span class="mtk12">value</span><span class="mtk1">)</span><span class="mtk4">}</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">onBlur</span><span class="mtk1">=</span><span class="mtk4">{</span><span class="mtk12">onBlur</span><span class="mtk4">}</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">type</span><span class="mtk1">=</span><span class="mtk4">{</span><span class="mtk12">columnMeta</span><span class="mtk1">?.</span><span class="mtk12">type</span><span class="mtk1"> || </span><span class="mtk8">&quot;text&quot;</span><span class="mtk4">}</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">required</span><span class="mtk1">=</span><span class="mtk4">{</span><span class="mtk12">columnMeta</span><span class="mtk1">?.</span><span class="mtk12">required</span><span class="mtk4">}</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">pattern</span><span class="mtk1">=</span><span class="mtk4">{</span><span class="mtk12">columnMeta</span><span class="mtk1">?.</span><span class="mtk12">pattern</span><span class="mtk4">}</span></span></span> <span class="grvsc-line grvsc-line-highlighted"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">title</span><span class="mtk1">=</span><span class="mtk4">{</span><span class="mtk12">validationMessage</span><span class="mtk4">}</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk17">/&gt;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> );</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> }</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk15">return</span><span class="mtk1"> </span><span class="mtk17">&lt;</span><span class="mtk4">span</span><span class="mtk17">&gt;</span><span class="mtk4">{</span><span class="mtk12">value</span><span class="mtk4">}</span><span class="mtk17">&lt;/</span><span class="mtk4">span</span><span class="mtk17">&gt;</span><span class="mtk1">;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1">};</span></span></span> <span class="grvsc-line"><span class="grvsc-source"></span></span></code></pre> <p>Now, in the demo below, if we enter an invalid value in the “name” field and hover over it, we will see the validation message.</p> <div id="ValidateReactTableFive" data-code data-height="350px"></div> <p>Note that using <code>title</code> attribute might not be the best way to display the validation message because of the limited styling options. We can always create a customomized tooltip or use a third-party library such as <a href="https://www.npmjs.com/package/react-tooltip">react-tooltip</a>, but this is out of the scope of this tutorial.</p> <h2 id="custom-validation" style="position:relative;"><a href="#custom-validation" aria-label="custom validation permalink" class="anchor before"><svg aria-hidden="true" focusable="false" height="16" version="1.1" viewBox="0 0 16 16" width="16"><path fill-rule="evenodd" d="M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z"></path></svg></a>Custom Validation</h2> <p>The custom validation is useful when we want to validate the field using a more complex logic and using regex might add more complexity to the code. Let’s take the date as an example. We want to validate that the date is not in the future.</p> <p>To do this, we will add a new property called <code>validate</code> in the <code>column.ts</code> file with a callback function that has the validation logic. The function will return a boolean value. Also, we will add a new property called <code>validationMessage</code> to display the custom validation message.</p> <pre class="grvsc-container grvsc-has-line-highlighting default-dark" data-language="ts" data-index="10"><code class="grvsc-code"><span class="grvsc-line"><span class="grvsc-source"><span class="mtk1">...</span></span></span> <span class="grvsc-line"><span class="grvsc-source"></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk15">export</span><span class="mtk1"> </span><span class="mtk4">const</span><span class="mtk1"> </span><span class="mtk12">columns</span><span class="mtk1"> = [</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> ...</span></span></span> <span class="grvsc-line"><span class="grvsc-source"></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">columnHelper</span><span class="mtk1">.</span><span class="mtk11">accessor</span><span class="mtk1">(</span><span class="mtk8">&#39;date&#39;</span><span class="mtk1">, {</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">header:</span><span class="mtk1"> </span><span class="mtk8">&#39;Date&#39;</span><span class="mtk1">,</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">cell:</span><span class="mtk1"> </span><span class="mtk12">TableCell</span><span class="mtk1">,</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">meta:</span><span class="mtk1"> {</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">type:</span><span class="mtk1"> </span><span class="mtk8">&#39;date&#39;</span><span class="mtk1">,</span></span></span> <span class="grvsc-line grvsc-line-highlighted"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">required:</span><span class="mtk1"> </span><span class="mtk4">true</span><span class="mtk1">,</span></span></span> <span class="grvsc-line grvsc-line-highlighted"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk11">validate</span><span class="mtk12">:</span><span class="mtk1"> (</span><span class="mtk12">value</span><span class="mtk1">: </span><span class="mtk10">string</span><span class="mtk1">) </span><span class="mtk4">=&gt;</span><span class="mtk1"> {</span></span></span> <span class="grvsc-line grvsc-line-highlighted"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk4">const</span><span class="mtk1"> </span><span class="mtk12">date</span><span class="mtk1"> = </span><span class="mtk4">new</span><span class="mtk1"> </span><span class="mtk10">Date</span><span class="mtk1">(</span><span class="mtk12">value</span><span class="mtk1">);</span></span></span> <span class="grvsc-line grvsc-line-highlighted"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk4">const</span><span class="mtk1"> </span><span class="mtk12">today</span><span class="mtk1"> = </span><span class="mtk4">new</span><span class="mtk1"> </span><span class="mtk10">Date</span><span class="mtk1">();</span></span></span> <span class="grvsc-line grvsc-line-highlighted"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk15">return</span><span class="mtk1"> </span><span class="mtk12">date</span><span class="mtk1"> &lt;= </span><span class="mtk12">today</span><span class="mtk1">;</span></span></span> <span class="grvsc-line grvsc-line-highlighted"><span class="grvsc-source"><span class="mtk1"> },</span></span></span> <span class="grvsc-line grvsc-line-highlighted"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">validationMessage:</span><span class="mtk1"> </span><span class="mtk8">&#39;Date cannot be in the future&#39;</span><span class="mtk1">,</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> },</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> }),</span></span></span> <span class="grvsc-line"><span class="grvsc-source"></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> ...</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1">]</span></span></span></code></pre> <p>Then, in the <code>displayValidationMessage</code> function, we will check if the <code>validate</code> property is present in the <code>columnMeta</code> object. If it is, we will call the <code>validate</code> function and set the new <code>validationMessage</code> state.</p> <pre class="grvsc-container grvsc-has-line-highlighting default-dark" data-language="jsx" data-index="11"><code class="grvsc-code"><span class="grvsc-line"><span class="grvsc-source"><span class="mtk15">import</span><span class="mtk1"> { </span><span class="mtk12">useState</span><span class="mtk1">, </span><span class="mtk12">useEffect</span><span class="mtk1">, </span><span class="mtk12">ChangeEvent</span><span class="mtk1"> } </span><span class="mtk15">from</span><span class="mtk1"> </span><span class="mtk8">&quot;react&quot;</span><span class="mtk1">;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk15">import</span><span class="mtk1"> </span><span class="mtk8">&quot;./table.css&quot;</span><span class="mtk1">;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk4">type</span><span class="mtk1"> </span><span class="mtk10">Option</span><span class="mtk1"> = {</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">label</span><span class="mtk1">: </span><span class="mtk10">string</span><span class="mtk1">;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">value</span><span class="mtk1">: </span><span class="mtk10">string</span><span class="mtk1">;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1">};</span></span></span> <span class="grvsc-line"><span class="grvsc-source"></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk15">export</span><span class="mtk1"> </span><span class="mtk4">const</span><span class="mtk1"> </span><span class="mtk11">TableCell</span><span class="mtk1"> = ({ </span><span class="mtk12">getValue</span><span class="mtk1">, </span><span class="mtk12">row</span><span class="mtk1">, </span><span class="mtk12">column</span><span class="mtk1">, </span><span class="mtk12">table</span><span class="mtk1"> }) </span><span class="mtk4">=&gt;</span><span class="mtk1"> {</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> ...</span></span></span> <span class="grvsc-line"><span class="grvsc-source"></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk4">const</span><span class="mtk1"> </span><span class="mtk11">displayValidationMessage</span><span class="mtk1"> = &lt;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk10">T</span><span class="mtk1"> </span><span class="mtk4">extends</span><span class="mtk1"> </span><span class="mtk10">HTMLInputElement</span><span class="mtk1"> | </span><span class="mtk10">HTMLSelectElement</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> &gt;(</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">e</span><span class="mtk1">: </span><span class="mtk10">ChangeEvent</span><span class="mtk1">&lt;</span><span class="mtk10">T</span><span class="mtk1">&gt;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> ) </span><span class="mtk4">=&gt;</span><span class="mtk1"> {</span></span></span> <span class="grvsc-line grvsc-line-highlighted"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk15">if</span><span class="mtk1"> (</span><span class="mtk12">columnMeta</span><span class="mtk1">?.</span><span class="mtk12">validate</span><span class="mtk1">) {</span></span></span> <span class="grvsc-line grvsc-line-highlighted"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk4">const</span><span class="mtk1"> </span><span class="mtk12">isValid</span><span class="mtk1"> = </span><span class="mtk12">columnMeta</span><span class="mtk1">.</span><span class="mtk11">validate</span><span class="mtk1">(</span><span class="mtk12">e</span><span class="mtk1">.</span><span class="mtk12">target</span><span class="mtk1">.</span><span class="mtk12">value</span><span class="mtk1">);</span></span></span> <span class="grvsc-line grvsc-line-highlighted"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk15">if</span><span class="mtk1"> (</span><span class="mtk12">isValid</span><span class="mtk1">) {</span></span></span> <span class="grvsc-line grvsc-line-highlighted"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">e</span><span class="mtk1">.</span><span class="mtk12">target</span><span class="mtk1">.</span><span class="mtk11">setCustomValidity</span><span class="mtk1">(</span><span class="mtk8">&quot;&quot;</span><span class="mtk1">);</span></span></span> <span class="grvsc-line grvsc-line-highlighted"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk11">setValidationMessage</span><span class="mtk1">(</span><span class="mtk8">&quot;&quot;</span><span class="mtk1">);</span></span></span> <span class="grvsc-line grvsc-line-highlighted"><span class="grvsc-source"><span class="mtk1"> } </span><span class="mtk15">else</span><span class="mtk1"> {</span></span></span> <span class="grvsc-line grvsc-line-highlighted"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">e</span><span class="mtk1">.</span><span class="mtk12">target</span><span class="mtk1">.</span><span class="mtk11">setCustomValidity</span><span class="mtk1">(</span><span class="mtk12">columnMeta</span><span class="mtk1">.</span><span class="mtk12">validationMessage</span><span class="mtk1">);</span></span></span> <span class="grvsc-line grvsc-line-highlighted"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk11">setValidationMessage</span><span class="mtk1">(</span><span class="mtk12">columnMeta</span><span class="mtk1">.</span><span class="mtk12">validationMessage</span><span class="mtk1">);</span></span></span> <span class="grvsc-line grvsc-line-highlighted"><span class="grvsc-source"><span class="mtk1"> }</span></span></span> <span class="grvsc-line grvsc-line-highlighted"><span class="grvsc-source"><span class="mtk1"> } </span><span class="mtk15">else</span><span class="mtk1"> </span><span class="mtk15">if</span><span class="mtk1"> (</span><span class="mtk12">e</span><span class="mtk1">.</span><span class="mtk12">target</span><span class="mtk1">.</span><span class="mtk12">validity</span><span class="mtk1">.</span><span class="mtk12">valid</span><span class="mtk1">) {</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk11">setValidationMessage</span><span class="mtk1">(</span><span class="mtk8">&quot;&quot;</span><span class="mtk1">);</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> } </span><span class="mtk15">else</span><span class="mtk1"> {</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk11">setValidationMessage</span><span class="mtk1">(</span><span class="mtk12">e</span><span class="mtk1">.</span><span class="mtk12">target</span><span class="mtk1">.</span><span class="mtk12">validationMessage</span><span class="mtk1">);</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> }</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> };</span></span></span> <span class="grvsc-line"><span class="grvsc-source"></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> ...</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> }</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk15">return</span><span class="mtk1"> </span><span class="mtk17">&lt;</span><span class="mtk4">span</span><span class="mtk17">&gt;</span><span class="mtk4">{</span><span class="mtk12">value</span><span class="mtk4">}</span><span class="mtk17">&lt;/</span><span class="mtk4">span</span><span class="mtk17">&gt;</span><span class="mtk1">;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1">};</span></span></span> <span class="grvsc-line"><span class="grvsc-source"></span></span></code></pre> <p>Notice that we used the <code>setCustomValidity</code> function. Since we are using the native HTML5 validation, we need to use the <code>setCustomValidity</code> function to trigger the <code>:invalid</code> pseudo-class for the styling.</p> <p>In the demo below, we will see that the “date” field will be validated using the custom validation if the date is in the future.</p> <div id="ValidateReactTableSix" data-code data-height="350px"></div> <h2 id="row-validation" style="position:relative;"><a href="#row-validation" aria-label="row validation permalink" class="anchor before"><svg aria-hidden="true" focusable="false" height="16" version="1.1" viewBox="0 0 16 16" width="16"><path fill-rule="evenodd" d="M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z"></path></svg></a>Row Validation</h2> <p>The row validation is useful when we want to validate the row as a whole. For example, we want to disable the save button if there is an invalid field in the row to avoid saving invalid data.</p> <p>Since the save button is in a different component, we will need to add a new <code>validRows</code> state in the <code>Table</code> component to store the valid rows and pass it to the table meta. In addition, we will update the <code>validRows</code> state in the <code>updateData</code> function, which will have a new <code>isValid</code> parameter.</p> <pre class="grvsc-container grvsc-has-line-highlighting default-dark" data-language="jsx" data-index="12"><code class="grvsc-code"><span class="grvsc-line"><span class="grvsc-source"><span class="mtk15">import</span><span class="mtk1"> { </span><span class="mtk12">useState</span><span class="mtk1"> } </span><span class="mtk15">from</span><span class="mtk1"> </span><span class="mtk8">&quot;react&quot;</span><span class="mtk1">;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk15">import</span><span class="mtk1"> { </span><span class="mtk12">Student</span><span class="mtk1">, </span><span class="mtk12">data</span><span class="mtk1"> </span><span class="mtk15">as</span><span class="mtk1"> </span><span class="mtk12">defaultData</span><span class="mtk1"> } </span><span class="mtk15">from</span><span class="mtk1"> </span><span class="mtk8">&quot;./data&quot;</span><span class="mtk1">;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk15">import</span><span class="mtk1"> </span><span class="mtk8">&quot;./table.css&quot;</span><span class="mtk1">;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk15">import</span><span class="mtk1"> {</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">flexRender</span><span class="mtk1">,</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">getCoreRowModel</span><span class="mtk1">,</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">useReactTable</span><span class="mtk1">,</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1">} </span><span class="mtk15">from</span><span class="mtk1"> </span><span class="mtk8">&quot;@tanstack/react-table&quot;</span><span class="mtk1">;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk15">import</span><span class="mtk1"> { </span><span class="mtk12">columns</span><span class="mtk1"> } </span><span class="mtk15">from</span><span class="mtk1"> </span><span class="mtk8">&quot;./columns&quot;</span><span class="mtk1">;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk15">import</span><span class="mtk1"> { </span><span class="mtk12">FooterCell</span><span class="mtk1"> } </span><span class="mtk15">from</span><span class="mtk1"> </span><span class="mtk8">&quot;./FooterCell&quot;</span><span class="mtk1">;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk15">export</span><span class="mtk1"> </span><span class="mtk4">const</span><span class="mtk1"> </span><span class="mtk11">Table</span><span class="mtk1"> = () </span><span class="mtk4">=&gt;</span><span class="mtk1"> {</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> ...</span></span></span> <span class="grvsc-line"><span class="grvsc-source"></span></span> <span class="grvsc-line grvsc-line-highlighted"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk4">const</span><span class="mtk1"> [</span><span class="mtk12">validRows</span><span class="mtk1">, </span><span class="mtk12">setValidRows</span><span class="mtk1">] = </span><span class="mtk11">useState</span><span class="mtk1">({});</span></span></span> <span class="grvsc-line"><span class="grvsc-source"></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk4">const</span><span class="mtk1"> </span><span class="mtk12">table</span><span class="mtk1"> = </span><span class="mtk11">useReactTable</span><span class="mtk1">({</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">data</span><span class="mtk1">,</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">columns</span><span class="mtk1">,</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">getCoreRowModel:</span><span class="mtk1"> </span><span class="mtk11">getCoreRowModel</span><span class="mtk1">(),</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">enableRowSelection:</span><span class="mtk1"> </span><span class="mtk4">true</span><span class="mtk1">,</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">meta:</span><span class="mtk1"> {</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> ...</span></span></span> <span class="grvsc-line grvsc-line-highlighted"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">validRows</span><span class="mtk1">,</span></span></span> <span class="grvsc-line grvsc-line-highlighted"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">setValidRows</span><span class="mtk1">,</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> ...</span></span></span> <span class="grvsc-line grvsc-line-highlighted"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">updateData</span><span class="mtk1">: (</span><span class="mtk12">rowIndex</span><span class="mtk1">: </span><span class="mtk10">number</span><span class="mtk1">, </span><span class="mtk12">columnId</span><span class="mtk1">: </span><span class="mtk10">string</span><span class="mtk1">, </span><span class="mtk12">value</span><span class="mtk1">: </span><span class="mtk10">string</span><span class="mtk1">, </span><span class="mtk12">isValid</span><span class="mtk1">: </span><span class="mtk10">boolean</span><span class="mtk1">) </span><span class="mtk4">=&gt;</span><span class="mtk1"> {</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk11">setData</span><span class="mtk1">((</span><span class="mtk12">old</span><span class="mtk1">) </span><span class="mtk4">=&gt;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">old</span><span class="mtk1">.</span><span class="mtk11">map</span><span class="mtk1">((</span><span class="mtk12">row</span><span class="mtk1">, </span><span class="mtk12">index</span><span class="mtk1">) </span><span class="mtk4">=&gt;</span><span class="mtk1"> {</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk15">if</span><span class="mtk1"> (</span><span class="mtk12">index</span><span class="mtk1"> === </span><span class="mtk12">rowIndex</span><span class="mtk1">) {</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk15">return</span><span class="mtk1"> {</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> ...</span><span class="mtk12">old</span><span class="mtk1">[</span><span class="mtk12">rowIndex</span><span class="mtk1">],</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">[columnId]:</span><span class="mtk1"> </span><span class="mtk12">value</span><span class="mtk1">,</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> };</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> }</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk15">return</span><span class="mtk1"> </span><span class="mtk12">row</span><span class="mtk1">;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> })</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> );</span></span></span> <span class="grvsc-line grvsc-line-highlighted"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk11">setValidRows</span><span class="mtk1">((</span><span class="mtk12">old</span><span class="mtk1">) </span><span class="mtk4">=&gt;</span><span class="mtk1"> ({</span></span></span> <span class="grvsc-line grvsc-line-highlighted"><span class="grvsc-source"><span class="mtk1"> ...</span><span class="mtk12">old</span><span class="mtk1">,</span></span></span> <span class="grvsc-line grvsc-line-highlighted"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">[rowIndex]:</span><span class="mtk1"> { ...</span><span class="mtk12">old</span><span class="mtk1">[</span><span class="mtk12">rowIndex</span><span class="mtk1">], </span><span class="mtk12">[columnId]:</span><span class="mtk1"> </span><span class="mtk12">isValid</span><span class="mtk1"> },</span></span></span> <span class="grvsc-line grvsc-line-highlighted"><span class="grvsc-source"><span class="mtk1"> }));</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> },</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> ...</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> },</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> });</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> ...</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1">};</span></span></span></code></pre> <p>A quick clarification to what the <code>setValidRows</code> is doing, it is updating the <code>validRows</code> state by adding a new key-value pair to the object. The key is the row index, and the value is an object with the column id as the key and the validation status as the value.</p> <p>Below is a JSON representation of the <code>validRows</code> state.</p> <pre class="grvsc-container default-dark" data-language="json" data-index="13"><code class="grvsc-code"><span class="grvsc-line"><span class="grvsc-source"><span class="mtk1">{</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">&quot;0&quot;</span><span class="mtk1">: {</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">&quot;name&quot;</span><span class="mtk1">: </span><span class="mtk4">true</span><span class="mtk1">,</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">&quot;major&quot;</span><span class="mtk1">: </span><span class="mtk4">true</span><span class="mtk1">,</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">&quot;date&quot;</span><span class="mtk1">: </span><span class="mtk4">false</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> },</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">&quot;1&quot;</span><span class="mtk1">: {</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">&quot;name&quot;</span><span class="mtk1">: </span><span class="mtk4">true</span><span class="mtk1">,</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">&quot;major&quot;</span><span class="mtk1">: </span><span class="mtk4">false</span><span class="mtk1">,</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">&quot;date&quot;</span><span class="mtk1">: </span><span class="mtk4">true</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> },</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk14">...</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1">}</span></span></span></code></pre> <p>Now that the <code>updateData</code> has a new <code>isValid</code> parameter, we will need to update the <code>TableCell</code> component to pass the <code>isValid</code> parameter to the <code>updateData</code> function.</p> <pre class="grvsc-container grvsc-has-line-highlighting default-dark" data-language="jsx" data-index="14"><code class="grvsc-code"><span class="grvsc-line"><span class="grvsc-source"><span class="mtk1">...</span></span></span> <span class="grvsc-line"><span class="grvsc-source"></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk15">export</span><span class="mtk1"> </span><span class="mtk4">const</span><span class="mtk1"> </span><span class="mtk11">TableCell</span><span class="mtk1"> = ({ </span><span class="mtk12">getValue</span><span class="mtk1">, </span><span class="mtk12">row</span><span class="mtk1">, </span><span class="mtk12">column</span><span class="mtk1">, </span><span class="mtk12">table</span><span class="mtk1"> }) </span><span class="mtk4">=&gt;</span><span class="mtk1"> {</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> ...</span></span></span> <span class="grvsc-line"><span class="grvsc-source"></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk4">const</span><span class="mtk1"> </span><span class="mtk11">onBlur</span><span class="mtk1"> = (</span><span class="mtk12">e</span><span class="mtk1">: </span><span class="mtk10">ChangeEvent</span><span class="mtk1">&lt;</span><span class="mtk10">HTMLInputElement</span><span class="mtk1">&gt;) </span><span class="mtk4">=&gt;</span><span class="mtk1"> {</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk11">displayValidationMessage</span><span class="mtk1">(</span><span class="mtk12">e</span><span class="mtk1">);</span></span></span> <span class="grvsc-line grvsc-line-highlighted"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">tableMeta</span><span class="mtk1">?.</span><span class="mtk11">updateData</span><span class="mtk1">(</span><span class="mtk12">row</span><span class="mtk1">.</span><span class="mtk12">index</span><span class="mtk1">, </span><span class="mtk12">column</span><span class="mtk1">.</span><span class="mtk12">id</span><span class="mtk1">, </span><span class="mtk12">value</span><span class="mtk1">, </span><span class="mtk12">e</span><span class="mtk1">.</span><span class="mtk12">target</span><span class="mtk1">.</span><span class="mtk12">validity</span><span class="mtk1">.</span><span class="mtk12">valid</span><span class="mtk1">);</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> };</span></span></span> <span class="grvsc-line"><span class="grvsc-source"></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk4">const</span><span class="mtk1"> </span><span class="mtk11">onSelectChange</span><span class="mtk1"> = (</span><span class="mtk12">e</span><span class="mtk1">: </span><span class="mtk10">ChangeEvent</span><span class="mtk1">&lt;</span><span class="mtk10">HTMLSelectElement</span><span class="mtk1">&gt;) </span><span class="mtk4">=&gt;</span><span class="mtk1"> {</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk11">displayValidationMessage</span><span class="mtk1">(</span><span class="mtk12">e</span><span class="mtk1">);</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk11">setValue</span><span class="mtk1">(</span><span class="mtk12">e</span><span class="mtk1">.</span><span class="mtk12">target</span><span class="mtk1">.</span><span class="mtk12">value</span><span class="mtk1">);</span></span></span> <span class="grvsc-line grvsc-line-highlighted"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">tableMeta</span><span class="mtk1">?.</span><span class="mtk11">updateData</span><span class="mtk1">(</span><span class="mtk12">row</span><span class="mtk1">.</span><span class="mtk12">index</span><span class="mtk1">, </span><span class="mtk12">column</span><span class="mtk1">.</span><span class="mtk12">id</span><span class="mtk1">, </span><span class="mtk12">e</span><span class="mtk1">.</span><span class="mtk12">target</span><span class="mtk1">.</span><span class="mtk12">value</span><span class="mtk1">, </span><span class="mtk12">e</span><span class="mtk1">.</span><span class="mtk12">target</span><span class="mtk1">.</span><span class="mtk12">validity</span><span class="mtk1">.</span><span class="mtk12">valid</span><span class="mtk1">);</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> };</span></span></span> <span class="grvsc-line"><span class="grvsc-source"></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> ...</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1">};</span></span></span></code></pre> <p>Finally, we will update the <code>EditCell</code> component to disable the save button if there is an invalid field in the current row. We will also style the save button to indicate that it is disabled.</p> <pre class="grvsc-container grvsc-has-line-highlighting default-dark" data-language="jsx" data-index="15"><code class="grvsc-code"><span class="grvsc-line"><span class="grvsc-source"><span class="mtk15">import</span><span class="mtk1"> { </span><span class="mtk12">MouseEvent</span><span class="mtk1"> } </span><span class="mtk15">from</span><span class="mtk1"> </span><span class="mtk8">&quot;react&quot;</span><span class="mtk1">;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk15">export</span><span class="mtk1"> </span><span class="mtk4">const</span><span class="mtk1"> </span><span class="mtk11">EditCell</span><span class="mtk1"> = ({ </span><span class="mtk12">row</span><span class="mtk1">, </span><span class="mtk12">table</span><span class="mtk1"> }) </span><span class="mtk4">=&gt;</span><span class="mtk1"> {</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk4">const</span><span class="mtk1"> </span><span class="mtk12">meta</span><span class="mtk1"> = </span><span class="mtk12">table</span><span class="mtk1">.</span><span class="mtk12">options</span><span class="mtk1">.</span><span class="mtk12">meta</span><span class="mtk1">;</span></span></span> <span class="grvsc-line grvsc-line-highlighted"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk4">const</span><span class="mtk1"> </span><span class="mtk12">validRow</span><span class="mtk1"> = </span><span class="mtk12">meta</span><span class="mtk1">?.</span><span class="mtk12">validRows</span><span class="mtk1">[</span><span class="mtk12">row</span><span class="mtk1">.</span><span class="mtk12">id</span><span class="mtk1">];</span></span></span> <span class="grvsc-line grvsc-line-highlighted"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk4">const</span><span class="mtk1"> </span><span class="mtk12">disableSubmit</span><span class="mtk1"> = </span><span class="mtk12">validRow</span><span class="mtk1"> ? </span><span class="mtk10">Object</span><span class="mtk1">.</span><span class="mtk11">values</span><span class="mtk1">(</span><span class="mtk12">validRow</span><span class="mtk1">)?.</span><span class="mtk11">some</span><span class="mtk1">(</span><span class="mtk12">item</span><span class="mtk1"> </span><span class="mtk4">=&gt;</span><span class="mtk1"> !</span><span class="mtk12">item</span><span class="mtk1">) : </span><span class="mtk4">false</span><span class="mtk1">;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> ...</span></span></span> <span class="grvsc-line"><span class="grvsc-source"></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk15">return</span><span class="mtk1"> (</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk17">&lt;</span><span class="mtk4">div</span><span class="mtk1"> </span><span class="mtk12">className</span><span class="mtk1">=</span><span class="mtk8">&quot;edit-cell-container&quot;</span><span class="mtk17">&gt;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk4">{</span><span class="mtk12">meta</span><span class="mtk1">?.</span><span class="mtk12">editedRows</span><span class="mtk1">[</span><span class="mtk12">row</span><span class="mtk1">.</span><span class="mtk12">id</span><span class="mtk1">] ? (</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk17">&lt;</span><span class="mtk4">div</span><span class="mtk1"> </span><span class="mtk12">className</span><span class="mtk1">=</span><span class="mtk8">&quot;edit-cell-action&quot;</span><span class="mtk17">&gt;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk17">&lt;</span><span class="mtk4">button</span><span class="mtk1"> </span><span class="mtk12">onClick</span><span class="mtk1">=</span><span class="mtk4">{</span><span class="mtk12">setEditedRows</span><span class="mtk4">}</span><span class="mtk1"> </span><span class="mtk12">name</span><span class="mtk1">=</span><span class="mtk8">&quot;cancel&quot;</span><span class="mtk17">&gt;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> ⚊</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk17">&lt;/</span><span class="mtk4">button</span><span class="mtk17">&gt;</span><span class="mtk4">{</span><span class="mtk8">&quot; &quot;</span><span class="mtk4">}</span></span></span> <span class="grvsc-line grvsc-line-highlighted"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk17">&lt;</span><span class="mtk4">button</span><span class="mtk1"> </span><span class="mtk12">onClick</span><span class="mtk1">=</span><span class="mtk4">{</span><span class="mtk12">setEditedRows</span><span class="mtk4">}</span><span class="mtk1"> </span><span class="mtk12">name</span><span class="mtk1">=</span><span class="mtk8">&quot;done&quot;</span><span class="mtk1"> </span><span class="mtk12">disabled</span><span class="mtk1">=</span><span class="mtk4">{</span><span class="mtk12">disableSubmit</span><span class="mtk4">}</span><span class="mtk17">&gt;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> ✔</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk17">&lt;/</span><span class="mtk4">button</span><span class="mtk17">&gt;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk17">&lt;/</span><span class="mtk4">div</span><span class="mtk17">&gt;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> ) : (</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk17">&lt;</span><span class="mtk4">div</span><span class="mtk1"> </span><span class="mtk12">className</span><span class="mtk1">=</span><span class="mtk8">&quot;edit-cell-action&quot;</span><span class="mtk17">&gt;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk17">&lt;</span><span class="mtk4">button</span><span class="mtk1"> </span><span class="mtk12">onClick</span><span class="mtk1">=</span><span class="mtk4">{</span><span class="mtk12">setEditedRows</span><span class="mtk4">}</span><span class="mtk1"> </span><span class="mtk12">name</span><span class="mtk1">=</span><span class="mtk8">&quot;edit&quot;</span><span class="mtk17">&gt;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> ✐</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk17">&lt;/</span><span class="mtk4">button</span><span class="mtk17">&gt;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk17">&lt;</span><span class="mtk4">button</span><span class="mtk1"> </span><span class="mtk12">onClick</span><span class="mtk1">=</span><span class="mtk4">{</span><span class="mtk12">removeRow</span><span class="mtk4">}</span><span class="mtk1"> </span><span class="mtk12">name</span><span class="mtk1">=</span><span class="mtk8">&quot;remove&quot;</span><span class="mtk17">&gt;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> X</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk17">&lt;/</span><span class="mtk4">button</span><span class="mtk17">&gt;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk17">&lt;/</span><span class="mtk4">div</span><span class="mtk17">&gt;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> )</span><span class="mtk4">}</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk17">&lt;</span><span class="mtk4">input</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">type</span><span class="mtk1">=</span><span class="mtk8">&quot;checkbox&quot;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">checked</span><span class="mtk1">=</span><span class="mtk4">{</span><span class="mtk12">row</span><span class="mtk1">.</span><span class="mtk11">getIsSelected</span><span class="mtk1">()</span><span class="mtk4">}</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">onChange</span><span class="mtk1">=</span><span class="mtk4">{</span><span class="mtk12">row</span><span class="mtk1">.</span><span class="mtk11">getToggleSelectedHandler</span><span class="mtk1">()</span><span class="mtk4">}</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk17">/&gt;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk17">&lt;/</span><span class="mtk4">div</span><span class="mtk17">&gt;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> );</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1">};</span></span></span></code></pre> <pre class="grvsc-container default-dark" data-language="css" data-index="16"><code class="grvsc-code"><span class="grvsc-line"><span class="grvsc-source"><span class="mtk6">table</span><span class="mtk1"> </span><span class="mtk6">.edit-cell-action</span><span class="mtk1"> </span><span class="mtk6">button</span><span class="mtk1">[</span><span class="mtk12">name</span><span class="mtk1">=</span><span class="mtk8">&#39;done&#39;</span><span class="mtk1">]</span><span class="mtk6">:disabled</span><span class="mtk1"> {</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">background-color</span><span class="mtk1">: </span><span class="mtk8">#ccc</span><span class="mtk1">;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">cursor</span><span class="mtk1">: </span><span class="mtk8">not-allowed</span><span class="mtk1">;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1">}</span></span></span></code></pre> <p>Here is the final demo of the table, when we try to save an invalid row, we will see that the save button is disabled.</p> <div id="ValidateReactTableSeven" data-code data-height="350px"></div> <h2 id="complete-code-and-live-demo" style="position:relative;"><a href="#complete-code-and-live-demo" aria-label="complete code and live demo permalink" class="anchor before"><svg aria-hidden="true" focusable="false" height="16" version="1.1" viewBox="0 0 16 16" width="16"><path fill-rule="evenodd" d="M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z"></path></svg></a>Complete code and live demo</h2> <p>The complete code is available in <a href="https://github.com/muhimasri/react-editable-table">this repository</a>. If you liked the tutorial, please <a href="https://github.com/muhimasri/react-editable-table/stargazers">star the repository</a>, and feel free to request new features!</p> <p>Alternatively, you can try the code in the live demo below:</p> <div data-stackblitz="vaildate-react-table"> <button>Run Code</button> </div> <h2 id="summary" style="position:relative;"><a href="#summary" aria-label="summary permalink" class="anchor before"><svg aria-hidden="true" focusable="false" height="16" version="1.1" viewBox="0 0 16 16" width="16"><path fill-rule="evenodd" d="M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z"></path></svg></a>Summary</h2> <p>In this part, we learned how to validate table rows and fields using React Tanstack. We learned how to validate required fields, select fields, and custom validations. We also learned how to display validation messages and disable the save button if there is an invalid field in the row.</p> <p>Bye for now 👋</p> <style class="grvsc-styles"> .grvsc-container { overflow: auto; position: relative; -webkit-overflow-scrolling: touch; padding-top: 1rem; padding-top: var(--grvsc-padding-top, var(--grvsc-padding-v, 1rem)); padding-bottom: 1rem; padding-bottom: var(--grvsc-padding-bottom, var(--grvsc-padding-v, 1rem)); border-radius: 8px; border-radius: var(--grvsc-border-radius, 8px); font-feature-settings: normal; line-height: 1.4; } .grvsc-code { display: table; } .grvsc-line { display: table-row; box-sizing: border-box; width: 100%; position: relative; } .grvsc-line > * { position: relative; } .grvsc-gutter-pad { display: table-cell; padding-left: 0.75rem; padding-left: calc(var(--grvsc-padding-left, var(--grvsc-padding-h, 1.5rem)) / 2); } .grvsc-gutter { display: table-cell; -webkit-user-select: none; -moz-user-select: none; user-select: none; } .grvsc-gutter::before { content: attr(data-content); } .grvsc-source { display: table-cell; padding-left: 1.5rem; padding-left: var(--grvsc-padding-left, var(--grvsc-padding-h, 1.5rem)); padding-right: 1.5rem; padding-right: var(--grvsc-padding-right, var(--grvsc-padding-h, 1.5rem)); } .grvsc-source:empty::after { content: ' '; -webkit-user-select: none; -moz-user-select: none; user-select: none; } .grvsc-gutter + .grvsc-source { padding-left: 0.75rem; padding-left: calc(var(--grvsc-padding-left, var(--grvsc-padding-h, 1.5rem)) / 2); } /* Line transformer styles */ .grvsc-has-line-highlighting > .grvsc-code > .grvsc-line::before { content: ' '; position: absolute; width: 100%; } .grvsc-line-diff-add::before { background-color: var(--grvsc-line-diff-add-background-color, rgba(0, 255, 60, 0.2)); } .grvsc-line-diff-del::before { background-color: var(--grvsc-line-diff-del-background-color, rgba(255, 0, 20, 0.2)); } .grvsc-line-number { padding: 0 2px; text-align: right; opacity: 0.7; } .default-dark { background-color: #1E1E1E; color: #D4D4D4; } .default-dark .mtk17 { color: #808080; } .default-dark .mtk4 { color: #569CD6; } .default-dark .mtk1 { color: #D4D4D4; } .default-dark .mtk12 { color: #9CDCFE; } .default-dark .mtk11 { color: #DCDCAA; } .default-dark .mtk8 { color: #CE9178; } .default-dark .mtk6 { color: #D7BA7D; } .default-dark .mtk7 { color: #B5CEA8; } .default-dark .mtk15 { color: #C586C0; } .default-dark .mtk10 { color: #4EC9B0; } .default-dark .mtk14 { color: #F44747; } .default-dark .grvsc-line-highlighted::before { background-color: var(--grvsc-line-highlighted-background-color, rgba(255, 255, 255, 0.1)); box-shadow: inset var(--grvsc-line-highlighted-border-width, 4px) 0 0 0 var(--grvsc-line-highlighted-border-color, rgba(255, 255, 255, 0.5)); } </style><![CDATA[[Part 2] Add and Remove Table Rows with React TanStack]]>https://muhimasri.comadd-remove-react-table-rowshttps://muhimasri.comadd-remove-react-table-rows<p>In the <a href="https://muhimasri.com/blogs/react-editable-table/">previous part</a>, we went through a detailed approach to creating an editable React table with a dynamic column schema. We also utilized TanStack Table to simplify the process. The code from the previous part is available <a href="https://stackblitz.com/edit/vitejs-vite-hzowq6?file=package.json">here in Stackblitz</a>.</p> <p>In this part, we will continue building on what we’ve done previously and add the ability to remove and add table rows with multiple row selections.</p> <p>Below is a short video of how we want the table to look and behave at the end of this tutorial:</p> <video width="720" height="400" autoplay loop muted preload="none"> <source src="/7fd7df47bd1545f8561fd1f91bbd49af/add-remove-table-rows.mp4" type="video/mp4"> </video> <p><em>As we continue building upon the same code from the previous part, it’s recommended that you go through the first tutorial to understand how the code structure works as we will not be explaining it here. You can navigate to any part using the table of contents.</em></p> <h2 id="add-table-row" style="position:relative;"><a href="#add-table-row" aria-label="add table row permalink" class="anchor before"><svg aria-hidden="true" focusable="false" height="16" version="1.1" viewBox="0 0 16 16" width="16"><path fill-rule="evenodd" d="M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z"></path></svg></a>Add table row</h2> <p>To enable adding table rows, we must add an “Add Row” button and then create the logic to insert an empty row into the data array.</p> <p>Let’s start by adding the logic to insert the row in the main table component. Like the previous approach, we’ll attach the function in the <code>meta</code> object in the <code>useReactTableHook</code>. This way, we can access it anywhere through the main <code>table</code> object:</p> <pre class="grvsc-container grvsc-has-line-highlighting default-dark" data-language="tsx" data-index="0"><code class="grvsc-code"><span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk4">const</span><span class="mtk1"> </span><span class="mtk12">table</span><span class="mtk1"> = </span><span class="mtk11">useReactTable</span><span class="mtk1">({</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">data</span><span class="mtk1">,</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">columns</span><span class="mtk1">,</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">getCoreRowModel:</span><span class="mtk1"> </span><span class="mtk11">getCoreRowModel</span><span class="mtk1">(),</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">meta:</span><span class="mtk1"> {</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">editedRows</span><span class="mtk1">,</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">setEditedRows</span><span class="mtk1">,</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">revertData:</span><span class="mtk1"> (...) </span><span class="mtk4">=&gt;</span><span class="mtk1"> {</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> ...</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> },</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">updateData:</span><span class="mtk1"> (...) </span><span class="mtk4">=&gt;</span><span class="mtk1"> {</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> ...</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> },</span></span></span> <span class="grvsc-line grvsc-line-highlighted"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk11">addRow</span><span class="mtk12">:</span><span class="mtk1"> () </span><span class="mtk4">=&gt;</span><span class="mtk1"> {</span></span></span> <span class="grvsc-line grvsc-line-highlighted"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk4">const</span><span class="mtk1"> </span><span class="mtk12">newRow</span><span class="mtk1">: </span><span class="mtk10">Student</span><span class="mtk1"> = {</span></span></span> <span class="grvsc-line grvsc-line-highlighted"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">studentId:</span><span class="mtk1"> </span><span class="mtk10">Math</span><span class="mtk1">.</span><span class="mtk11">floor</span><span class="mtk1">(</span><span class="mtk10">Math</span><span class="mtk1">.</span><span class="mtk11">random</span><span class="mtk1">() * </span><span class="mtk7">10000</span><span class="mtk1">),</span></span></span> <span class="grvsc-line grvsc-line-highlighted"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">name:</span><span class="mtk1"> </span><span class="mtk8">&quot;&quot;</span><span class="mtk1">,</span></span></span> <span class="grvsc-line grvsc-line-highlighted"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">dateOfBirth:</span><span class="mtk1"> </span><span class="mtk8">&quot;&quot;</span><span class="mtk1">,</span></span></span> <span class="grvsc-line grvsc-line-highlighted"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">major:</span><span class="mtk1"> </span><span class="mtk8">&quot;&quot;</span><span class="mtk1">,</span></span></span> <span class="grvsc-line grvsc-line-highlighted"><span class="grvsc-source"><span class="mtk1"> };</span></span></span> <span class="grvsc-line grvsc-line-highlighted"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk4">const</span><span class="mtk1"> </span><span class="mtk11">setFunc</span><span class="mtk1"> = (</span><span class="mtk12">old</span><span class="mtk1">: </span><span class="mtk10">Student</span><span class="mtk1">[]) </span><span class="mtk4">=&gt;</span><span class="mtk1"> [...</span><span class="mtk12">old</span><span class="mtk1">, </span><span class="mtk12">newRow</span><span class="mtk1">];</span></span></span> <span class="grvsc-line grvsc-line-highlighted"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk11">setData</span><span class="mtk1">(</span><span class="mtk12">setFunc</span><span class="mtk1">);</span></span></span> <span class="grvsc-line grvsc-line-highlighted"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk11">setOriginalData</span><span class="mtk1">(</span><span class="mtk12">setFunc</span><span class="mtk1">);</span></span></span> <span class="grvsc-line grvsc-line-highlighted"><span class="grvsc-source"><span class="mtk1"> },</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> },</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> });</span></span></span></code></pre> <p>Note that we also updated the <code>originalData</code> array, as we need to keep them in sync for the cancel/save row functionality discussed in the <a href="https://muhimasri.com/blogs/react-editable-table/">first part</a>.</p> <p>Now, we can create a Footer Cell component with a button and event handler to consume the <code>addRow</code> function.</p> <pre class="grvsc-container default-dark" data-language="tsx" data-index="1"><code class="grvsc-code"><span class="grvsc-line"><span class="grvsc-source"><span class="mtk15">export</span><span class="mtk1"> </span><span class="mtk4">const</span><span class="mtk1"> </span><span class="mtk11">FooterCell</span><span class="mtk1"> = ({ </span><span class="mtk12">table</span><span class="mtk1"> }) </span><span class="mtk4">=&gt;</span><span class="mtk1"> {</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk4">const</span><span class="mtk1"> </span><span class="mtk12">meta</span><span class="mtk1"> = </span><span class="mtk12">table</span><span class="mtk1">.</span><span class="mtk12">options</span><span class="mtk1">.</span><span class="mtk12">meta</span></span></span> <span class="grvsc-line"><span class="grvsc-source"></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk15">return</span><span class="mtk1"> (</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk17">&lt;</span><span class="mtk4">div</span><span class="mtk1"> </span><span class="mtk12">className</span><span class="mtk1">=</span><span class="mtk8">&quot;footer-buttons&quot;</span><span class="mtk17">&gt;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk17">&lt;</span><span class="mtk4">button</span><span class="mtk1"> </span><span class="mtk12">className</span><span class="mtk1">=</span><span class="mtk8">&quot;add-button&quot;</span><span class="mtk1"> </span><span class="mtk12">onClick</span><span class="mtk1">=</span><span class="mtk4">{</span><span class="mtk12">meta</span><span class="mtk1">?.</span><span class="mtk12">addRow</span><span class="mtk4">}</span><span class="mtk17">&gt;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> Add New +</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk17">&lt;/</span><span class="mtk4">button</span><span class="mtk17">&gt;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk17">&lt;/</span><span class="mtk4">div</span><span class="mtk17">&gt;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> )</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1">}</span></span></span></code></pre> <p>Lastly, we need to display the <code>FooterCell</code> component somewhere on the table for the user to consume. There are multiple options, but adding it to the footer’s main table can be a good place as it will feel more integrated.</p> <pre class="grvsc-container grvsc-has-line-highlighting default-dark" data-language="tsx" data-index="2"><code class="grvsc-code"><span class="grvsc-line grvsc-line-highlighted"><span class="grvsc-source"><span class="mtk15">import</span><span class="mtk1"> { </span><span class="mtk12">FooterCell</span><span class="mtk1"> } </span><span class="mtk15">from</span><span class="mtk1"> </span><span class="mtk8">&#39;../Table/FooterCell&#39;</span><span class="mtk1">;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk15">export</span><span class="mtk1"> </span><span class="mtk4">const</span><span class="mtk1"> </span><span class="mtk11">Table</span><span class="mtk1"> = () </span><span class="mtk4">=&gt;</span><span class="mtk1"> {</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk4">const</span><span class="mtk1"> [</span><span class="mtk12">data</span><span class="mtk1">, </span><span class="mtk12">setData</span><span class="mtk1">] = </span><span class="mtk11">useState</span><span class="mtk1">(() </span><span class="mtk4">=&gt;</span><span class="mtk1"> [...</span><span class="mtk12">defaultData</span><span class="mtk1">]);</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk4">const</span><span class="mtk1"> [</span><span class="mtk12">originalData</span><span class="mtk1">, </span><span class="mtk12">setOriginalData</span><span class="mtk1">] = </span><span class="mtk11">useState</span><span class="mtk1">(() </span><span class="mtk4">=&gt;</span><span class="mtk1"> [...</span><span class="mtk12">defaultData</span><span class="mtk1">]);</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk4">const</span><span class="mtk1"> [</span><span class="mtk12">editedRows</span><span class="mtk1">, </span><span class="mtk12">setEditedRows</span><span class="mtk1">] = </span><span class="mtk11">useState</span><span class="mtk1">({});</span></span></span> <span class="grvsc-line"><span class="grvsc-source"></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk4">const</span><span class="mtk1"> </span><span class="mtk12">table</span><span class="mtk1"> = </span><span class="mtk11">useReactTable</span><span class="mtk1">({</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">data</span><span class="mtk1">,</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">columns</span><span class="mtk1">,</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">getCoreRowModel:</span><span class="mtk1"> </span><span class="mtk11">getCoreRowModel</span><span class="mtk1">(),</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">meta:</span><span class="mtk1"> {</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">editedRows</span><span class="mtk1">,</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">setEditedRows</span><span class="mtk1">,</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">revertData:</span><span class="mtk1"> (...) </span><span class="mtk4">=&gt;</span><span class="mtk1"> {</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> ...</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> },</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">updateData:</span><span class="mtk1"> (...) </span><span class="mtk4">=&gt;</span><span class="mtk1"> {</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> ...</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> },</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk11">addRow</span><span class="mtk12">:</span><span class="mtk1"> () </span><span class="mtk4">=&gt;</span><span class="mtk1"> {</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk4">const</span><span class="mtk1"> </span><span class="mtk12">newRow</span><span class="mtk1">: </span><span class="mtk10">Student</span><span class="mtk1"> = {</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">studentId:</span><span class="mtk1"> </span><span class="mtk10">Math</span><span class="mtk1">.</span><span class="mtk11">floor</span><span class="mtk1">(</span><span class="mtk10">Math</span><span class="mtk1">.</span><span class="mtk11">random</span><span class="mtk1">() * </span><span class="mtk7">10000</span><span class="mtk1">),</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">name:</span><span class="mtk1"> </span><span class="mtk8">&quot;&quot;</span><span class="mtk1">,</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">dateOfBirth:</span><span class="mtk1"> </span><span class="mtk8">&quot;&quot;</span><span class="mtk1">,</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">major:</span><span class="mtk1"> </span><span class="mtk8">&quot;&quot;</span><span class="mtk1">,</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> };</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk4">const</span><span class="mtk1"> </span><span class="mtk11">setFunc</span><span class="mtk1"> = (</span><span class="mtk12">old</span><span class="mtk1">: </span><span class="mtk10">Student</span><span class="mtk1">[]) </span><span class="mtk4">=&gt;</span><span class="mtk1"> [...</span><span class="mtk12">old</span><span class="mtk1">, </span><span class="mtk12">newRow</span><span class="mtk1">];</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk11">setData</span><span class="mtk1">(</span><span class="mtk12">setFunc</span><span class="mtk1">);</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk11">setOriginalData</span><span class="mtk1">(</span><span class="mtk12">setFunc</span><span class="mtk1">);</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> },</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> },</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> });</span></span></span> <span class="grvsc-line"><span class="grvsc-source"></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk15">return</span><span class="mtk1"> (</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk17">&lt;</span><span class="mtk4">article</span><span class="mtk1"> </span><span class="mtk12">className</span><span class="mtk1">=</span><span class="mtk8">&quot;table-container&quot;</span><span class="mtk17">&gt;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk17">&lt;</span><span class="mtk4">table</span><span class="mtk17">&gt;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk17">&lt;</span><span class="mtk4">thead</span><span class="mtk17">&gt;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> ...</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk17">&lt;/</span><span class="mtk4">thead</span><span class="mtk17">&gt;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk17">&lt;</span><span class="mtk4">tbody</span><span class="mtk17">&gt;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> ...</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk17">&lt;/</span><span class="mtk4">tbody</span><span class="mtk17">&gt;</span></span></span> <span class="grvsc-line grvsc-line-highlighted"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk17">&lt;</span><span class="mtk4">tfoot</span><span class="mtk17">&gt;</span></span></span> <span class="grvsc-line grvsc-line-highlighted"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk17">&lt;</span><span class="mtk4">tr</span><span class="mtk17">&gt;</span></span></span> <span class="grvsc-line grvsc-line-highlighted"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk17">&lt;</span><span class="mtk4">th</span><span class="mtk1"> </span><span class="mtk12">colSpan</span><span class="mtk1">=</span><span class="mtk4">{</span><span class="mtk12">table</span><span class="mtk1">.</span><span class="mtk11">getCenterLeafColumns</span><span class="mtk1">().</span><span class="mtk12">length</span><span class="mtk4">}</span><span class="mtk1"> </span><span class="mtk12">align</span><span class="mtk1">=</span><span class="mtk8">&quot;right&quot;</span><span class="mtk17">&gt;</span></span></span> <span class="grvsc-line grvsc-line-highlighted"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk17">&lt;</span><span class="mtk10">FooterCell</span><span class="mtk1"> </span><span class="mtk12">table</span><span class="mtk1">=</span><span class="mtk4">{</span><span class="mtk12">table</span><span class="mtk4">}</span><span class="mtk1"> </span><span class="mtk17">/&gt;</span></span></span> <span class="grvsc-line grvsc-line-highlighted"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk17">&lt;/</span><span class="mtk4">th</span><span class="mtk17">&gt;</span></span></span> <span class="grvsc-line grvsc-line-highlighted"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk17">&lt;/</span><span class="mtk4">tr</span><span class="mtk17">&gt;</span></span></span> <span class="grvsc-line grvsc-line-highlighted"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk17">&lt;/</span><span class="mtk4">tfoot</span><span class="mtk17">&gt;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk17">&lt;/</span><span class="mtk4">table</span><span class="mtk17">&gt;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk17">&lt;/</span><span class="mtk4">article</span><span class="mtk17">&gt;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> );</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1">};</span></span></span></code></pre> <p>Below is a live example of the code above with some button styling:</p> <div id="AddRemoveReactTableRowsOne" data-code data-height="350px"></div> <pre class="grvsc-container default-dark" data-language="css" data-index="3"><code class="grvsc-code"><span class="grvsc-line"><span class="grvsc-source"><span class="mtk6">table</span><span class="mtk1"> </span><span class="mtk6">.footer-buttons</span><span class="mtk1"> </span><span class="mtk6">button</span><span class="mtk1"> {</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">border</span><span class="mtk1">: </span><span class="mtk8">none</span><span class="mtk1">;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">background-color</span><span class="mtk1">: </span><span class="mtk8">transparent</span><span class="mtk1">;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1">}</span></span></span> <span class="grvsc-line"><span class="grvsc-source"></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk6">table</span><span class="mtk1"> </span><span class="mtk6">.add-button</span><span class="mtk1"> {</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">color</span><span class="mtk1">: </span><span class="mtk8">#4bbd7f</span><span class="mtk1">;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1">}</span></span></span></code></pre> <h2 id="remove-table-row" style="position:relative;"><a href="#remove-table-row" aria-label="remove table row permalink" class="anchor before"><svg aria-hidden="true" focusable="false" height="16" version="1.1" viewBox="0 0 16 16" width="16"><path fill-rule="evenodd" d="M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z"></path></svg></a>Remove table row</h2> <p>Removing table rows will follow the same approach as the previous section. Let’s start by adding the <code>removeRow</code> function, a simple one-liner filter method to remove the row from the data and original data arrays.</p> <pre class="grvsc-container grvsc-has-line-highlighting default-dark" data-language="tsx" data-index="4"><code class="grvsc-code"><span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk4">const</span><span class="mtk1"> </span><span class="mtk12">table</span><span class="mtk1"> = </span><span class="mtk11">useReactTable</span><span class="mtk1">({</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">data</span><span class="mtk1">,</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">columns</span><span class="mtk1">,</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">getCoreRowModel:</span><span class="mtk1"> </span><span class="mtk11">getCoreRowModel</span><span class="mtk1">(),</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">meta:</span><span class="mtk1"> {</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">editedRows</span><span class="mtk1">,</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">setEditedRows</span><span class="mtk1">,</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">revertData:</span><span class="mtk1"> (...) </span><span class="mtk4">=&gt;</span><span class="mtk1"> {</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> ...</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> },</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">updateData:</span><span class="mtk1"> (...) </span><span class="mtk4">=&gt;</span><span class="mtk1"> {</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> ...</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> },</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk11">addRow</span><span class="mtk12">:</span><span class="mtk1"> () </span><span class="mtk4">=&gt;</span><span class="mtk1"> {</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> ...</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> },</span></span></span> <span class="grvsc-line grvsc-line-highlighted"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk11">removeRow</span><span class="mtk12">:</span><span class="mtk1"> (</span><span class="mtk12">rowIndex</span><span class="mtk1">: </span><span class="mtk10">number</span><span class="mtk1">) </span><span class="mtk4">=&gt;</span><span class="mtk1"> {</span></span></span> <span class="grvsc-line grvsc-line-highlighted"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk4">const</span><span class="mtk1"> </span><span class="mtk11">setFilterFunc</span><span class="mtk1"> = (</span><span class="mtk12">old</span><span class="mtk1">: </span><span class="mtk10">Student</span><span class="mtk1">[]) </span><span class="mtk4">=&gt;</span></span></span> <span class="grvsc-line grvsc-line-highlighted"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">old</span><span class="mtk1">.</span><span class="mtk11">filter</span><span class="mtk1">((</span><span class="mtk12">_row</span><span class="mtk1">: </span><span class="mtk10">Student</span><span class="mtk1">, </span><span class="mtk12">index</span><span class="mtk1">: </span><span class="mtk10">number</span><span class="mtk1">) </span><span class="mtk4">=&gt;</span><span class="mtk1"> </span><span class="mtk12">index</span><span class="mtk1"> !== </span><span class="mtk12">rowIndex</span><span class="mtk1">);</span></span></span> <span class="grvsc-line grvsc-line-highlighted"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk11">setData</span><span class="mtk1">(</span><span class="mtk12">setFilterFunc</span><span class="mtk1">);</span></span></span> <span class="grvsc-line grvsc-line-highlighted"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk11">setOriginalData</span><span class="mtk1">(</span><span class="mtk12">setFilterFunc</span><span class="mtk1">);</span></span></span> <span class="grvsc-line grvsc-line-highlighted"><span class="grvsc-source"><span class="mtk1"> },</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> },</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> });</span></span></span></code></pre> <p>For the “Remove” button, creating a new component wouldn’t be necessary as it will reside next to the “Edit” button in the <code>EditCell</code> component.</p> <p>Now, we can add a <code>removeRow</code> function in the <code>EditCell</code> component and call it on the “Remove” button’s <code>onClick</code> event.</p> <pre class="grvsc-container grvsc-has-line-highlighting default-dark" data-language="tsx" data-index="5"><code class="grvsc-code"><span class="grvsc-line"><span class="grvsc-source"><span class="mtk15">export</span><span class="mtk1"> </span><span class="mtk4">const</span><span class="mtk1"> </span><span class="mtk11">EditCell</span><span class="mtk1"> = ({ </span><span class="mtk12">row</span><span class="mtk1">, </span><span class="mtk12">table</span><span class="mtk1"> }) </span><span class="mtk4">=&gt;</span><span class="mtk1"> {</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk4">const</span><span class="mtk1"> </span><span class="mtk12">meta</span><span class="mtk1"> = </span><span class="mtk12">table</span><span class="mtk1">.</span><span class="mtk12">options</span><span class="mtk1">.</span><span class="mtk12">meta</span><span class="mtk1">;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk4">const</span><span class="mtk1"> </span><span class="mtk12">setEditedRows</span><span class="mtk1"> = (...) </span><span class="mtk4">=&gt;</span><span class="mtk1"> {</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> ...</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> };</span></span></span> <span class="grvsc-line"><span class="grvsc-source"></span></span> <span class="grvsc-line grvsc-line-highlighted"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk4">const</span><span class="mtk1"> </span><span class="mtk11">removeRow</span><span class="mtk1"> = () </span><span class="mtk4">=&gt;</span><span class="mtk1"> {</span></span></span> <span class="grvsc-line grvsc-line-highlighted"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">meta</span><span class="mtk1">?.</span><span class="mtk11">removeRow</span><span class="mtk1">(</span><span class="mtk12">row</span><span class="mtk1">.</span><span class="mtk12">index</span><span class="mtk1">);</span></span></span> <span class="grvsc-line grvsc-line-highlighted"><span class="grvsc-source"><span class="mtk1"> };</span></span></span> <span class="grvsc-line"><span class="grvsc-source"></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk15">return</span><span class="mtk1"> (</span></span></span> <span class="grvsc-line grvsc-line-highlighted"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk17">&lt;</span><span class="mtk4">div</span><span class="mtk1"> </span><span class="mtk12">className</span><span class="mtk1">=</span><span class="mtk8">&quot;edit-cell-container&quot;</span><span class="mtk17">&gt;</span></span></span> <span class="grvsc-line grvsc-line-highlighted"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk4">{</span><span class="mtk12">meta</span><span class="mtk1">?.</span><span class="mtk12">editedRows</span><span class="mtk1">[</span><span class="mtk12">row</span><span class="mtk1">.</span><span class="mtk12">id</span><span class="mtk1">] ? (</span></span></span> <span class="grvsc-line grvsc-line-highlighted"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk17">&lt;</span><span class="mtk4">div</span><span class="mtk1"> </span><span class="mtk12">className</span><span class="mtk1">=</span><span class="mtk8">&quot;edit-cell-action&quot;</span><span class="mtk17">&gt;</span></span></span> <span class="grvsc-line grvsc-line-highlighted"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk17">&lt;</span><span class="mtk4">button</span><span class="mtk1"> </span><span class="mtk12">onClick</span><span class="mtk1">=</span><span class="mtk4">{</span><span class="mtk12">setEditedRows</span><span class="mtk4">}</span><span class="mtk1"> </span><span class="mtk12">name</span><span class="mtk1">=</span><span class="mtk8">&quot;cancel&quot;</span><span class="mtk17">&gt;</span></span></span> <span class="grvsc-line grvsc-line-highlighted"><span class="grvsc-source"><span class="mtk1"> ⚊</span></span></span> <span class="grvsc-line grvsc-line-highlighted"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk17">&lt;/</span><span class="mtk4">button</span><span class="mtk17">&gt;</span><span class="mtk4">{</span><span class="mtk8">&quot; &quot;</span><span class="mtk4">}</span></span></span> <span class="grvsc-line grvsc-line-highlighted"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk17">&lt;</span><span class="mtk4">button</span><span class="mtk1"> </span><span class="mtk12">onClick</span><span class="mtk1">=</span><span class="mtk4">{</span><span class="mtk12">setEditedRows</span><span class="mtk4">}</span><span class="mtk1"> </span><span class="mtk12">name</span><span class="mtk1">=</span><span class="mtk8">&quot;done&quot;</span><span class="mtk17">&gt;</span></span></span> <span class="grvsc-line grvsc-line-highlighted"><span class="grvsc-source"><span class="mtk1"> ✔</span></span></span> <span class="grvsc-line grvsc-line-highlighted"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk17">&lt;/</span><span class="mtk4">button</span><span class="mtk17">&gt;</span></span></span> <span class="grvsc-line grvsc-line-highlighted"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk17">&lt;/</span><span class="mtk4">div</span><span class="mtk17">&gt;</span></span></span> <span class="grvsc-line grvsc-line-highlighted"><span class="grvsc-source"><span class="mtk1"> ) : (</span></span></span> <span class="grvsc-line grvsc-line-highlighted"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk17">&lt;</span><span class="mtk4">div</span><span class="mtk1"> </span><span class="mtk12">className</span><span class="mtk1">=</span><span class="mtk8">&quot;edit-cell-action&quot;</span><span class="mtk17">&gt;</span></span></span> <span class="grvsc-line grvsc-line-highlighted"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk17">&lt;</span><span class="mtk4">button</span><span class="mtk1"> </span><span class="mtk12">onClick</span><span class="mtk1">=</span><span class="mtk4">{</span><span class="mtk12">setEditedRows</span><span class="mtk4">}</span><span class="mtk1"> </span><span class="mtk12">name</span><span class="mtk1">=</span><span class="mtk8">&quot;edit&quot;</span><span class="mtk17">&gt;</span></span></span> <span class="grvsc-line grvsc-line-highlighted"><span class="grvsc-source"><span class="mtk1"> ✐</span></span></span> <span class="grvsc-line grvsc-line-highlighted"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk17">&lt;/</span><span class="mtk4">button</span><span class="mtk17">&gt;</span></span></span> <span class="grvsc-line grvsc-line-highlighted"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk17">&lt;</span><span class="mtk4">button</span><span class="mtk1"> </span><span class="mtk12">onClick</span><span class="mtk1">=</span><span class="mtk4">{</span><span class="mtk12">removeRow</span><span class="mtk4">}</span><span class="mtk1"> </span><span class="mtk12">name</span><span class="mtk1">=</span><span class="mtk8">&quot;remove&quot;</span><span class="mtk17">&gt;</span></span></span> <span class="grvsc-line grvsc-line-highlighted"><span class="grvsc-source"><span class="mtk1"> X</span></span></span> <span class="grvsc-line grvsc-line-highlighted"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk17">&lt;/</span><span class="mtk4">button</span><span class="mtk17">&gt;</span></span></span> <span class="grvsc-line grvsc-line-highlighted"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk17">&lt;/</span><span class="mtk4">div</span><span class="mtk17">&gt;</span></span></span> <span class="grvsc-line grvsc-line-highlighted"><span class="grvsc-source"><span class="mtk1"> )</span><span class="mtk4">}</span></span></span> <span class="grvsc-line grvsc-line-highlighted"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk17">&lt;/</span><span class="mtk4">div</span><span class="mtk17">&gt;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> );</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1">};</span></span></span> <span class="grvsc-line"><span class="grvsc-source"></span></span></code></pre> <p>Note that we changed the “Cancel” icon to a minus sign (⚊) and the “Remove” icon to a cross (X) for better clarity.</p> <p>Below is a live demo of the code above with some button styling and alignment:</p> <div id="AddRemoveReactTableRowsTwo" data-code data-height="350px"></div> <pre class="grvsc-container default-dark" data-language="css" data-index="6"><code class="grvsc-code"><span class="grvsc-line"><span class="grvsc-source"><span class="mtk6">table</span><span class="mtk1"> </span><span class="mtk6">.edit-cell-action</span><span class="mtk1"> </span><span class="mtk6">button</span><span class="mtk1">[</span><span class="mtk12">name</span><span class="mtk1">=</span><span class="mtk8">&quot;edit&quot;</span><span class="mtk1">] {</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">color</span><span class="mtk1">: </span><span class="mtk8">#ffb918</span><span class="mtk1">;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1">}</span></span></span> <span class="grvsc-line"><span class="grvsc-source"></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk6">table</span><span class="mtk1"> </span><span class="mtk6">.edit-cell-action</span><span class="mtk1"> </span><span class="mtk6">button</span><span class="mtk1">[</span><span class="mtk12">name</span><span class="mtk1">=</span><span class="mtk8">&quot;cancel&quot;</span><span class="mtk1">] {</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">color</span><span class="mtk1">: </span><span class="mtk8">#7b7b7b</span><span class="mtk1">;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1">}</span></span></span> <span class="grvsc-line"><span class="grvsc-source"></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk6">table</span><span class="mtk1"> </span><span class="mtk6">.edit-cell-action</span><span class="mtk1"> </span><span class="mtk6">button</span><span class="mtk1">[</span><span class="mtk12">name</span><span class="mtk1">=</span><span class="mtk8">&quot;done&quot;</span><span class="mtk1">] {</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">color</span><span class="mtk1">: </span><span class="mtk8">#4bbd7f</span><span class="mtk1">;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1">}</span></span></span> <span class="grvsc-line"><span class="grvsc-source"></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk6">table</span><span class="mtk1"> </span><span class="mtk6">.edit-cell-action</span><span class="mtk1"> </span><span class="mtk6">button</span><span class="mtk1">[</span><span class="mtk12">name</span><span class="mtk1">=</span><span class="mtk8">&quot;remove&quot;</span><span class="mtk1">] {</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">color</span><span class="mtk1">: </span><span class="mtk8">red</span><span class="mtk1">;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">background-color</span><span class="mtk1">: </span><span class="mtk11">rgb</span><span class="mtk1">(</span><span class="mtk7">230</span><span class="mtk1">, </span><span class="mtk7">208</span><span class="mtk1">, </span><span class="mtk7">208</span><span class="mtk1">);</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1">}</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk6">table</span><span class="mtk1"> </span><span class="mtk6">.edit-cell-action</span><span class="mtk1"> {</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">display</span><span class="mtk1">: </span><span class="mtk8">flex</span><span class="mtk1">;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">gap</span><span class="mtk1">: </span><span class="mtk7">5px</span><span class="mtk1">;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1">}</span></span></span></code></pre> <h2 id="remove-multiple-table-rows" style="position:relative;"><a href="#remove-multiple-table-rows" aria-label="remove multiple table rows permalink" class="anchor before"><svg aria-hidden="true" focusable="false" height="16" version="1.1" viewBox="0 0 16 16" width="16"><path fill-rule="evenodd" d="M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z"></path></svg></a>Remove multiple table rows</h2> <p>It’s always helpful to select and remove multiple rows at once. Luckily, row selection is available out of the box from TanStack Table. All we need to do is enable the feature and pass in the proper methods; it will manage the rest for us.</p> <p>First, we’ll add <code>enableRowSelection</code> in <code>useReactTable</code> and create a new <code>removeSelectedRows</code> function. The function will receive an array of selected row IDs and filter them out from the <code>data</code> array.</p> <pre class="grvsc-container grvsc-has-line-highlighting default-dark" data-language="tsx" data-index="7"><code class="grvsc-code"><span class="grvsc-line"><span class="grvsc-source"><span class="mtk4">const</span><span class="mtk1"> </span><span class="mtk12">table</span><span class="mtk1"> = </span><span class="mtk11">useReactTable</span><span class="mtk1">({</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">data</span><span class="mtk1">,</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">columns</span><span class="mtk1">,</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">getCoreRowModel:</span><span class="mtk1"> </span><span class="mtk11">getCoreRowModel</span><span class="mtk1">(),</span></span></span> <span class="grvsc-line grvsc-line-highlighted"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">enableRowSelection:</span><span class="mtk1"> </span><span class="mtk4">true</span><span class="mtk1">,</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">meta:</span><span class="mtk1"> {</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">editedRows</span><span class="mtk1">,</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">setEditedRows</span><span class="mtk1">,</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">revertData:</span><span class="mtk1"> (...) </span><span class="mtk4">=&gt;</span><span class="mtk1"> {</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> ...</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> },</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">updateData:</span><span class="mtk1"> (...) </span><span class="mtk4">=&gt;</span><span class="mtk1"> {</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> ...</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> },</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk11">addRow</span><span class="mtk12">:</span><span class="mtk1"> () </span><span class="mtk4">=&gt;</span><span class="mtk1"> {</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> ...</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> },</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">removeRow:</span><span class="mtk1"> (...) </span><span class="mtk4">=&gt;</span><span class="mtk1"> {</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> ...</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> },</span></span></span> <span class="grvsc-line grvsc-line-highlighted"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk11">removeSelectedRows</span><span class="mtk12">:</span><span class="mtk1"> (</span><span class="mtk12">selectedRows</span><span class="mtk1">: </span><span class="mtk10">number</span><span class="mtk1">[]) </span><span class="mtk4">=&gt;</span><span class="mtk1"> {</span></span></span> <span class="grvsc-line grvsc-line-highlighted"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk4">const</span><span class="mtk1"> </span><span class="mtk11">setFilterFunc</span><span class="mtk1"> = (</span><span class="mtk12">old</span><span class="mtk1">: </span><span class="mtk10">Student</span><span class="mtk1">[]) </span><span class="mtk4">=&gt;</span></span></span> <span class="grvsc-line grvsc-line-highlighted"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">old</span><span class="mtk1">.</span><span class="mtk11">filter</span><span class="mtk1">((</span><span class="mtk12">_row</span><span class="mtk1">, </span><span class="mtk12">index</span><span class="mtk1">) </span><span class="mtk4">=&gt;</span><span class="mtk1"> !</span><span class="mtk12">selectedRows</span><span class="mtk1">.</span><span class="mtk11">includes</span><span class="mtk1">(</span><span class="mtk12">index</span><span class="mtk1">));</span></span></span> <span class="grvsc-line grvsc-line-highlighted"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk11">setData</span><span class="mtk1">(</span><span class="mtk12">setFilterFunc</span><span class="mtk1">);</span></span></span> <span class="grvsc-line grvsc-line-highlighted"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk11">setOriginalData</span><span class="mtk1">(</span><span class="mtk12">setFilterFunc</span><span class="mtk1">);</span></span></span> <span class="grvsc-line grvsc-line-highlighted"><span class="grvsc-source"><span class="mtk1"> },</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> },</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1">});</span></span></span></code></pre> <p>Then, in the <code>EditCell</code> component, we’ll add a checkbox input with the appropriate props to capture and update the selected rows. The event handlers are coming from the <code>row</code> object available for us from the <code>useReactTable</code> hook.</p> <pre class="grvsc-container grvsc-has-line-highlighting default-dark" data-language="tsx" data-index="8"><code class="grvsc-code"><span class="grvsc-line"><span class="grvsc-source"><span class="mtk15">export</span><span class="mtk1"> </span><span class="mtk4">const</span><span class="mtk1"> </span><span class="mtk11">EditCell</span><span class="mtk1"> = ({ </span><span class="mtk12">row</span><span class="mtk1">, </span><span class="mtk12">table</span><span class="mtk1"> }) </span><span class="mtk4">=&gt;</span><span class="mtk1"> {</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk4">const</span><span class="mtk1"> </span><span class="mtk12">meta</span><span class="mtk1"> = </span><span class="mtk12">table</span><span class="mtk1">.</span><span class="mtk12">options</span><span class="mtk1">.</span><span class="mtk12">meta</span><span class="mtk1">;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk4">const</span><span class="mtk1"> </span><span class="mtk12">setEditedRows</span><span class="mtk1"> = (...) </span><span class="mtk4">=&gt;</span><span class="mtk1"> {</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> ...</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> };</span></span></span> <span class="grvsc-line"><span class="grvsc-source"></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk4">const</span><span class="mtk1"> </span><span class="mtk11">removeRow</span><span class="mtk1"> = () </span><span class="mtk4">=&gt;</span><span class="mtk1"> {</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">meta</span><span class="mtk1">?.</span><span class="mtk11">removeRow</span><span class="mtk1">(</span><span class="mtk12">row</span><span class="mtk1">.</span><span class="mtk12">index</span><span class="mtk1">);</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> };</span></span></span> <span class="grvsc-line"><span class="grvsc-source"></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk15">return</span><span class="mtk1"> (</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk17">&lt;</span><span class="mtk4">div</span><span class="mtk1"> </span><span class="mtk12">className</span><span class="mtk1">=</span><span class="mtk8">&quot;edit-cell-container&quot;</span><span class="mtk17">&gt;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk4">{</span><span class="mtk12">meta</span><span class="mtk1">?.</span><span class="mtk12">editedRows</span><span class="mtk1">[</span><span class="mtk12">row</span><span class="mtk1">.</span><span class="mtk12">id</span><span class="mtk1">] ? (</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk17">&lt;</span><span class="mtk4">div</span><span class="mtk1"> </span><span class="mtk12">className</span><span class="mtk1">=</span><span class="mtk8">&quot;edit-cell-action&quot;</span><span class="mtk17">&gt;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk17">&lt;</span><span class="mtk4">button</span><span class="mtk1"> </span><span class="mtk12">onClick</span><span class="mtk1">=</span><span class="mtk4">{</span><span class="mtk12">setEditedRows</span><span class="mtk4">}</span><span class="mtk1"> </span><span class="mtk12">name</span><span class="mtk1">=</span><span class="mtk8">&quot;cancel&quot;</span><span class="mtk17">&gt;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> ⚊</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk17">&lt;/</span><span class="mtk4">button</span><span class="mtk17">&gt;</span><span class="mtk4">{</span><span class="mtk8">&quot; &quot;</span><span class="mtk4">}</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk17">&lt;</span><span class="mtk4">button</span><span class="mtk1"> </span><span class="mtk12">onClick</span><span class="mtk1">=</span><span class="mtk4">{</span><span class="mtk12">setEditedRows</span><span class="mtk4">}</span><span class="mtk1"> </span><span class="mtk12">name</span><span class="mtk1">=</span><span class="mtk8">&quot;done&quot;</span><span class="mtk17">&gt;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> ✔</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk17">&lt;/</span><span class="mtk4">button</span><span class="mtk17">&gt;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk17">&lt;/</span><span class="mtk4">div</span><span class="mtk17">&gt;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> ) : (</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk17">&lt;</span><span class="mtk4">div</span><span class="mtk1"> </span><span class="mtk12">className</span><span class="mtk1">=</span><span class="mtk8">&quot;edit-cell-action&quot;</span><span class="mtk17">&gt;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk17">&lt;</span><span class="mtk4">button</span><span class="mtk1"> </span><span class="mtk12">onClick</span><span class="mtk1">=</span><span class="mtk4">{</span><span class="mtk12">setEditedRows</span><span class="mtk4">}</span><span class="mtk1"> </span><span class="mtk12">name</span><span class="mtk1">=</span><span class="mtk8">&quot;edit&quot;</span><span class="mtk17">&gt;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> ✐</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk17">&lt;/</span><span class="mtk4">button</span><span class="mtk17">&gt;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk17">&lt;</span><span class="mtk4">button</span><span class="mtk1"> </span><span class="mtk12">onClick</span><span class="mtk1">=</span><span class="mtk4">{</span><span class="mtk12">removeRow</span><span class="mtk4">}</span><span class="mtk1"> </span><span class="mtk12">name</span><span class="mtk1">=</span><span class="mtk8">&quot;remove&quot;</span><span class="mtk17">&gt;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> X</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk17">&lt;/</span><span class="mtk4">button</span><span class="mtk17">&gt;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk17">&lt;/</span><span class="mtk4">div</span><span class="mtk17">&gt;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> )</span><span class="mtk4">}</span></span></span> <span class="grvsc-line grvsc-line-highlighted"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk17">&lt;</span><span class="mtk4">input</span></span></span> <span class="grvsc-line grvsc-line-highlighted"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">type</span><span class="mtk1">=</span><span class="mtk8">&quot;checkbox&quot;</span></span></span> <span class="grvsc-line grvsc-line-highlighted"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">checked</span><span class="mtk1">=</span><span class="mtk4">{</span><span class="mtk12">row</span><span class="mtk1">.</span><span class="mtk11">getIsSelected</span><span class="mtk1">()</span><span class="mtk4">}</span></span></span> <span class="grvsc-line grvsc-line-highlighted"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">onChange</span><span class="mtk1">=</span><span class="mtk4">{</span><span class="mtk12">row</span><span class="mtk1">.</span><span class="mtk11">getToggleSelectedHandler</span><span class="mtk1">()</span><span class="mtk4">}</span></span></span> <span class="grvsc-line grvsc-line-highlighted"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk17">/&gt;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk17">&lt;/</span><span class="mtk4">div</span><span class="mtk17">&gt;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> );</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1">};</span></span></span> <span class="grvsc-line"><span class="grvsc-source"></span></span></code></pre> <p>Last, we’ll add a new <code>Remove Selected</code> button to the <code>FooterCell</code> component and pass in the <code>removeSelectedRows</code> function from the <code>meta</code> object. The selected rows can be retrieved from the <code>getSelectedRowModel</code> function that has <code>rows</code> property.</p> <pre class="grvsc-container grvsc-has-line-highlighting default-dark" data-language="tsx" data-index="9"><code class="grvsc-code"><span class="grvsc-line"><span class="grvsc-source"><span class="mtk15">export</span><span class="mtk1"> </span><span class="mtk4">const</span><span class="mtk1"> </span><span class="mtk11">FooterCell</span><span class="mtk1"> = ({ </span><span class="mtk12">table</span><span class="mtk1"> }) </span><span class="mtk4">=&gt;</span><span class="mtk1"> {</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk4">const</span><span class="mtk1"> </span><span class="mtk12">meta</span><span class="mtk1"> = </span><span class="mtk12">table</span><span class="mtk1">.</span><span class="mtk12">options</span><span class="mtk1">.</span><span class="mtk12">meta</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk4">const</span><span class="mtk1"> </span><span class="mtk12">selectedRows</span><span class="mtk1"> = </span><span class="mtk12">table</span><span class="mtk1">.</span><span class="mtk11">getSelectedRowModel</span><span class="mtk1">().</span><span class="mtk12">rows</span></span></span> <span class="grvsc-line"><span class="grvsc-source"></span></span> <span class="grvsc-line grvsc-line-highlighted"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk4">const</span><span class="mtk1"> </span><span class="mtk11">removeRows</span><span class="mtk1"> = () </span><span class="mtk4">=&gt;</span><span class="mtk1"> {</span></span></span> <span class="grvsc-line grvsc-line-highlighted"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">meta</span><span class="mtk1">.</span><span class="mtk11">removeSelectedRows</span><span class="mtk1">(</span></span></span> <span class="grvsc-line grvsc-line-highlighted"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">table</span><span class="mtk1">.</span><span class="mtk11">getSelectedRowModel</span><span class="mtk1">().</span><span class="mtk12">rows</span><span class="mtk1">.</span><span class="mtk11">map</span><span class="mtk1">(</span><span class="mtk12">row</span><span class="mtk1"> </span><span class="mtk4">=&gt;</span><span class="mtk1"> </span><span class="mtk12">row</span><span class="mtk1">.</span><span class="mtk12">index</span><span class="mtk1">)</span></span></span> <span class="grvsc-line grvsc-line-highlighted"><span class="grvsc-source"><span class="mtk1"> )</span></span></span> <span class="grvsc-line grvsc-line-highlighted"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">table</span><span class="mtk1">.</span><span class="mtk11">resetRowSelection</span><span class="mtk1">()</span></span></span> <span class="grvsc-line grvsc-line-highlighted"><span class="grvsc-source"><span class="mtk1"> }</span></span></span> <span class="grvsc-line"><span class="grvsc-source"></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk15">return</span><span class="mtk1"> (</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk17">&lt;</span><span class="mtk4">div</span><span class="mtk1"> </span><span class="mtk12">className</span><span class="mtk1">=</span><span class="mtk8">&quot;footer-buttons&quot;</span><span class="mtk17">&gt;</span></span></span> <span class="grvsc-line grvsc-line-highlighted"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk4">{</span><span class="mtk12">selectedRows</span><span class="mtk1">.</span><span class="mtk12">length</span><span class="mtk1"> &gt; </span><span class="mtk7">0</span><span class="mtk1"> ? (</span></span></span> <span class="grvsc-line grvsc-line-highlighted"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk17">&lt;</span><span class="mtk4">button</span><span class="mtk1"> </span><span class="mtk12">className</span><span class="mtk1">=</span><span class="mtk8">&quot;remove-button&quot;</span><span class="mtk1"> </span><span class="mtk12">onClick</span><span class="mtk1">=</span><span class="mtk4">{</span><span class="mtk12">removeRows</span><span class="mtk4">}</span><span class="mtk17">&gt;</span></span></span> <span class="grvsc-line grvsc-line-highlighted"><span class="grvsc-source"><span class="mtk1"> Remove Selected x</span></span></span> <span class="grvsc-line grvsc-line-highlighted"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk17">&lt;/</span><span class="mtk4">button</span><span class="mtk17">&gt;</span></span></span> <span class="grvsc-line grvsc-line-highlighted"><span class="grvsc-source"><span class="mtk1"> ) : </span><span class="mtk4">null}</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk17">&lt;</span><span class="mtk4">button</span><span class="mtk1"> </span><span class="mtk12">className</span><span class="mtk1">=</span><span class="mtk8">&quot;add-button&quot;</span><span class="mtk1"> </span><span class="mtk12">onClick</span><span class="mtk1">=</span><span class="mtk4">{</span><span class="mtk12">meta</span><span class="mtk1">?.</span><span class="mtk12">addRow</span><span class="mtk4">}</span><span class="mtk17">&gt;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> Add New +</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk17">&lt;/</span><span class="mtk4">button</span><span class="mtk17">&gt;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk17">&lt;/</span><span class="mtk4">div</span><span class="mtk17">&gt;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> )</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1">}</span></span></span></code></pre> <p>Additionally, we added a condition to show the <code>Remove Selected</code> button only if there are selected rows.</p> <p>Below is the final demo, along with the rest of the styling for the <code>Remove Selected</code> button and check box input:</p> <div id="AddRemoveReactTableRowsThree" data-code data-height="350px"></div> <pre class="grvsc-container default-dark" data-language="css" data-index="10"><code class="grvsc-code"><span class="grvsc-line"><span class="grvsc-source"><span class="mtk6">table</span><span class="mtk1"> </span><span class="mtk6">.edit-cell-container</span><span class="mtk1"> {</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">display</span><span class="mtk1">: </span><span class="mtk8">flex</span><span class="mtk1">;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">justify-content</span><span class="mtk1">: </span><span class="mtk8">end</span><span class="mtk1">;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">align-items</span><span class="mtk1">: </span><span class="mtk8">center</span><span class="mtk1">;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">gap</span><span class="mtk1">: </span><span class="mtk7">4px</span><span class="mtk1">;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1">}</span></span></span> <span class="grvsc-line"><span class="grvsc-source"></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk6">table</span><span class="mtk1"> </span><span class="mtk6">input</span><span class="mtk1">[</span><span class="mtk12">type</span><span class="mtk1">=</span><span class="mtk8">&quot;checkbox&quot;</span><span class="mtk1">] {</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">width</span><span class="mtk1">: </span><span class="mtk7">16px</span><span class="mtk1">;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">height</span><span class="mtk1">: </span><span class="mtk7">16px</span><span class="mtk1">;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1">}</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk6">table</span><span class="mtk1"> </span><span class="mtk6">.remove-button</span><span class="mtk1"> {</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">color</span><span class="mtk1">: </span><span class="mtk8">#e44747</span><span class="mtk1">;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1">}</span></span></span></code></pre> <h2 id="complete-code-and-live-demo" style="position:relative;"><a href="#complete-code-and-live-demo" aria-label="complete code and live demo permalink" class="anchor before"><svg aria-hidden="true" focusable="false" height="16" version="1.1" viewBox="0 0 16 16" width="16"><path fill-rule="evenodd" d="M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z"></path></svg></a>Complete code and live demo</h2> <p>The complete code is available in <a href="https://github.com/muhimasri/react-editable-table">this repository</a>. If you liked the tutorial, please <a href="https://github.com/muhimasri/react-editable-table/stargazers">star the repository</a>, and feel free to request new features!</p> <p>Alternatively, you can try the code in the live demo below:</p> <div data-stackblitz="react-add-remove-rows"> <button>Run Code</button> </div> <h2 id="summary" style="position:relative;"><a href="#summary" aria-label="summary permalink" class="anchor before"><svg aria-hidden="true" focusable="false" height="16" version="1.1" viewBox="0 0 16 16" width="16"><path fill-rule="evenodd" d="M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z"></path></svg></a>Summary</h2> <p>In this tutorial, we learned how to add and remove rows from a React Table. We also learned how to add a checkbox input to select and remove multiple rows with a single click.</p> <p>Bye for now 👋</p> <style class="grvsc-styles"> .grvsc-container { overflow: auto; position: relative; -webkit-overflow-scrolling: touch; padding-top: 1rem; padding-top: var(--grvsc-padding-top, var(--grvsc-padding-v, 1rem)); padding-bottom: 1rem; padding-bottom: var(--grvsc-padding-bottom, var(--grvsc-padding-v, 1rem)); border-radius: 8px; border-radius: var(--grvsc-border-radius, 8px); font-feature-settings: normal; line-height: 1.4; } .grvsc-code { display: table; } .grvsc-line { display: table-row; box-sizing: border-box; width: 100%; position: relative; } .grvsc-line > * { position: relative; } .grvsc-gutter-pad { display: table-cell; padding-left: 0.75rem; padding-left: calc(var(--grvsc-padding-left, var(--grvsc-padding-h, 1.5rem)) / 2); } .grvsc-gutter { display: table-cell; -webkit-user-select: none; -moz-user-select: none; user-select: none; } .grvsc-gutter::before { content: attr(data-content); } .grvsc-source { display: table-cell; padding-left: 1.5rem; padding-left: var(--grvsc-padding-left, var(--grvsc-padding-h, 1.5rem)); padding-right: 1.5rem; padding-right: var(--grvsc-padding-right, var(--grvsc-padding-h, 1.5rem)); } .grvsc-source:empty::after { content: ' '; -webkit-user-select: none; -moz-user-select: none; user-select: none; } .grvsc-gutter + .grvsc-source { padding-left: 0.75rem; padding-left: calc(var(--grvsc-padding-left, var(--grvsc-padding-h, 1.5rem)) / 2); } /* Line transformer styles */ .grvsc-has-line-highlighting > .grvsc-code > .grvsc-line::before { content: ' '; position: absolute; width: 100%; } .grvsc-line-diff-add::before { background-color: var(--grvsc-line-diff-add-background-color, rgba(0, 255, 60, 0.2)); } .grvsc-line-diff-del::before { background-color: var(--grvsc-line-diff-del-background-color, rgba(255, 0, 20, 0.2)); } .grvsc-line-number { padding: 0 2px; text-align: right; opacity: 0.7; } .default-dark { background-color: #1E1E1E; color: #D4D4D4; } .default-dark .mtk1 { color: #D4D4D4; } .default-dark .mtk4 { color: #569CD6; } .default-dark .mtk12 { color: #9CDCFE; } .default-dark .mtk11 { color: #DCDCAA; } .default-dark .mtk10 { color: #4EC9B0; } .default-dark .mtk7 { color: #B5CEA8; } .default-dark .mtk8 { color: #CE9178; } .default-dark .mtk15 { color: #C586C0; } .default-dark .mtk17 { color: #808080; } .default-dark .mtk6 { color: #D7BA7D; } .default-dark .grvsc-line-highlighted::before { background-color: var(--grvsc-line-highlighted-background-color, rgba(255, 255, 255, 0.1)); box-shadow: inset var(--grvsc-line-highlighted-border-width, 4px) 0 0 0 var(--grvsc-line-highlighted-border-color, rgba(255, 255, 255, 0.5)); } </style><![CDATA[Creating an Editable and Dynamic React Table with TanStack]]>https://muhimasri.comreact-editable-tablehttps://muhimasri.comreact-editable-table<p>An editable table is an essential component in many applications in the real world. While plenty of excellent React libraries are feature-rich and easy to use for editing tables, most are paid services or need to be customized to fit business requirements.</p> <p>In this tutorial, we’ll go through all the steps to create a dynamic editable table using <a href="https://tanstack.com/table/v8">TanStack Table</a>, a Headless UI library for building robust tables and data grids in React. Since it’s just a utility, we have complete control over the UI structure and editable elements. We will be covering some of the basics, but having some basic knowledge is recommended.</p> <p>The aim is to design a flexible enough component where we can provide the data source with the columns schema, and the table can adapt accordingly.</p> <p>Let’s take a simplified example; if we have the data and column input below, the editable table will populate input text fields for all cells.</p> <pre class="grvsc-container default-dark" data-language="javascript" data-index="0"><code class="grvsc-code"><span class="grvsc-line"><span class="grvsc-source"><span class="mtk4">const</span><span class="mtk1"> </span><span class="mtk12">data</span><span class="mtk1"> = [</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> {</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">studentId:</span><span class="mtk1"> </span><span class="mtk7">1111</span><span class="mtk1">,</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">name:</span><span class="mtk1"> </span><span class="mtk8">&quot;Bahar Constantia&quot;</span><span class="mtk1">,</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">dateOfBirth:</span><span class="mtk1"> </span><span class="mtk8">&quot;1984-01-04&quot;</span><span class="mtk1">,</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">major:</span><span class="mtk1"> </span><span class="mtk8">&quot;Computer Science&quot;</span><span class="mtk1">,</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> },</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> {</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">studentId:</span><span class="mtk1"> </span><span class="mtk7">2222</span><span class="mtk1">,</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">name:</span><span class="mtk1"> </span><span class="mtk8">&quot;Harold Nona&quot;</span><span class="mtk1">,</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">dateOfBirth:</span><span class="mtk1"> </span><span class="mtk8">&quot;1961-05-10&quot;</span><span class="mtk1">,</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">major:</span><span class="mtk1"> </span><span class="mtk8">&quot;Communications&quot;</span><span class="mtk1">,</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> },</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> {</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">studentId:</span><span class="mtk1"> </span><span class="mtk7">3333</span><span class="mtk1">,</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">name:</span><span class="mtk1"> </span><span class="mtk8">&quot;Raginolf Arnulf&quot;</span><span class="mtk1">,</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">dateOfBirth:</span><span class="mtk1"> </span><span class="mtk8">&quot;1991-10-12&quot;</span><span class="mtk1">,</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">major:</span><span class="mtk1"> </span><span class="mtk8">&quot;Business&quot;</span><span class="mtk1">,</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> },</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> {</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">studentId:</span><span class="mtk1"> </span><span class="mtk7">4444</span><span class="mtk1">,</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">name:</span><span class="mtk1"> </span><span class="mtk8">&quot;Marvyn Wendi&quot;</span><span class="mtk1">,</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">dateOfBirth:</span><span class="mtk1"> </span><span class="mtk8">&quot;1978-09-24&quot;</span><span class="mtk1">,</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">major:</span><span class="mtk1"> </span><span class="mtk8">&quot;Psychology&quot;</span><span class="mtk1">,</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> },</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1">]</span></span></span></code></pre> <pre class="grvsc-container default-dark" data-language="javascript" data-index="1"><code class="grvsc-code"><span class="grvsc-line"><span class="grvsc-source"><span class="mtk4">const</span><span class="mtk1"> </span><span class="mtk12">columns</span><span class="mtk1"> = [</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> {</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">header:</span><span class="mtk1"> </span><span class="mtk8">&quot;Student ID&quot;</span><span class="mtk1">,</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">type:</span><span class="mtk1"> </span><span class="mtk8">&quot;text&quot;</span><span class="mtk1">,</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> },</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> {</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">header:</span><span class="mtk1"> </span><span class="mtk8">&quot;Full Name&quot;</span><span class="mtk1">,</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">type:</span><span class="mtk1"> </span><span class="mtk8">&quot;text&quot;</span><span class="mtk1">,</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> },</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> {</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">header:</span><span class="mtk1"> </span><span class="mtk8">&quot;Date Of Birth&quot;</span><span class="mtk1">,</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">type:</span><span class="mtk1"> </span><span class="mtk8">&quot;text&quot;</span><span class="mtk1">,</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> },</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> {</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">header:</span><span class="mtk1"> </span><span class="mtk8">&quot;Major&quot;</span><span class="mtk1">,</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">type:</span><span class="mtk1"> </span><span class="mtk8">&quot;text&quot;</span><span class="mtk1">,</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> },</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1">]</span></span></span></code></pre> <video width="720" height="400" autoplay loop muted playsinline preload="none"> <source src="/b54ab551018b415c2cf8f2bf5d9ced30/react-editable-table-text.mp4" type="video/mp4"> </video> <p>On the other hand, if some column types change from “text” to “date” or “number”, the table will respond dynamically and populate a date or number input field instead of a text field.</p> <pre class="grvsc-container grvsc-has-line-highlighting default-dark" data-language="javascript" data-index="2"><code class="grvsc-code"><span class="grvsc-line"><span class="grvsc-source"><span class="mtk4">const</span><span class="mtk1"> </span><span class="mtk12">columns</span><span class="mtk1"> = [</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> {</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">header:</span><span class="mtk1"> </span><span class="mtk8">&quot;Student ID&quot;</span><span class="mtk1">,</span></span></span> <span class="grvsc-line grvsc-line-highlighted"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">type:</span><span class="mtk1"> </span><span class="mtk8">&quot;number&quot;</span><span class="mtk1">,</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> },</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> {</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">header:</span><span class="mtk1"> </span><span class="mtk8">&quot;Full Name&quot;</span><span class="mtk1">,</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">type:</span><span class="mtk1"> </span><span class="mtk8">&quot;text&quot;</span><span class="mtk1">,</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> },</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> {</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">header:</span><span class="mtk1"> </span><span class="mtk8">&quot;Date Of Birth&quot;</span><span class="mtk1">,</span></span></span> <span class="grvsc-line grvsc-line-highlighted"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">type:</span><span class="mtk1"> </span><span class="mtk8">&quot;date&quot;</span><span class="mtk1">,</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> },</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> {</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">header:</span><span class="mtk1"> </span><span class="mtk8">&quot;Major&quot;</span><span class="mtk1">,</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">type:</span><span class="mtk1"> </span><span class="mtk8">&quot;select&quot;</span><span class="mtk1">,</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> },</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1">]</span></span></span></code></pre> <video width="720" height="400" autoplay loop muted playsinline preload="none"> <source src="/74f086d4d25f3476bf9d0c246b7eadff/react-editable-table-dynamic.mp4" type="video/mp4"> </video> <p>The above demo is how we want the table to look and behave at the end of the tutorial. So without further ado, let’s dive into the implementation🚀</p> <h2 id="creating-a-basic-table" style="position:relative;"><a href="#creating-a-basic-table" aria-label="creating a basic table permalink" class="anchor before"><svg aria-hidden="true" focusable="false" height="16" version="1.1" viewBox="0 0 16 16" width="16"><path fill-rule="evenodd" d="M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z"></path></svg></a>Creating a basic table</h2> <p>To get started with TanStack Table, we have to create a model type, default data, and a column definition, which is essential to creating a basic table and, eventually, dynamic editable cells. Please refer to the <a href="https://tanstack.com/table/v8/docs/guide/introduction">official documentation</a> for a more detailed understanding.</p> <pre class="grvsc-container default-dark" data-language="jsx" data-index="3"><code class="grvsc-code"><span class="grvsc-line"><span class="grvsc-source"><span class="mtk4">type</span><span class="mtk1"> </span><span class="mtk10">Student</span><span class="mtk1"> = {</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">studentId</span><span class="mtk1">: </span><span class="mtk10">number</span><span class="mtk1">;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">name</span><span class="mtk1">: </span><span class="mtk10">string</span><span class="mtk1">;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">dateOfBirth</span><span class="mtk1">: </span><span class="mtk10">string</span><span class="mtk1">;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">major</span><span class="mtk1">: </span><span class="mtk10">string</span><span class="mtk1">;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1">};</span></span></span> <span class="grvsc-line"><span class="grvsc-source"></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk4">const</span><span class="mtk1"> </span><span class="mtk12">defaultData</span><span class="mtk1">: </span><span class="mtk10">Student</span><span class="mtk1">[] = [</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> {</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">studentId:</span><span class="mtk1"> </span><span class="mtk7">1111</span><span class="mtk1">,</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">name:</span><span class="mtk1"> </span><span class="mtk8">&quot;Bahar Constantia&quot;</span><span class="mtk1">,</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">dateOfBirth:</span><span class="mtk1"> </span><span class="mtk8">&quot;1984-01-04&quot;</span><span class="mtk1">,</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">major:</span><span class="mtk1"> </span><span class="mtk8">&quot;Computer Science&quot;</span><span class="mtk1">,</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> },</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> {</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">studentId:</span><span class="mtk1"> </span><span class="mtk7">2222</span><span class="mtk1">,</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">name:</span><span class="mtk1"> </span><span class="mtk8">&quot;Harold Nona&quot;</span><span class="mtk1">,</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">dateOfBirth:</span><span class="mtk1"> </span><span class="mtk8">&quot;1961-05-10&quot;</span><span class="mtk1">,</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">major:</span><span class="mtk1"> </span><span class="mtk8">&quot;Communications&quot;</span><span class="mtk1">,</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> },</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> {</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">studentId:</span><span class="mtk1"> </span><span class="mtk7">3333</span><span class="mtk1">,</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">name:</span><span class="mtk1"> </span><span class="mtk8">&quot;Raginolf Arnulf&quot;</span><span class="mtk1">,</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">dateOfBirth:</span><span class="mtk1"> </span><span class="mtk8">&quot;1991-10-12&quot;</span><span class="mtk1">,</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">major:</span><span class="mtk1"> </span><span class="mtk8">&quot;Business&quot;</span><span class="mtk1">,</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> },</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> {</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">studentId:</span><span class="mtk1"> </span><span class="mtk7">4444</span><span class="mtk1">,</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">name:</span><span class="mtk1"> </span><span class="mtk8">&quot;Marvyn Wendi&quot;</span><span class="mtk1">,</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">dateOfBirth:</span><span class="mtk1"> </span><span class="mtk8">&quot;1978-09-24&quot;</span><span class="mtk1">,</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">major:</span><span class="mtk1"> </span><span class="mtk8">&quot;Psychology&quot;</span><span class="mtk1">,</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> },</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1">];</span></span></span> <span class="grvsc-line"><span class="grvsc-source"></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk4">const</span><span class="mtk1"> </span><span class="mtk12">columnHelper</span><span class="mtk1"> = </span><span class="mtk11">createColumnHelper</span><span class="mtk1">&lt;</span><span class="mtk10">Student</span><span class="mtk1">&gt;();</span></span></span> <span class="grvsc-line"><span class="grvsc-source"></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk4">const</span><span class="mtk1"> </span><span class="mtk12">columns</span><span class="mtk1"> = [</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">columnHelper</span><span class="mtk1">.</span><span class="mtk11">accessor</span><span class="mtk1">(</span><span class="mtk8">&quot;studentId&quot;</span><span class="mtk1">, {</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">header:</span><span class="mtk1"> </span><span class="mtk8">&quot;Student ID&quot;</span><span class="mtk1">,</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> }),</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">columnHelper</span><span class="mtk1">.</span><span class="mtk11">accessor</span><span class="mtk1">(</span><span class="mtk8">&quot;name&quot;</span><span class="mtk1">, {</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">header:</span><span class="mtk1"> </span><span class="mtk8">&quot;Full Name&quot;</span><span class="mtk1">,</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> }),</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">columnHelper</span><span class="mtk1">.</span><span class="mtk11">accessor</span><span class="mtk1">(</span><span class="mtk8">&quot;dateOfBirth&quot;</span><span class="mtk1">, {</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">header:</span><span class="mtk1"> </span><span class="mtk8">&quot;Date Of Birth&quot;</span><span class="mtk1">,</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> }),</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">columnHelper</span><span class="mtk1">.</span><span class="mtk11">accessor</span><span class="mtk1">(</span><span class="mtk8">&quot;major&quot;</span><span class="mtk1">, {</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">header:</span><span class="mtk1"> </span><span class="mtk8">&quot;Major&quot;</span><span class="mtk1">,</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> }),</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1">];</span></span></span></code></pre> <p><code>columns</code> can be a regular object, but using <code>createColumnHelper</code> provides a utility for creating different column definition types.</p> <p>Let’s add the rest of the code to get the basic TanStack table running.</p> <pre class="grvsc-container default-dark" data-language="jsx" data-index="4"><code class="grvsc-code"><span class="grvsc-line"><span class="grvsc-source"><span class="mtk15">import</span><span class="mtk1"> { </span><span class="mtk12">useState</span><span class="mtk1"> } </span><span class="mtk15">from</span><span class="mtk1"> </span><span class="mtk8">&quot;react&quot;</span><span class="mtk1">;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk15">import</span><span class="mtk1"> </span><span class="mtk8">&quot;./table.css&quot;</span><span class="mtk1">;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk15">import</span><span class="mtk1"> {</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">createColumnHelper</span><span class="mtk1">,</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">flexRender</span><span class="mtk1">,</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">getCoreRowModel</span><span class="mtk1">,</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">useReactTable</span><span class="mtk1">,</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1">} </span><span class="mtk15">from</span><span class="mtk1"> </span><span class="mtk8">&quot;@tanstack/react-table&quot;</span><span class="mtk1">;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk4">type</span><span class="mtk1"> </span><span class="mtk10">Student</span><span class="mtk1"> = {</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">studentId</span><span class="mtk1">: </span><span class="mtk10">number</span><span class="mtk1">;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">name</span><span class="mtk1">: </span><span class="mtk10">string</span><span class="mtk1">;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">dateOfBirth</span><span class="mtk1">: </span><span class="mtk10">string</span><span class="mtk1">;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">major</span><span class="mtk1">: </span><span class="mtk10">string</span><span class="mtk1">;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1">};</span></span></span> <span class="grvsc-line"><span class="grvsc-source"></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk4">const</span><span class="mtk1"> </span><span class="mtk12">defaultData</span><span class="mtk1">: </span><span class="mtk10">Student</span><span class="mtk1">[] = [</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> {</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">studentId:</span><span class="mtk1"> </span><span class="mtk7">1111</span><span class="mtk1">,</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">name:</span><span class="mtk1"> </span><span class="mtk8">&quot;Bahar Constantia&quot;</span><span class="mtk1">,</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">dateOfBirth:</span><span class="mtk1"> </span><span class="mtk8">&quot;1984-01-04&quot;</span><span class="mtk1">,</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">major:</span><span class="mtk1"> </span><span class="mtk8">&quot;Business&quot;</span><span class="mtk1">,</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> },</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> {</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">studentId:</span><span class="mtk1"> </span><span class="mtk7">2222</span><span class="mtk1">,</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">name:</span><span class="mtk1"> </span><span class="mtk8">&quot;Harold Nona&quot;</span><span class="mtk1">,</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">dateOfBirth:</span><span class="mtk1"> </span><span class="mtk8">&quot;1961-05-10&quot;</span><span class="mtk1">,</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">major:</span><span class="mtk1"> </span><span class="mtk8">&quot;Communications&quot;</span><span class="mtk1">,</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> },</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> {</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">studentId:</span><span class="mtk1"> </span><span class="mtk7">3333</span><span class="mtk1">,</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">name:</span><span class="mtk1"> </span><span class="mtk8">&quot;Raginolf Arnulf&quot;</span><span class="mtk1">,</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">dateOfBirth:</span><span class="mtk1"> </span><span class="mtk8">&quot;1991-10-12&quot;</span><span class="mtk1">,</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">major:</span><span class="mtk1"> </span><span class="mtk8">&quot;Business&quot;</span><span class="mtk1">,</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> },</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> {</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">studentId:</span><span class="mtk1"> </span><span class="mtk7">4444</span><span class="mtk1">,</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">name:</span><span class="mtk1"> </span><span class="mtk8">&quot;Marvyn Wendi&quot;</span><span class="mtk1">,</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">dateOfBirth:</span><span class="mtk1"> </span><span class="mtk8">&quot;1978-09-24&quot;</span><span class="mtk1">,</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">major:</span><span class="mtk1"> </span><span class="mtk8">&quot;Business&quot;</span><span class="mtk1">,</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> },</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1">];</span></span></span> <span class="grvsc-line"><span class="grvsc-source"></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk4">const</span><span class="mtk1"> </span><span class="mtk12">columnHelper</span><span class="mtk1"> = </span><span class="mtk11">createColumnHelper</span><span class="mtk1">&lt;</span><span class="mtk10">Student</span><span class="mtk1">&gt;();</span></span></span> <span class="grvsc-line"><span class="grvsc-source"></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk4">const</span><span class="mtk1"> </span><span class="mtk12">columns</span><span class="mtk1"> = [</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">columnHelper</span><span class="mtk1">.</span><span class="mtk11">accessor</span><span class="mtk1">(</span><span class="mtk8">&quot;studentId&quot;</span><span class="mtk1">, {</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">header:</span><span class="mtk1"> </span><span class="mtk8">&quot;Student ID&quot;</span><span class="mtk1">,</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> }),</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">columnHelper</span><span class="mtk1">.</span><span class="mtk11">accessor</span><span class="mtk1">(</span><span class="mtk8">&quot;name&quot;</span><span class="mtk1">, {</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">header:</span><span class="mtk1"> </span><span class="mtk8">&quot;Full Name&quot;</span><span class="mtk1">,</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> }),</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">columnHelper</span><span class="mtk1">.</span><span class="mtk11">accessor</span><span class="mtk1">(</span><span class="mtk8">&quot;dateOfBirth&quot;</span><span class="mtk1">, {</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">header:</span><span class="mtk1"> </span><span class="mtk8">&quot;Date Of Birth&quot;</span><span class="mtk1">,</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> }),</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">columnHelper</span><span class="mtk1">.</span><span class="mtk11">accessor</span><span class="mtk1">(</span><span class="mtk8">&quot;major&quot;</span><span class="mtk1">, {</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">header:</span><span class="mtk1"> </span><span class="mtk8">&quot;Major&quot;</span><span class="mtk1">,</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> }),</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1">];</span></span></span> <span class="grvsc-line"><span class="grvsc-source"></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk15">export</span><span class="mtk1"> </span><span class="mtk4">const</span><span class="mtk1"> </span><span class="mtk11">Table</span><span class="mtk1"> = () </span><span class="mtk4">=&gt;</span><span class="mtk1"> {</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk4">const</span><span class="mtk1"> [</span><span class="mtk12">data</span><span class="mtk1">, </span><span class="mtk12">setData</span><span class="mtk1">] = </span><span class="mtk11">useState</span><span class="mtk1">(() </span><span class="mtk4">=&gt;</span><span class="mtk1"> [...</span><span class="mtk12">defaultData</span><span class="mtk1">]);</span></span></span> <span class="grvsc-line"><span class="grvsc-source"></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk4">const</span><span class="mtk1"> </span><span class="mtk12">table</span><span class="mtk1"> = </span><span class="mtk11">useReactTable</span><span class="mtk1">({</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">data</span><span class="mtk1">,</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">columns</span><span class="mtk1">,</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">getCoreRowModel:</span><span class="mtk1"> </span><span class="mtk11">getCoreRowModel</span><span class="mtk1">(),</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> });</span></span></span> <span class="grvsc-line"><span class="grvsc-source"></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk15">return</span><span class="mtk1"> (</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk17">&lt;</span><span class="mtk4">table</span><span class="mtk17">&gt;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk17">&lt;</span><span class="mtk4">thead</span><span class="mtk17">&gt;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk4">{</span><span class="mtk12">table</span><span class="mtk1">.</span><span class="mtk11">getHeaderGroups</span><span class="mtk1">().</span><span class="mtk11">map</span><span class="mtk1">((</span><span class="mtk12">headerGroup</span><span class="mtk1">) </span><span class="mtk4">=&gt;</span><span class="mtk1"> (</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk17">&lt;</span><span class="mtk4">tr</span><span class="mtk1"> </span><span class="mtk12">key</span><span class="mtk1">=</span><span class="mtk4">{</span><span class="mtk12">headerGroup</span><span class="mtk1">.</span><span class="mtk12">id</span><span class="mtk4">}</span><span class="mtk17">&gt;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk4">{</span><span class="mtk12">headerGroup</span><span class="mtk1">.</span><span class="mtk12">headers</span><span class="mtk1">.</span><span class="mtk11">map</span><span class="mtk1">((</span><span class="mtk12">header</span><span class="mtk1">) </span><span class="mtk4">=&gt;</span><span class="mtk1"> (</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk17">&lt;</span><span class="mtk4">th</span><span class="mtk1"> </span><span class="mtk12">key</span><span class="mtk1">=</span><span class="mtk4">{</span><span class="mtk12">header</span><span class="mtk1">.</span><span class="mtk12">id</span><span class="mtk4">}</span><span class="mtk17">&gt;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk4">{</span><span class="mtk12">header</span><span class="mtk1">.</span><span class="mtk12">isPlaceholder</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> ? </span><span class="mtk4">null</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> : </span><span class="mtk11">flexRender</span><span class="mtk1">(</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">header</span><span class="mtk1">.</span><span class="mtk12">column</span><span class="mtk1">.</span><span class="mtk12">columnDef</span><span class="mtk1">.</span><span class="mtk12">header</span><span class="mtk1">,</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">header</span><span class="mtk1">.</span><span class="mtk11">getContext</span><span class="mtk1">()</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> )</span><span class="mtk4">}</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk17">&lt;/</span><span class="mtk4">th</span><span class="mtk17">&gt;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> ))</span><span class="mtk4">}</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk17">&lt;/</span><span class="mtk4">tr</span><span class="mtk17">&gt;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> ))</span><span class="mtk4">}</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk17">&lt;/</span><span class="mtk4">thead</span><span class="mtk17">&gt;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk17">&lt;</span><span class="mtk4">tbody</span><span class="mtk17">&gt;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk4">{</span><span class="mtk12">table</span><span class="mtk1">.</span><span class="mtk11">getRowModel</span><span class="mtk1">().</span><span class="mtk12">rows</span><span class="mtk1">.</span><span class="mtk11">map</span><span class="mtk1">((</span><span class="mtk12">row</span><span class="mtk1">) </span><span class="mtk4">=&gt;</span><span class="mtk1"> (</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk17">&lt;</span><span class="mtk4">tr</span><span class="mtk1"> </span><span class="mtk12">key</span><span class="mtk1">=</span><span class="mtk4">{</span><span class="mtk12">row</span><span class="mtk1">.</span><span class="mtk12">id</span><span class="mtk4">}</span><span class="mtk17">&gt;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk4">{</span><span class="mtk12">row</span><span class="mtk1">.</span><span class="mtk11">getVisibleCells</span><span class="mtk1">().</span><span class="mtk11">map</span><span class="mtk1">((</span><span class="mtk12">cell</span><span class="mtk1">) </span><span class="mtk4">=&gt;</span><span class="mtk1"> (</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk17">&lt;</span><span class="mtk4">td</span><span class="mtk1"> </span><span class="mtk12">key</span><span class="mtk1">=</span><span class="mtk4">{</span><span class="mtk12">cell</span><span class="mtk1">.</span><span class="mtk12">id</span><span class="mtk4">}</span><span class="mtk17">&gt;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk4">{</span><span class="mtk11">flexRender</span><span class="mtk1">(</span><span class="mtk12">cell</span><span class="mtk1">.</span><span class="mtk12">column</span><span class="mtk1">.</span><span class="mtk12">columnDef</span><span class="mtk1">.</span><span class="mtk12">cell</span><span class="mtk1">, </span><span class="mtk12">cell</span><span class="mtk1">.</span><span class="mtk11">getContext</span><span class="mtk1">())</span><span class="mtk4">}</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk17">&lt;/</span><span class="mtk4">td</span><span class="mtk17">&gt;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> ))</span><span class="mtk4">}</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk17">&lt;/</span><span class="mtk4">tr</span><span class="mtk17">&gt;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> ))</span><span class="mtk4">}</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk17">&lt;/</span><span class="mtk4">tbody</span><span class="mtk17">&gt;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk17">&lt;/</span><span class="mtk4">table</span><span class="mtk17">&gt;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> );</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1">};</span></span></span></code></pre> <div id="ReactEditableTableOne" data-code data-height="220px"></div> <p>In addition, we added some styling to the table - margins, alignments, and borders.</p> <pre class="grvsc-container default-dark" data-language="css" data-index="5"><code class="grvsc-code"><span class="grvsc-line"><span class="grvsc-source"><span class="mtk6">table</span><span class="mtk1"> {</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">font-family</span><span class="mtk1">: </span><span class="mtk8">sans-serif</span><span class="mtk1">;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">border-collapse</span><span class="mtk1">: </span><span class="mtk8">collapse</span><span class="mtk1">;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">border</span><span class="mtk1">: </span><span class="mtk7">1px</span><span class="mtk1"> </span><span class="mtk8">solid</span><span class="mtk1"> </span><span class="mtk8">#ccc</span><span class="mtk1">;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">margin</span><span class="mtk1">: </span><span class="mtk7">25px</span><span class="mtk1">;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">background-color</span><span class="mtk1">: </span><span class="mtk8">#fff</span><span class="mtk1">;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1">}</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk6">tr</span><span class="mtk1"> {</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">border-bottom</span><span class="mtk1">: </span><span class="mtk7">1px</span><span class="mtk1"> </span><span class="mtk8">solid</span><span class="mtk1"> </span><span class="mtk8">#ccc</span><span class="mtk1">;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1">}</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk6">th</span><span class="mtk1">,</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk6">td</span><span class="mtk1"> {</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">text-align</span><span class="mtk1">: </span><span class="mtk8">left</span><span class="mtk1">;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">padding</span><span class="mtk1">: </span><span class="mtk7">8px</span><span class="mtk1"> </span><span class="mtk7">10px</span><span class="mtk1">;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1">}</span></span></span></code></pre> <h2 id="adding-editable-cells" style="position:relative;"><a href="#adding-editable-cells" aria-label="adding editable cells permalink" class="anchor before"><svg aria-hidden="true" focusable="false" height="16" version="1.1" viewBox="0 0 16 16" width="16"><path fill-rule="evenodd" d="M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z"></path></svg></a>Adding editable cells</h2> <p>We’ll start with the most straightforward approach by replacing cells with input text fields, and we’ll make sure to structure the code in a way that will scale as we progress to the other sections.</p> <p>Let’s create a new Table Cell component with a state and an input field.</p> <pre class="grvsc-container default-dark" data-language="jsx" data-index="6"><code class="grvsc-code"><span class="grvsc-line"><span class="grvsc-source"><span class="mtk4">const</span><span class="mtk1"> </span><span class="mtk11">TableCell</span><span class="mtk1"> = () </span><span class="mtk4">=&gt;</span><span class="mtk1"> {</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk4">const</span><span class="mtk1"> [</span><span class="mtk12">value</span><span class="mtk1">, </span><span class="mtk12">setValue</span><span class="mtk1">] = </span><span class="mtk11">useState</span><span class="mtk1">(</span><span class="mtk8">&quot;&quot;</span><span class="mtk1">)</span></span></span> <span class="grvsc-line"><span class="grvsc-source"></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk15">return</span><span class="mtk1"> </span><span class="mtk17">&lt;</span><span class="mtk4">input</span><span class="mtk1"> </span><span class="mtk12">value</span><span class="mtk1">=</span><span class="mtk4">{</span><span class="mtk12">value</span><span class="mtk4">}</span><span class="mtk1"> </span><span class="mtk12">onChange</span><span class="mtk1">=</span><span class="mtk4">{</span><span class="mtk12">e</span><span class="mtk1"> </span><span class="mtk4">=&gt;</span><span class="mtk1"> </span><span class="mtk11">setValue</span><span class="mtk1">(</span><span class="mtk12">e</span><span class="mtk1">.</span><span class="mtk12">target</span><span class="mtk1">.</span><span class="mtk12">value</span><span class="mtk1">)</span><span class="mtk4">}</span><span class="mtk1"> </span><span class="mtk17">/&gt;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1">}</span></span></span></code></pre> <p>The column definition provides a <code>cell</code> prop to render any element we need instead of the default text value. This way, we can add the new <code>TableCell</code> component in all columns.</p> <pre class="grvsc-container grvsc-has-line-highlighting default-dark" data-language="jsx" data-index="7"><code class="grvsc-code"><span class="grvsc-line"><span class="grvsc-source"><span class="mtk4">const</span><span class="mtk1"> </span><span class="mtk12">columns</span><span class="mtk1"> = [</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">columnHelper</span><span class="mtk1">.</span><span class="mtk11">accessor</span><span class="mtk1">(</span><span class="mtk8">&quot;studentId&quot;</span><span class="mtk1">, {</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">header:</span><span class="mtk1"> </span><span class="mtk8">&quot;Student ID&quot;</span><span class="mtk1">,</span></span></span> <span class="grvsc-line grvsc-line-highlighted"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">cell:</span><span class="mtk1"> </span><span class="mtk12">TableCell</span><span class="mtk1">,</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> }),</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">columnHelper</span><span class="mtk1">.</span><span class="mtk11">accessor</span><span class="mtk1">(</span><span class="mtk8">&quot;name&quot;</span><span class="mtk1">, {</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">header:</span><span class="mtk1"> </span><span class="mtk8">&quot;Full Name&quot;</span><span class="mtk1">,</span></span></span> <span class="grvsc-line grvsc-line-highlighted"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">cell:</span><span class="mtk1"> </span><span class="mtk12">TableCell</span><span class="mtk1">,</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> }),</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">columnHelper</span><span class="mtk1">.</span><span class="mtk11">accessor</span><span class="mtk1">(</span><span class="mtk8">&quot;dateOfBirth&quot;</span><span class="mtk1">, {</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">header:</span><span class="mtk1"> </span><span class="mtk8">&quot;Date Of Birth&quot;</span><span class="mtk1">,</span></span></span> <span class="grvsc-line grvsc-line-highlighted"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">cell:</span><span class="mtk1"> </span><span class="mtk12">TableCell</span><span class="mtk1">,</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> }),</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">columnHelper</span><span class="mtk1">.</span><span class="mtk11">accessor</span><span class="mtk1">(</span><span class="mtk8">&quot;major&quot;</span><span class="mtk1">, {</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">header:</span><span class="mtk1"> </span><span class="mtk8">&quot;Major&quot;</span><span class="mtk1">,</span></span></span> <span class="grvsc-line grvsc-line-highlighted"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">cell:</span><span class="mtk1"> </span><span class="mtk12">TableCell</span><span class="mtk1">,</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> }),</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1">]</span></span></span></code></pre> <p>When the <code>cell</code> prop renders the component, it will provide all the information we need to access the table and update the value. But before going there, we need to create a new function in the main <code>Table</code> component to update the data based on the modified row and column.</p> <p>The function will have three parameters - row index, column id, and value.</p> <pre class="grvsc-container grvsc-has-line-highlighting default-dark" data-language="jsx" data-index="8"><code class="grvsc-code"><span class="grvsc-line"><span class="grvsc-source"><span class="mtk15">export</span><span class="mtk1"> </span><span class="mtk4">const</span><span class="mtk1"> </span><span class="mtk11">Table</span><span class="mtk1"> = () </span><span class="mtk4">=&gt;</span><span class="mtk1"> {</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk4">const</span><span class="mtk1"> [</span><span class="mtk12">data</span><span class="mtk1">, </span><span class="mtk12">setData</span><span class="mtk1">] = </span><span class="mtk11">useState</span><span class="mtk1">(() </span><span class="mtk4">=&gt;</span><span class="mtk1"> [...</span><span class="mtk12">defaultData</span><span class="mtk1">]);</span></span></span> <span class="grvsc-line"><span class="grvsc-source"></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk4">const</span><span class="mtk1"> </span><span class="mtk12">table</span><span class="mtk1"> = </span><span class="mtk11">useReactTable</span><span class="mtk1">({</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">data</span><span class="mtk1">,</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">columns</span><span class="mtk1">,</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">getCoreRowModel:</span><span class="mtk1"> </span><span class="mtk11">getCoreRowModel</span><span class="mtk1">(),</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">meta:</span><span class="mtk1"> {</span></span></span> <span class="grvsc-line grvsc-line-highlighted"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk11">updateData</span><span class="mtk12">:</span><span class="mtk1"> (</span><span class="mtk12">rowIndex</span><span class="mtk1">: </span><span class="mtk10">number</span><span class="mtk1">, </span><span class="mtk12">columnId</span><span class="mtk1">: </span><span class="mtk10">string</span><span class="mtk1">, </span><span class="mtk12">value</span><span class="mtk1">: </span><span class="mtk10">string</span><span class="mtk1">) </span><span class="mtk4">=&gt;</span><span class="mtk1"> {</span></span></span> <span class="grvsc-line grvsc-line-highlighted"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk11">setData</span><span class="mtk1">((</span><span class="mtk12">old</span><span class="mtk1">) </span><span class="mtk4">=&gt;</span></span></span> <span class="grvsc-line grvsc-line-highlighted"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">old</span><span class="mtk1">.</span><span class="mtk11">map</span><span class="mtk1">((</span><span class="mtk12">row</span><span class="mtk1">, </span><span class="mtk12">index</span><span class="mtk1">) </span><span class="mtk4">=&gt;</span><span class="mtk1"> {</span></span></span> <span class="grvsc-line grvsc-line-highlighted"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk15">if</span><span class="mtk1"> (</span><span class="mtk12">index</span><span class="mtk1"> === </span><span class="mtk12">rowIndex</span><span class="mtk1">) {</span></span></span> <span class="grvsc-line grvsc-line-highlighted"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk15">return</span><span class="mtk1"> {</span></span></span> <span class="grvsc-line grvsc-line-highlighted"><span class="grvsc-source"><span class="mtk1"> ...</span><span class="mtk12">old</span><span class="mtk1">[</span><span class="mtk12">rowIndex</span><span class="mtk1">],</span></span></span> <span class="grvsc-line grvsc-line-highlighted"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">[columnId]:</span><span class="mtk1"> </span><span class="mtk12">value</span><span class="mtk1">,</span></span></span> <span class="grvsc-line grvsc-line-highlighted"><span class="grvsc-source"><span class="mtk1"> };</span></span></span> <span class="grvsc-line grvsc-line-highlighted"><span class="grvsc-source"><span class="mtk1"> }</span></span></span> <span class="grvsc-line grvsc-line-highlighted"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk15">return</span><span class="mtk1"> </span><span class="mtk12">row</span><span class="mtk1">;</span></span></span> <span class="grvsc-line grvsc-line-highlighted"><span class="grvsc-source"><span class="mtk1"> })</span></span></span> <span class="grvsc-line grvsc-line-highlighted"><span class="grvsc-source"><span class="mtk1"> );</span></span></span> <span class="grvsc-line grvsc-line-highlighted"><span class="grvsc-source"><span class="mtk1"> },</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> },</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> });</span></span></span> <span class="grvsc-line"><span class="grvsc-source"></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk15">return</span><span class="mtk1"> (...);</span></span></span></code></pre> <p>Notice that we added the function in a <code>meta</code> object, which is part of the <code>useReactTable</code> options and can be accessed anywhere the table is available via <code>table.options.meta</code>.</p> <p>Now that we have all the functions and props we need, let’s complete the <code>TableCell</code> component to trigger the update function.</p> <pre class="grvsc-container grvsc-has-line-highlighting default-dark" data-language="jsx" data-index="9"><code class="grvsc-code"><span class="grvsc-line"><span class="grvsc-source"><span class="mtk4">const</span><span class="mtk1"> </span><span class="mtk11">TableCell</span><span class="mtk1"> = ({ </span><span class="mtk12">getValue</span><span class="mtk1">, </span><span class="mtk12">row</span><span class="mtk1">, </span><span class="mtk12">column</span><span class="mtk1">, </span><span class="mtk12">table</span><span class="mtk1"> }) </span><span class="mtk4">=&gt;</span><span class="mtk1"> {</span></span></span> <span class="grvsc-line grvsc-line-highlighted"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk4">const</span><span class="mtk1"> </span><span class="mtk12">initialValue</span><span class="mtk1"> = </span><span class="mtk11">getValue</span><span class="mtk1">()</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk4">const</span><span class="mtk1"> [</span><span class="mtk12">value</span><span class="mtk1">, </span><span class="mtk12">setValue</span><span class="mtk1">] = </span><span class="mtk11">useState</span><span class="mtk1">(</span><span class="mtk12">initialValue</span><span class="mtk1">)</span></span></span> <span class="grvsc-line"><span class="grvsc-source"></span></span> <span class="grvsc-line grvsc-line-highlighted"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk11">useEffect</span><span class="mtk1">(() </span><span class="mtk4">=&gt;</span><span class="mtk1"> {</span></span></span> <span class="grvsc-line grvsc-line-highlighted"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk11">setValue</span><span class="mtk1">(</span><span class="mtk12">initialValue</span><span class="mtk1">)</span></span></span> <span class="grvsc-line grvsc-line-highlighted"><span class="grvsc-source"><span class="mtk1"> }, [</span><span class="mtk12">initialValue</span><span class="mtk1">])</span></span></span> <span class="grvsc-line"><span class="grvsc-source"></span></span> <span class="grvsc-line grvsc-line-highlighted"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk4">const</span><span class="mtk1"> </span><span class="mtk11">onBlur</span><span class="mtk1"> = () </span><span class="mtk4">=&gt;</span><span class="mtk1"> {</span></span></span> <span class="grvsc-line grvsc-line-highlighted"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">table</span><span class="mtk1">.</span><span class="mtk12">options</span><span class="mtk1">.</span><span class="mtk12">meta</span><span class="mtk1">?.</span><span class="mtk11">updateData</span><span class="mtk1">(</span><span class="mtk12">row</span><span class="mtk1">.</span><span class="mtk12">index</span><span class="mtk1">, </span><span class="mtk12">column</span><span class="mtk1">.</span><span class="mtk12">id</span><span class="mtk1">, </span><span class="mtk12">value</span><span class="mtk1">)</span></span></span> <span class="grvsc-line grvsc-line-highlighted"><span class="grvsc-source"><span class="mtk1"> }</span></span></span> <span class="grvsc-line"><span class="grvsc-source"></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk15">return</span><span class="mtk1"> (</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk17">&lt;</span><span class="mtk4">input</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">value</span><span class="mtk1">=</span><span class="mtk4">{</span><span class="mtk12">value</span><span class="mtk4">}</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">onChange</span><span class="mtk1">=</span><span class="mtk4">{</span><span class="mtk12">e</span><span class="mtk1"> </span><span class="mtk4">=&gt;</span><span class="mtk1"> </span><span class="mtk11">setValue</span><span class="mtk1">(</span><span class="mtk12">e</span><span class="mtk1">.</span><span class="mtk12">target</span><span class="mtk1">.</span><span class="mtk12">value</span><span class="mtk1">)</span><span class="mtk4">}</span></span></span> <span class="grvsc-line grvsc-line-highlighted"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">onBlur</span><span class="mtk1">=</span><span class="mtk4">{</span><span class="mtk12">onBlur</span><span class="mtk4">}</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk17">/&gt;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> )</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1">}</span></span></span></code></pre> <p>We are using the <code>onBlur</code> to trigger the <code>updateData</code> function, and as we can see, it’s now available in <code>table.options.meta</code>. In addition, we’re passing a default value to the input field using <code>getValue</code>, which is available for us from the props.</p> <p>Now, let’s put everything together and look at what we have so far.</p> <pre class="grvsc-container default-dark" data-language="jsx" data-index="10"><code class="grvsc-code"><span class="grvsc-line"><span class="grvsc-source"><span class="mtk15">import</span><span class="mtk1"> { </span><span class="mtk12">useState</span><span class="mtk1">, </span><span class="mtk12">useEffect</span><span class="mtk1"> } </span><span class="mtk15">from</span><span class="mtk1"> </span><span class="mtk8">&quot;react&quot;</span><span class="mtk1">;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk15">import</span><span class="mtk1"> </span><span class="mtk8">&quot;./table.css&quot;</span><span class="mtk1">;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk15">import</span><span class="mtk1"> {</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">createColumnHelper</span><span class="mtk1">,</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">flexRender</span><span class="mtk1">,</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">getCoreRowModel</span><span class="mtk1">,</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">useReactTable</span><span class="mtk1">,</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1">} </span><span class="mtk15">from</span><span class="mtk1"> </span><span class="mtk8">&quot;@tanstack/react-table&quot;</span><span class="mtk1">;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk4">type</span><span class="mtk1"> </span><span class="mtk10">Student</span><span class="mtk1"> = {</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">studentId</span><span class="mtk1">: </span><span class="mtk10">number</span><span class="mtk1">;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">name</span><span class="mtk1">: </span><span class="mtk10">string</span><span class="mtk1">;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">dateOfBirth</span><span class="mtk1">: </span><span class="mtk10">string</span><span class="mtk1">;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">major</span><span class="mtk1">: </span><span class="mtk10">string</span><span class="mtk1">;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1">};</span></span></span> <span class="grvsc-line"><span class="grvsc-source"></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk4">const</span><span class="mtk1"> </span><span class="mtk12">defaultData</span><span class="mtk1">: </span><span class="mtk10">Student</span><span class="mtk1">[] = [</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> {</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">studentId:</span><span class="mtk1"> </span><span class="mtk7">1111</span><span class="mtk1">,</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">name:</span><span class="mtk1"> </span><span class="mtk8">&quot;Bahar Constantia&quot;</span><span class="mtk1">,</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">dateOfBirth:</span><span class="mtk1"> </span><span class="mtk8">&quot;1984-01-04&quot;</span><span class="mtk1">,</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">major:</span><span class="mtk1"> </span><span class="mtk8">&quot;Business&quot;</span><span class="mtk1">,</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> },</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> {</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">studentId:</span><span class="mtk1"> </span><span class="mtk7">2222</span><span class="mtk1">,</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">name:</span><span class="mtk1"> </span><span class="mtk8">&quot;Harold Nona&quot;</span><span class="mtk1">,</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">dateOfBirth:</span><span class="mtk1"> </span><span class="mtk8">&quot;1961-05-10&quot;</span><span class="mtk1">,</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">major:</span><span class="mtk1"> </span><span class="mtk8">&quot;Communications&quot;</span><span class="mtk1">,</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> },</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> {</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">studentId:</span><span class="mtk1"> </span><span class="mtk7">3333</span><span class="mtk1">,</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">name:</span><span class="mtk1"> </span><span class="mtk8">&quot;Raginolf Arnulf&quot;</span><span class="mtk1">,</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">dateOfBirth:</span><span class="mtk1"> </span><span class="mtk8">&quot;1991-10-12&quot;</span><span class="mtk1">,</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">major:</span><span class="mtk1"> </span><span class="mtk8">&quot;Business&quot;</span><span class="mtk1">,</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> },</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> {</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">studentId:</span><span class="mtk1"> </span><span class="mtk7">4444</span><span class="mtk1">,</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">name:</span><span class="mtk1"> </span><span class="mtk8">&quot;Marvyn Wendi&quot;</span><span class="mtk1">,</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">dateOfBirth:</span><span class="mtk1"> </span><span class="mtk8">&quot;1978-09-24&quot;</span><span class="mtk1">,</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">major:</span><span class="mtk1"> </span><span class="mtk8">&quot;Business&quot;</span><span class="mtk1">,</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> },</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1">];</span></span></span> <span class="grvsc-line"><span class="grvsc-source"></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk4">const</span><span class="mtk1"> </span><span class="mtk11">TableCell</span><span class="mtk1"> = ({ </span><span class="mtk12">getValue</span><span class="mtk1">, </span><span class="mtk12">row</span><span class="mtk1">, </span><span class="mtk12">column</span><span class="mtk1">, </span><span class="mtk12">table</span><span class="mtk1"> }) </span><span class="mtk4">=&gt;</span><span class="mtk1"> {</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk4">const</span><span class="mtk1"> </span><span class="mtk12">initialValue</span><span class="mtk1"> = </span><span class="mtk11">getValue</span><span class="mtk1">();</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk4">const</span><span class="mtk1"> [</span><span class="mtk12">value</span><span class="mtk1">, </span><span class="mtk12">setValue</span><span class="mtk1">] = </span><span class="mtk11">useState</span><span class="mtk1">(</span><span class="mtk12">initialValue</span><span class="mtk1">);</span></span></span> <span class="grvsc-line"><span class="grvsc-source"></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk11">useEffect</span><span class="mtk1">(() </span><span class="mtk4">=&gt;</span><span class="mtk1"> {</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk11">setValue</span><span class="mtk1">(</span><span class="mtk12">initialValue</span><span class="mtk1">);</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> }, [</span><span class="mtk12">initialValue</span><span class="mtk1">]);</span></span></span> <span class="grvsc-line"><span class="grvsc-source"></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk4">const</span><span class="mtk1"> </span><span class="mtk11">onBlur</span><span class="mtk1"> = () </span><span class="mtk4">=&gt;</span><span class="mtk1"> {</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">table</span><span class="mtk1">.</span><span class="mtk12">options</span><span class="mtk1">.</span><span class="mtk12">meta</span><span class="mtk1">?.</span><span class="mtk11">updateData</span><span class="mtk1">(</span><span class="mtk12">row</span><span class="mtk1">.</span><span class="mtk12">index</span><span class="mtk1">, </span><span class="mtk12">column</span><span class="mtk1">.</span><span class="mtk12">id</span><span class="mtk1">, </span><span class="mtk12">value</span><span class="mtk1">);</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> };</span></span></span> <span class="grvsc-line"><span class="grvsc-source"></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk15">return</span><span class="mtk1"> (</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk17">&lt;</span><span class="mtk4">input</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">value</span><span class="mtk1">=</span><span class="mtk4">{</span><span class="mtk12">value</span><span class="mtk4">}</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">onChange</span><span class="mtk1">=</span><span class="mtk4">{</span><span class="mtk1">(</span><span class="mtk12">e</span><span class="mtk1">) </span><span class="mtk4">=&gt;</span><span class="mtk1"> </span><span class="mtk11">setValue</span><span class="mtk1">(</span><span class="mtk12">e</span><span class="mtk1">.</span><span class="mtk12">target</span><span class="mtk1">.</span><span class="mtk12">value</span><span class="mtk1">)</span><span class="mtk4">}</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">onBlur</span><span class="mtk1">=</span><span class="mtk4">{</span><span class="mtk12">onBlur</span><span class="mtk4">}</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk17">/&gt;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> );</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1">};</span></span></span> <span class="grvsc-line"><span class="grvsc-source"></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk4">const</span><span class="mtk1"> </span><span class="mtk12">columnHelper</span><span class="mtk1"> = </span><span class="mtk11">createColumnHelper</span><span class="mtk1">&lt;</span><span class="mtk10">Student</span><span class="mtk1">&gt;();</span></span></span> <span class="grvsc-line"><span class="grvsc-source"></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk4">const</span><span class="mtk1"> </span><span class="mtk12">columns</span><span class="mtk1"> = [</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">columnHelper</span><span class="mtk1">.</span><span class="mtk11">accessor</span><span class="mtk1">(</span><span class="mtk8">&quot;studentId&quot;</span><span class="mtk1">, {</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">header:</span><span class="mtk1"> </span><span class="mtk8">&quot;Student ID&quot;</span><span class="mtk1">,</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">cell:</span><span class="mtk1"> </span><span class="mtk12">TableCell</span><span class="mtk1">,</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> }),</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">columnHelper</span><span class="mtk1">.</span><span class="mtk11">accessor</span><span class="mtk1">(</span><span class="mtk8">&quot;name&quot;</span><span class="mtk1">, {</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">header:</span><span class="mtk1"> </span><span class="mtk8">&quot;Full Name&quot;</span><span class="mtk1">,</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">cell:</span><span class="mtk1"> </span><span class="mtk12">TableCell</span><span class="mtk1">,</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> }),</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">columnHelper</span><span class="mtk1">.</span><span class="mtk11">accessor</span><span class="mtk1">(</span><span class="mtk8">&quot;dateOfBirth&quot;</span><span class="mtk1">, {</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">header:</span><span class="mtk1"> </span><span class="mtk8">&quot;Date Of Birth&quot;</span><span class="mtk1">,</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">cell:</span><span class="mtk1"> </span><span class="mtk12">TableCell</span><span class="mtk1">,</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> }),</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">columnHelper</span><span class="mtk1">.</span><span class="mtk11">accessor</span><span class="mtk1">(</span><span class="mtk8">&quot;major&quot;</span><span class="mtk1">, {</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">header:</span><span class="mtk1"> </span><span class="mtk8">&quot;Major&quot;</span><span class="mtk1">,</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">cell:</span><span class="mtk1"> </span><span class="mtk12">TableCell</span><span class="mtk1">,</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> }),</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1">];</span></span></span> <span class="grvsc-line"><span class="grvsc-source"></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk15">export</span><span class="mtk1"> </span><span class="mtk4">const</span><span class="mtk1"> </span><span class="mtk11">Table</span><span class="mtk1"> = () </span><span class="mtk4">=&gt;</span><span class="mtk1"> {</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk4">const</span><span class="mtk1"> [</span><span class="mtk12">data</span><span class="mtk1">, </span><span class="mtk12">setData</span><span class="mtk1">] = </span><span class="mtk11">useState</span><span class="mtk1">(() </span><span class="mtk4">=&gt;</span><span class="mtk1"> [...</span><span class="mtk12">defaultData</span><span class="mtk1">]);</span></span></span> <span class="grvsc-line"><span class="grvsc-source"></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk4">const</span><span class="mtk1"> </span><span class="mtk12">table</span><span class="mtk1"> = </span><span class="mtk11">useReactTable</span><span class="mtk1">({</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">data</span><span class="mtk1">,</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">columns</span><span class="mtk1">,</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">getCoreRowModel:</span><span class="mtk1"> </span><span class="mtk11">getCoreRowModel</span><span class="mtk1">(),</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">meta:</span><span class="mtk1"> {</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk11">updateData</span><span class="mtk12">:</span><span class="mtk1"> (</span><span class="mtk12">rowIndex</span><span class="mtk1">: </span><span class="mtk10">number</span><span class="mtk1">, </span><span class="mtk12">columnId</span><span class="mtk1">: </span><span class="mtk10">string</span><span class="mtk1">, </span><span class="mtk12">value</span><span class="mtk1">: </span><span class="mtk10">string</span><span class="mtk1">) </span><span class="mtk4">=&gt;</span><span class="mtk1"> {</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk11">setData</span><span class="mtk1">((</span><span class="mtk12">old</span><span class="mtk1">) </span><span class="mtk4">=&gt;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">old</span><span class="mtk1">.</span><span class="mtk11">map</span><span class="mtk1">((</span><span class="mtk12">row</span><span class="mtk1">, </span><span class="mtk12">index</span><span class="mtk1">) </span><span class="mtk4">=&gt;</span><span class="mtk1"> {</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk15">if</span><span class="mtk1"> (</span><span class="mtk12">index</span><span class="mtk1"> === </span><span class="mtk12">rowIndex</span><span class="mtk1">) {</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk15">return</span><span class="mtk1"> {</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> ...</span><span class="mtk12">old</span><span class="mtk1">[</span><span class="mtk12">rowIndex</span><span class="mtk1">],</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">[columnId]:</span><span class="mtk1"> </span><span class="mtk12">value</span><span class="mtk1">,</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> };</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> }</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk15">return</span><span class="mtk1"> </span><span class="mtk12">row</span><span class="mtk1">;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> })</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> );</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> },</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> },</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> });</span></span></span> <span class="grvsc-line"><span class="grvsc-source"></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk15">return</span><span class="mtk1"> (</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk17">&lt;&gt;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk17">&lt;</span><span class="mtk4">table</span><span class="mtk17">&gt;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk17">&lt;</span><span class="mtk4">thead</span><span class="mtk17">&gt;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk4">{</span><span class="mtk12">table</span><span class="mtk1">.</span><span class="mtk11">getHeaderGroups</span><span class="mtk1">().</span><span class="mtk11">map</span><span class="mtk1">((</span><span class="mtk12">headerGroup</span><span class="mtk1">) </span><span class="mtk4">=&gt;</span><span class="mtk1"> (</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk17">&lt;</span><span class="mtk4">tr</span><span class="mtk1"> </span><span class="mtk12">key</span><span class="mtk1">=</span><span class="mtk4">{</span><span class="mtk12">headerGroup</span><span class="mtk1">.</span><span class="mtk12">id</span><span class="mtk4">}</span><span class="mtk17">&gt;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk4">{</span><span class="mtk12">headerGroup</span><span class="mtk1">.</span><span class="mtk12">headers</span><span class="mtk1">.</span><span class="mtk11">map</span><span class="mtk1">((</span><span class="mtk12">header</span><span class="mtk1">) </span><span class="mtk4">=&gt;</span><span class="mtk1"> (</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk17">&lt;</span><span class="mtk4">th</span><span class="mtk1"> </span><span class="mtk12">key</span><span class="mtk1">=</span><span class="mtk4">{</span><span class="mtk12">header</span><span class="mtk1">.</span><span class="mtk12">id</span><span class="mtk4">}</span><span class="mtk17">&gt;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk4">{</span><span class="mtk12">header</span><span class="mtk1">.</span><span class="mtk12">isPlaceholder</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> ? </span><span class="mtk4">null</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> : </span><span class="mtk11">flexRender</span><span class="mtk1">(</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">header</span><span class="mtk1">.</span><span class="mtk12">column</span><span class="mtk1">.</span><span class="mtk12">columnDef</span><span class="mtk1">.</span><span class="mtk12">header</span><span class="mtk1">,</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">header</span><span class="mtk1">.</span><span class="mtk11">getContext</span><span class="mtk1">()</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> )</span><span class="mtk4">}</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk17">&lt;/</span><span class="mtk4">th</span><span class="mtk17">&gt;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> ))</span><span class="mtk4">}</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk17">&lt;/</span><span class="mtk4">tr</span><span class="mtk17">&gt;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> ))</span><span class="mtk4">}</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk17">&lt;/</span><span class="mtk4">thead</span><span class="mtk17">&gt;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk17">&lt;</span><span class="mtk4">tbody</span><span class="mtk17">&gt;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk4">{</span><span class="mtk12">table</span><span class="mtk1">.</span><span class="mtk11">getRowModel</span><span class="mtk1">().</span><span class="mtk12">rows</span><span class="mtk1">.</span><span class="mtk11">map</span><span class="mtk1">((</span><span class="mtk12">row</span><span class="mtk1">) </span><span class="mtk4">=&gt;</span><span class="mtk1"> (</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk17">&lt;</span><span class="mtk4">tr</span><span class="mtk1"> </span><span class="mtk12">key</span><span class="mtk1">=</span><span class="mtk4">{</span><span class="mtk12">row</span><span class="mtk1">.</span><span class="mtk12">id</span><span class="mtk4">}</span><span class="mtk17">&gt;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk4">{</span><span class="mtk12">row</span><span class="mtk1">.</span><span class="mtk11">getVisibleCells</span><span class="mtk1">().</span><span class="mtk11">map</span><span class="mtk1">((</span><span class="mtk12">cell</span><span class="mtk1">) </span><span class="mtk4">=&gt;</span><span class="mtk1"> (</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk17">&lt;</span><span class="mtk4">td</span><span class="mtk1"> </span><span class="mtk12">key</span><span class="mtk1">=</span><span class="mtk4">{</span><span class="mtk12">cell</span><span class="mtk1">.</span><span class="mtk12">id</span><span class="mtk4">}</span><span class="mtk17">&gt;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk4">{</span><span class="mtk11">flexRender</span><span class="mtk1">(</span><span class="mtk12">cell</span><span class="mtk1">.</span><span class="mtk12">column</span><span class="mtk1">.</span><span class="mtk12">columnDef</span><span class="mtk1">.</span><span class="mtk12">cell</span><span class="mtk1">, </span><span class="mtk12">cell</span><span class="mtk1">.</span><span class="mtk11">getContext</span><span class="mtk1">())</span><span class="mtk4">}</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk17">&lt;/</span><span class="mtk4">td</span><span class="mtk17">&gt;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> ))</span><span class="mtk4">}</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk17">&lt;/</span><span class="mtk4">tr</span><span class="mtk17">&gt;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> ))</span><span class="mtk4">}</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk17">&lt;/</span><span class="mtk4">tbody</span><span class="mtk17">&gt;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk17">&lt;/</span><span class="mtk4">table</span><span class="mtk17">&gt;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk17">&lt;</span><span class="mtk4">pre</span><span class="mtk17">&gt;</span><span class="mtk4">{</span><span class="mtk10">JSON</span><span class="mtk1">.</span><span class="mtk11">stringify</span><span class="mtk1">(</span><span class="mtk12">data</span><span class="mtk1">, </span><span class="mtk4">null</span><span class="mtk1">, </span><span class="mtk8">&quot;</span><span class="mtk6">\t</span><span class="mtk8">&quot;</span><span class="mtk1">)</span><span class="mtk4">}</span><span class="mtk17">&lt;/</span><span class="mtk4">pre</span><span class="mtk17">&gt;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk17">&lt;/&gt;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> );</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1">};</span></span></span> <span class="grvsc-line"><span class="grvsc-source"></span></span></code></pre> <div id="ReactEditableTableTwo" data-code data-height="800px"></div> <p>The object is printed out at the end to validate that the input updates are working as expected.</p> <h2 id="supporting-dynamic-types" style="position:relative;"><a href="#supporting-dynamic-types" aria-label="supporting dynamic types permalink" class="anchor before"><svg aria-hidden="true" focusable="false" height="16" version="1.1" viewBox="0 0 16 16" width="16"><path fill-rule="evenodd" d="M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z"></path></svg></a>Supporting dynamic types</h2> <p>So far, we’ve created an editable table that only supports text fields. As mentioned in the introduction, the goal is to be able to define different column types and render the appropriate elements dynamically.</p> <p>Let’s start by adding a new <code>type</code> prop to the <code>columns</code> object.</p> <pre class="grvsc-container grvsc-has-line-highlighting default-dark" data-language="jsx" data-index="11"><code class="grvsc-code"><span class="grvsc-line"><span class="grvsc-source"><span class="mtk4">const</span><span class="mtk1"> </span><span class="mtk12">columns</span><span class="mtk1"> = [</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">columnHelper</span><span class="mtk1">.</span><span class="mtk11">accessor</span><span class="mtk1">(</span><span class="mtk8">&quot;studentId&quot;</span><span class="mtk1">, {</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">header:</span><span class="mtk1"> </span><span class="mtk8">&quot;Student ID&quot;</span><span class="mtk1">,</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">cell:</span><span class="mtk1"> </span><span class="mtk12">TableCell</span><span class="mtk1">,</span></span></span> <span class="grvsc-line grvsc-line-highlighted"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">meta:</span><span class="mtk1"> {</span></span></span> <span class="grvsc-line grvsc-line-highlighted"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">type:</span><span class="mtk1"> </span><span class="mtk8">&quot;number&quot;</span><span class="mtk1">,</span></span></span> <span class="grvsc-line grvsc-line-highlighted"><span class="grvsc-source"><span class="mtk1"> },</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> }),</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">columnHelper</span><span class="mtk1">.</span><span class="mtk11">accessor</span><span class="mtk1">(</span><span class="mtk8">&quot;name&quot;</span><span class="mtk1">, {</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">header:</span><span class="mtk1"> </span><span class="mtk8">&quot;Full Name&quot;</span><span class="mtk1">,</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">cell:</span><span class="mtk1"> </span><span class="mtk12">TableCell</span><span class="mtk1">,</span></span></span> <span class="grvsc-line grvsc-line-highlighted"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">meta:</span><span class="mtk1"> {</span></span></span> <span class="grvsc-line grvsc-line-highlighted"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">type:</span><span class="mtk1"> </span><span class="mtk8">&quot;text&quot;</span><span class="mtk1">,</span></span></span> <span class="grvsc-line grvsc-line-highlighted"><span class="grvsc-source"><span class="mtk1"> },</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> }),</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">columnHelper</span><span class="mtk1">.</span><span class="mtk11">accessor</span><span class="mtk1">(</span><span class="mtk8">&quot;dateOfBirth&quot;</span><span class="mtk1">, {</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">header:</span><span class="mtk1"> </span><span class="mtk8">&quot;Date Of Birth&quot;</span><span class="mtk1">,</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">cell:</span><span class="mtk1"> </span><span class="mtk12">TableCell</span><span class="mtk1">,</span></span></span> <span class="grvsc-line grvsc-line-highlighted"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">meta:</span><span class="mtk1"> {</span></span></span> <span class="grvsc-line grvsc-line-highlighted"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">type:</span><span class="mtk1"> </span><span class="mtk8">&quot;date&quot;</span><span class="mtk1">,</span></span></span> <span class="grvsc-line grvsc-line-highlighted"><span class="grvsc-source"><span class="mtk1"> },</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> }),</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">columnHelper</span><span class="mtk1">.</span><span class="mtk11">accessor</span><span class="mtk1">(</span><span class="mtk8">&quot;major&quot;</span><span class="mtk1">, {</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">header:</span><span class="mtk1"> </span><span class="mtk8">&quot;Major&quot;</span><span class="mtk1">,</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">cell:</span><span class="mtk1"> </span><span class="mtk12">TableCell</span><span class="mtk1">,</span></span></span> <span class="grvsc-line grvsc-line-highlighted"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">meta:</span><span class="mtk1"> {</span></span></span> <span class="grvsc-line grvsc-line-highlighted"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">type:</span><span class="mtk1"> </span><span class="mtk8">&quot;text&quot;</span><span class="mtk1">,</span></span></span> <span class="grvsc-line grvsc-line-highlighted"><span class="grvsc-source"><span class="mtk1"> },</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> }),</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1">]</span></span></span></code></pre> <p>Similar to the table, the columns provide a <code>meta</code> object to add whatever we’d like to it. All we need to do is get the type from the <code>meta</code> object and pass it to the input field in the <code>TableCell</code> component.</p> <pre class="grvsc-container grvsc-has-line-highlighting default-dark" data-language="jsx" data-index="12"><code class="grvsc-code"><span class="grvsc-line"><span class="grvsc-source"><span class="mtk4">const</span><span class="mtk1"> </span><span class="mtk11">TableCell</span><span class="mtk1"> = ({ </span><span class="mtk12">getValue</span><span class="mtk1">, </span><span class="mtk12">row</span><span class="mtk1">, </span><span class="mtk12">column</span><span class="mtk1">, </span><span class="mtk12">table</span><span class="mtk1"> }) </span><span class="mtk4">=&gt;</span><span class="mtk1"> {</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk4">const</span><span class="mtk1"> </span><span class="mtk12">initialValue</span><span class="mtk1"> = </span><span class="mtk11">getValue</span><span class="mtk1">()</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk4">const</span><span class="mtk1"> [</span><span class="mtk12">value</span><span class="mtk1">, </span><span class="mtk12">setValue</span><span class="mtk1">] = </span><span class="mtk11">useState</span><span class="mtk1">(</span><span class="mtk12">initialValue</span><span class="mtk1">)</span></span></span> <span class="grvsc-line"><span class="grvsc-source"></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk11">useEffect</span><span class="mtk1">(() </span><span class="mtk4">=&gt;</span><span class="mtk1"> {</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk11">setValue</span><span class="mtk1">(</span><span class="mtk12">initialValue</span><span class="mtk1">)</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> }, [</span><span class="mtk12">initialValue</span><span class="mtk1">])</span></span></span> <span class="grvsc-line"><span class="grvsc-source"></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk4">const</span><span class="mtk1"> </span><span class="mtk11">onBlur</span><span class="mtk1"> = () </span><span class="mtk4">=&gt;</span><span class="mtk1"> {</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">table</span><span class="mtk1">.</span><span class="mtk12">options</span><span class="mtk1">.</span><span class="mtk12">meta</span><span class="mtk1">?.</span><span class="mtk11">updateData</span><span class="mtk1">(</span><span class="mtk12">row</span><span class="mtk1">.</span><span class="mtk12">index</span><span class="mtk1">, </span><span class="mtk12">column</span><span class="mtk1">.</span><span class="mtk12">id</span><span class="mtk1">, </span><span class="mtk12">value</span><span class="mtk1">)</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> }</span></span></span> <span class="grvsc-line"><span class="grvsc-source"></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk15">return</span><span class="mtk1"> (</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk17">&lt;</span><span class="mtk4">input</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">value</span><span class="mtk1">=</span><span class="mtk4">{</span><span class="mtk12">value</span><span class="mtk4">}</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">onChange</span><span class="mtk1">=</span><span class="mtk4">{</span><span class="mtk12">e</span><span class="mtk1"> </span><span class="mtk4">=&gt;</span><span class="mtk1"> </span><span class="mtk11">setValue</span><span class="mtk1">(</span><span class="mtk12">e</span><span class="mtk1">.</span><span class="mtk12">target</span><span class="mtk1">.</span><span class="mtk12">value</span><span class="mtk1">)</span><span class="mtk4">}</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">onBlur</span><span class="mtk1">=</span><span class="mtk4">{</span><span class="mtk12">onBlur</span><span class="mtk4">}</span></span></span> <span class="grvsc-line grvsc-line-highlighted"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">type</span><span class="mtk1">=</span><span class="mtk4">{</span><span class="mtk12">column</span><span class="mtk1">.</span><span class="mtk12">columnDef</span><span class="mtk1">.</span><span class="mtk12">meta</span><span class="mtk1">?.</span><span class="mtk12">type</span><span class="mtk1"> || </span><span class="mtk8">&quot;text&quot;</span><span class="mtk4">}</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk17">/&gt;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> )</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1">}</span></span></span></code></pre> <p>Voila! That was fast!</p> <p>What if we want a more complex data type, like a select element? Well, for that, we need to do a bit more work 🙂</p> <p>Here are the steps we need to follow:</p> <ul> <li>Change the “Major” col type to “select” and provide all the select options within the column <code>meta</code>. Remember, we want to make this as dynamic as possible to support different data models.</li> <li>Introduce a new <code>select</code> element in the <code>TableCell</code> component, which will populate all options from the column <code>meta</code> object.</li> </ul> <pre class="grvsc-container grvsc-has-line-highlighting default-dark" data-language="jsx" data-index="13"><code class="grvsc-code"><span class="grvsc-line grvsc-line-highlighted"><span class="grvsc-source"><span class="mtk4">type</span><span class="mtk1"> </span><span class="mtk10">Option</span><span class="mtk1"> = {</span></span></span> <span class="grvsc-line grvsc-line-highlighted"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">label</span><span class="mtk1">: </span><span class="mtk10">string</span><span class="mtk1">;</span></span></span> <span class="grvsc-line grvsc-line-highlighted"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">value</span><span class="mtk1">: </span><span class="mtk10">string</span><span class="mtk1">;</span></span></span> <span class="grvsc-line grvsc-line-highlighted"><span class="grvsc-source"><span class="mtk1">};</span></span></span> <span class="grvsc-line"><span class="grvsc-source"></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk4">const</span><span class="mtk1"> </span><span class="mtk11">TableCell</span><span class="mtk1"> = ({ </span><span class="mtk12">getValue</span><span class="mtk1">, </span><span class="mtk12">row</span><span class="mtk1">, </span><span class="mtk12">column</span><span class="mtk1">, </span><span class="mtk12">table</span><span class="mtk1"> }) </span><span class="mtk4">=&gt;</span><span class="mtk1"> {</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk4">const</span><span class="mtk1"> </span><span class="mtk12">initialValue</span><span class="mtk1"> = </span><span class="mtk11">getValue</span><span class="mtk1">();</span></span></span> <span class="grvsc-line grvsc-line-highlighted"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk4">const</span><span class="mtk1"> </span><span class="mtk12">columnMeta</span><span class="mtk1"> = </span><span class="mtk12">column</span><span class="mtk1">.</span><span class="mtk12">columnDef</span><span class="mtk1">.</span><span class="mtk12">meta</span><span class="mtk1">;</span></span></span> <span class="grvsc-line grvsc-line-highlighted"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk4">const</span><span class="mtk1"> </span><span class="mtk12">tableMeta</span><span class="mtk1"> = </span><span class="mtk12">table</span><span class="mtk1">.</span><span class="mtk12">options</span><span class="mtk1">.</span><span class="mtk12">meta</span><span class="mtk1">;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk4">const</span><span class="mtk1"> [</span><span class="mtk12">value</span><span class="mtk1">, </span><span class="mtk12">setValue</span><span class="mtk1">] = </span><span class="mtk11">useState</span><span class="mtk1">(</span><span class="mtk12">initialValue</span><span class="mtk1">);</span></span></span> <span class="grvsc-line"><span class="grvsc-source"></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk11">useEffect</span><span class="mtk1">(() </span><span class="mtk4">=&gt;</span><span class="mtk1"> {</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk11">setValue</span><span class="mtk1">(</span><span class="mtk12">initialValue</span><span class="mtk1">);</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> }, [</span><span class="mtk12">initialValue</span><span class="mtk1">]);</span></span></span> <span class="grvsc-line"><span class="grvsc-source"></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk4">const</span><span class="mtk1"> </span><span class="mtk11">onBlur</span><span class="mtk1"> = () </span><span class="mtk4">=&gt;</span><span class="mtk1"> {</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">tableMeta</span><span class="mtk1">?.</span><span class="mtk11">updateData</span><span class="mtk1">(</span><span class="mtk12">row</span><span class="mtk1">.</span><span class="mtk12">index</span><span class="mtk1">, </span><span class="mtk12">column</span><span class="mtk1">.</span><span class="mtk12">id</span><span class="mtk1">, </span><span class="mtk12">value</span><span class="mtk1">);</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> };</span></span></span> <span class="grvsc-line"><span class="grvsc-source"></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk4">const</span><span class="mtk1"> </span><span class="mtk11">onSelectChange</span><span class="mtk1"> = (</span><span class="mtk12">e</span><span class="mtk1">: </span><span class="mtk10">ChangeEvent</span><span class="mtk1">&lt;</span><span class="mtk10">HTMLSelectElement</span><span class="mtk1">&gt;) </span><span class="mtk4">=&gt;</span><span class="mtk1"> {</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk11">setValue</span><span class="mtk1">(</span><span class="mtk12">e</span><span class="mtk1">.</span><span class="mtk12">target</span><span class="mtk1">.</span><span class="mtk12">value</span><span class="mtk1">);</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">tableMeta</span><span class="mtk1">?.</span><span class="mtk11">updateData</span><span class="mtk1">(</span><span class="mtk12">row</span><span class="mtk1">.</span><span class="mtk12">index</span><span class="mtk1">, </span><span class="mtk12">column</span><span class="mtk1">.</span><span class="mtk12">id</span><span class="mtk1">, </span><span class="mtk12">e</span><span class="mtk1">.</span><span class="mtk12">target</span><span class="mtk1">.</span><span class="mtk12">value</span><span class="mtk1">);</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> };</span></span></span> <span class="grvsc-line"><span class="grvsc-source"></span></span> <span class="grvsc-line grvsc-line-highlighted"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk15">return</span><span class="mtk1"> </span><span class="mtk12">columnMeta</span><span class="mtk1">?.</span><span class="mtk12">type</span><span class="mtk1"> === </span><span class="mtk8">&quot;select&quot;</span><span class="mtk1"> ? (</span></span></span> <span class="grvsc-line grvsc-line-highlighted"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk17">&lt;</span><span class="mtk4">select</span><span class="mtk1"> </span><span class="mtk12">onChange</span><span class="mtk1">=</span><span class="mtk4">{</span><span class="mtk12">onSelectChange</span><span class="mtk4">}</span><span class="mtk1"> </span><span class="mtk12">value</span><span class="mtk1">=</span><span class="mtk4">{</span><span class="mtk12">initialValue</span><span class="mtk4">}</span><span class="mtk17">&gt;</span></span></span> <span class="grvsc-line grvsc-line-highlighted"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk4">{</span><span class="mtk12">columnMeta</span><span class="mtk1">?.</span><span class="mtk12">options</span><span class="mtk1">?.</span><span class="mtk11">map</span><span class="mtk1">((</span><span class="mtk12">option</span><span class="mtk1">: </span><span class="mtk10">Option</span><span class="mtk1">) </span><span class="mtk4">=&gt;</span><span class="mtk1"> (</span></span></span> <span class="grvsc-line grvsc-line-highlighted"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk17">&lt;</span><span class="mtk4">option</span><span class="mtk1"> </span><span class="mtk12">key</span><span class="mtk1">=</span><span class="mtk4">{</span><span class="mtk12">option</span><span class="mtk1">.</span><span class="mtk12">value</span><span class="mtk4">}</span><span class="mtk1"> </span><span class="mtk12">value</span><span class="mtk1">=</span><span class="mtk4">{</span><span class="mtk12">option</span><span class="mtk1">.</span><span class="mtk12">value</span><span class="mtk4">}</span><span class="mtk17">&gt;</span><span class="mtk4">{</span><span class="mtk12">option</span><span class="mtk1">.</span><span class="mtk12">label</span><span class="mtk4">}</span><span class="mtk17">&lt;/</span><span class="mtk4">option</span><span class="mtk17">&gt;</span></span></span> <span class="grvsc-line grvsc-line-highlighted"><span class="grvsc-source"><span class="mtk1"> ))</span><span class="mtk4">}</span></span></span> <span class="grvsc-line grvsc-line-highlighted"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk17">&lt;/</span><span class="mtk4">select</span><span class="mtk17">&gt;</span></span></span> <span class="grvsc-line grvsc-line-highlighted"><span class="grvsc-source"><span class="mtk1"> ) : (</span></span></span> <span class="grvsc-line grvsc-line-highlighted"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk17">&lt;</span><span class="mtk4">input</span></span></span> <span class="grvsc-line grvsc-line-highlighted"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">value</span><span class="mtk1">=</span><span class="mtk4">{</span><span class="mtk12">value</span><span class="mtk4">}</span></span></span> <span class="grvsc-line grvsc-line-highlighted"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">onChange</span><span class="mtk1">=</span><span class="mtk4">{</span><span class="mtk1">(</span><span class="mtk12">e</span><span class="mtk1">) </span><span class="mtk4">=&gt;</span><span class="mtk1"> </span><span class="mtk11">setValue</span><span class="mtk1">(</span><span class="mtk12">e</span><span class="mtk1">.</span><span class="mtk12">target</span><span class="mtk1">.</span><span class="mtk12">value</span><span class="mtk1">)</span><span class="mtk4">}</span></span></span> <span class="grvsc-line grvsc-line-highlighted"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">onBlur</span><span class="mtk1">=</span><span class="mtk4">{</span><span class="mtk12">onBlur</span><span class="mtk4">}</span></span></span> <span class="grvsc-line grvsc-line-highlighted"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">type</span><span class="mtk1">=</span><span class="mtk4">{</span><span class="mtk12">columnMeta</span><span class="mtk1">?.</span><span class="mtk12">type</span><span class="mtk1"> || </span><span class="mtk8">&quot;text&quot;</span><span class="mtk4">}</span></span></span> <span class="grvsc-line grvsc-line-highlighted"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk17">/&gt;</span></span></span> <span class="grvsc-line grvsc-line-highlighted"><span class="grvsc-source"><span class="mtk1"> );</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1">};</span></span></span> <span class="grvsc-line"><span class="grvsc-source"></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk4">const</span><span class="mtk1"> </span><span class="mtk12">columnHelper</span><span class="mtk1"> = </span><span class="mtk11">createColumnHelper</span><span class="mtk1">&lt;</span><span class="mtk10">Student</span><span class="mtk1">&gt;();</span></span></span> <span class="grvsc-line"><span class="grvsc-source"></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk4">const</span><span class="mtk1"> </span><span class="mtk12">columns</span><span class="mtk1"> = [</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">columnHelper</span><span class="mtk1">.</span><span class="mtk11">accessor</span><span class="mtk1">(</span><span class="mtk8">&quot;studentId&quot;</span><span class="mtk1">, {</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">header:</span><span class="mtk1"> </span><span class="mtk8">&quot;Student ID&quot;</span><span class="mtk1">,</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">cell:</span><span class="mtk1"> </span><span class="mtk12">TableCell</span><span class="mtk1">,</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">meta:</span><span class="mtk1"> {</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">type:</span><span class="mtk1"> </span><span class="mtk8">&quot;number&quot;</span><span class="mtk1">,</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> },</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> }),</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">columnHelper</span><span class="mtk1">.</span><span class="mtk11">accessor</span><span class="mtk1">(</span><span class="mtk8">&quot;name&quot;</span><span class="mtk1">, {</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">header:</span><span class="mtk1"> </span><span class="mtk8">&quot;Full Name&quot;</span><span class="mtk1">,</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">cell:</span><span class="mtk1"> </span><span class="mtk12">TableCell</span><span class="mtk1">,</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">meta:</span><span class="mtk1"> {</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">type:</span><span class="mtk1"> </span><span class="mtk8">&quot;text&quot;</span><span class="mtk1">,</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> },</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> }),</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">columnHelper</span><span class="mtk1">.</span><span class="mtk11">accessor</span><span class="mtk1">(</span><span class="mtk8">&quot;dateOfBirth&quot;</span><span class="mtk1">, {</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">header:</span><span class="mtk1"> </span><span class="mtk8">&quot;Date Of Birth&quot;</span><span class="mtk1">,</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">cell:</span><span class="mtk1"> </span><span class="mtk12">TableCell</span><span class="mtk1">,</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">meta:</span><span class="mtk1"> {</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">type:</span><span class="mtk1"> </span><span class="mtk8">&quot;date&quot;</span><span class="mtk1">,</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> },</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> }),</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">columnHelper</span><span class="mtk1">.</span><span class="mtk11">accessor</span><span class="mtk1">(</span><span class="mtk8">&quot;major&quot;</span><span class="mtk1">, {</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">header:</span><span class="mtk1"> </span><span class="mtk8">&quot;Major&quot;</span><span class="mtk1">,</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">cell:</span><span class="mtk1"> </span><span class="mtk12">TableCell</span><span class="mtk1">,</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">meta:</span><span class="mtk1"> {</span></span></span> <span class="grvsc-line grvsc-line-highlighted"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">type:</span><span class="mtk1"> </span><span class="mtk8">&quot;select&quot;</span><span class="mtk1">,</span></span></span> <span class="grvsc-line grvsc-line-highlighted"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">options:</span><span class="mtk1"> [</span></span></span> <span class="grvsc-line grvsc-line-highlighted"><span class="grvsc-source"><span class="mtk1"> { </span><span class="mtk12">value:</span><span class="mtk1"> </span><span class="mtk8">&quot;Computer Science&quot;</span><span class="mtk1">, </span><span class="mtk12">label:</span><span class="mtk1"> </span><span class="mtk8">&quot;Computer Science&quot;</span><span class="mtk1"> },</span></span></span> <span class="grvsc-line grvsc-line-highlighted"><span class="grvsc-source"><span class="mtk1"> { </span><span class="mtk12">value:</span><span class="mtk1"> </span><span class="mtk8">&quot;Communications&quot;</span><span class="mtk1">, </span><span class="mtk12">label:</span><span class="mtk1"> </span><span class="mtk8">&quot;Communications&quot;</span><span class="mtk1"> },</span></span></span> <span class="grvsc-line grvsc-line-highlighted"><span class="grvsc-source"><span class="mtk1"> { </span><span class="mtk12">value:</span><span class="mtk1"> </span><span class="mtk8">&quot;Business&quot;</span><span class="mtk1">, </span><span class="mtk12">label:</span><span class="mtk1"> </span><span class="mtk8">&quot;Business&quot;</span><span class="mtk1"> },</span></span></span> <span class="grvsc-line grvsc-line-highlighted"><span class="grvsc-source"><span class="mtk1"> { </span><span class="mtk12">value:</span><span class="mtk1"> </span><span class="mtk8">&quot;Psychology&quot;</span><span class="mtk1">, </span><span class="mtk12">label:</span><span class="mtk1"> </span><span class="mtk8">&quot;Psychology&quot;</span><span class="mtk1"> },</span></span></span> <span class="grvsc-line grvsc-line-highlighted"><span class="grvsc-source"><span class="mtk1"> ],</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> },</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> }),</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1">];</span></span></span></code></pre> <div id="ReactEditableTableThree" data-code data-height="800px"></div> <p>As we can see in the code and demo above, the “number”, “date” and “select” along with the options, are all correctly showing. For the <code>select</code> element, we defined a new <code>onSelectChange</code> event to trigger the update function. Additionally, we did some code cleanup to make accessing <code>column</code> and <code>table</code> less verbose.</p> <h2 id="editable-rows" style="position:relative;"><a href="#editable-rows" aria-label="editable rows permalink" class="anchor before"><svg aria-hidden="true" focusable="false" height="16" version="1.1" viewBox="0 0 16 16" width="16"><path fill-rule="evenodd" d="M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z"></path></svg></a>Editable rows</h2> <p>We often want the table to be read-only and switch to an edit mode on demand. The reasons could be performance enhancement or want to submit data to the server, so avoid triggering an API call on every field.</p> <p>A common practice is to add an action button in a new column that will toggle the row between edit and non-edit mode. It will also contain a cancel action in case the user wants to abort changes.</p> <p>Let’s start with creating an <code>editedRows</code> state, a key/value object that indicates which rows are in edit mode. We’ll also add the getter and setter to the table <code>meta</code> so we can access it from other components.</p> <pre class="grvsc-container grvsc-has-line-highlighting default-dark" data-language="jsx" data-index="14"><code class="grvsc-code"><span class="grvsc-line"><span class="grvsc-source"><span class="mtk15">export</span><span class="mtk1"> </span><span class="mtk4">const</span><span class="mtk1"> </span><span class="mtk11">Table</span><span class="mtk1"> = () </span><span class="mtk4">=&gt;</span><span class="mtk1"> {</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk4">const</span><span class="mtk1"> [</span><span class="mtk12">data</span><span class="mtk1">, </span><span class="mtk12">setData</span><span class="mtk1">] = </span><span class="mtk11">useState</span><span class="mtk1">(() </span><span class="mtk4">=&gt;</span><span class="mtk1"> [...</span><span class="mtk12">defaultData</span><span class="mtk1">]);</span></span></span> <span class="grvsc-line grvsc-line-highlighted"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk4">const</span><span class="mtk1"> [</span><span class="mtk12">editedRows</span><span class="mtk1">, </span><span class="mtk12">setEditedRows</span><span class="mtk1">] = </span><span class="mtk11">useState</span><span class="mtk1">({});</span></span></span> <span class="grvsc-line"><span class="grvsc-source"></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk4">const</span><span class="mtk1"> </span><span class="mtk12">table</span><span class="mtk1"> = </span><span class="mtk11">useReactTable</span><span class="mtk1">({</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">data</span><span class="mtk1">,</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">columns</span><span class="mtk1">,</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">getCoreRowModel:</span><span class="mtk1"> </span><span class="mtk11">getCoreRowModel</span><span class="mtk1">(),</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">meta:</span><span class="mtk1"> {</span></span></span> <span class="grvsc-line grvsc-line-highlighted"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">editedRows</span><span class="mtk1">,</span></span></span> <span class="grvsc-line grvsc-line-highlighted"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">setEditedRows</span><span class="mtk1">,</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> ...</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> },</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> });</span></span></span> <span class="grvsc-line"><span class="grvsc-source"></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk15">return</span><span class="mtk1"> (...);</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1">};</span></span></span></code></pre> <p>Then, we can create an <code>EditCell</code> component with “edit”, “cancel”, and “done” buttons. “cancel” and “done” will only show if the <code>editedRows</code> contains the row id set to <code>true</code>. A unique row id is automatically generated for each row through the <code>getCoreRowModel</code> function.</p> <pre class="grvsc-container default-dark" data-language="jsx" data-index="15"><code class="grvsc-code"><span class="grvsc-line"><span class="grvsc-source"><span class="mtk4">const</span><span class="mtk1"> </span><span class="mtk11">EditCell</span><span class="mtk1"> = ({ </span><span class="mtk12">row</span><span class="mtk1">, </span><span class="mtk12">table</span><span class="mtk1"> }) </span><span class="mtk4">=&gt;</span><span class="mtk1"> {</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk4">const</span><span class="mtk1"> </span><span class="mtk12">meta</span><span class="mtk1"> = </span><span class="mtk12">table</span><span class="mtk1">.</span><span class="mtk12">options</span><span class="mtk1">.</span><span class="mtk12">meta</span></span></span> <span class="grvsc-line"><span class="grvsc-source"></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk4">const</span><span class="mtk1"> </span><span class="mtk11">setEditedRows</span><span class="mtk1"> = (</span><span class="mtk12">e</span><span class="mtk1">: </span><span class="mtk10">MouseEvent</span><span class="mtk1">&lt;</span><span class="mtk10">HTMLButtonElement</span><span class="mtk1">&gt;) </span><span class="mtk4">=&gt;</span><span class="mtk1"> {</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">meta</span><span class="mtk1">?.</span><span class="mtk11">setEditedRows</span><span class="mtk1">((</span><span class="mtk12">old</span><span class="mtk1">: []) </span><span class="mtk4">=&gt;</span><span class="mtk1"> ({</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> ...</span><span class="mtk12">old</span><span class="mtk1">,</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">[row.id]:</span><span class="mtk1"> !</span><span class="mtk12">old</span><span class="mtk1">[</span><span class="mtk12">row</span><span class="mtk1">.</span><span class="mtk12">id</span><span class="mtk1">],</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> }))</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> }</span></span></span> <span class="grvsc-line"><span class="grvsc-source"></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk15">return</span><span class="mtk1"> </span><span class="mtk12">meta</span><span class="mtk1">?.</span><span class="mtk12">editedRows</span><span class="mtk1">[</span><span class="mtk12">row</span><span class="mtk1">.</span><span class="mtk12">id</span><span class="mtk1">] ? (</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk17">&lt;&gt;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk17">&lt;</span><span class="mtk4">button</span><span class="mtk17">&gt;</span><span class="mtk1">X</span><span class="mtk17">&lt;/</span><span class="mtk4">button</span><span class="mtk17">&gt;</span><span class="mtk1"> </span><span class="mtk17">&lt;</span><span class="mtk4">button</span><span class="mtk1"> </span><span class="mtk12">onClick</span><span class="mtk1">=</span><span class="mtk4">{</span><span class="mtk12">setEditedRows</span><span class="mtk4">}</span><span class="mtk17">&gt;</span><span class="mtk1">✔</span><span class="mtk17">&lt;/</span><span class="mtk4">button</span><span class="mtk17">&gt;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk17">&lt;/&gt;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> ) : (</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk17">&lt;</span><span class="mtk4">button</span><span class="mtk1"> </span><span class="mtk12">onClick</span><span class="mtk1">=</span><span class="mtk4">{</span><span class="mtk12">setEditedRows</span><span class="mtk4">}</span><span class="mtk17">&gt;</span><span class="mtk1">✐</span><span class="mtk17">&lt;/</span><span class="mtk4">button</span><span class="mtk17">&gt;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> )</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1">}</span></span></span></code></pre> <p>We also defined an event, a simple true/false toggle for the current row id using the setter function we just passed in the <code>meta</code> options.</p> <p>Now, the component has to be placed in a new column. TanStack Table provides a <code>display</code> column option, which means it won’t be part of the data model as its only purpose is to manage the editable state.</p> <pre class="grvsc-container grvsc-has-line-highlighting default-dark" data-language="jsx" data-index="16"><code class="grvsc-code"><span class="grvsc-line"><span class="grvsc-source"><span class="mtk4">const</span><span class="mtk1"> </span><span class="mtk12">columns</span><span class="mtk1"> = [</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">columnHelper</span><span class="mtk1">.</span><span class="mtk11">accessor</span><span class="mtk1">(</span><span class="mtk8">&quot;studentId&quot;</span><span class="mtk1">, {</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">header:</span><span class="mtk1"> </span><span class="mtk8">&quot;Student ID&quot;</span><span class="mtk1">,</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">cell:</span><span class="mtk1"> </span><span class="mtk12">TableCell</span><span class="mtk1">,</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">meta:</span><span class="mtk1"> {</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">type:</span><span class="mtk1"> </span><span class="mtk8">&quot;number&quot;</span><span class="mtk1">,</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> },</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> }),</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">columnHelper</span><span class="mtk1">.</span><span class="mtk11">accessor</span><span class="mtk1">(</span><span class="mtk8">&quot;name&quot;</span><span class="mtk1">, {</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">header:</span><span class="mtk1"> </span><span class="mtk8">&quot;Full Name&quot;</span><span class="mtk1">,</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">cell:</span><span class="mtk1"> </span><span class="mtk12">TableCell</span><span class="mtk1">,</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">meta:</span><span class="mtk1"> {</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">type:</span><span class="mtk1"> </span><span class="mtk8">&quot;text&quot;</span><span class="mtk1">,</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> },</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> }),</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">columnHelper</span><span class="mtk1">.</span><span class="mtk11">accessor</span><span class="mtk1">(</span><span class="mtk8">&quot;dateOfBirth&quot;</span><span class="mtk1">, {</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">header:</span><span class="mtk1"> </span><span class="mtk8">&quot;Date Of Birth&quot;</span><span class="mtk1">,</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">cell:</span><span class="mtk1"> </span><span class="mtk12">TableCell</span><span class="mtk1">,</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">meta:</span><span class="mtk1"> {</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">type:</span><span class="mtk1"> </span><span class="mtk8">&quot;date&quot;</span><span class="mtk1">,</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> },</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> }),</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">columnHelper</span><span class="mtk1">.</span><span class="mtk11">accessor</span><span class="mtk1">(</span><span class="mtk8">&quot;major&quot;</span><span class="mtk1">, {</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">header:</span><span class="mtk1"> </span><span class="mtk8">&quot;Major&quot;</span><span class="mtk1">,</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">cell:</span><span class="mtk1"> </span><span class="mtk12">TableCell</span><span class="mtk1">,</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">meta:</span><span class="mtk1"> {</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">type:</span><span class="mtk1"> </span><span class="mtk8">&quot;select&quot;</span><span class="mtk1">,</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">options:</span><span class="mtk1"> [</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> { </span><span class="mtk12">value:</span><span class="mtk1"> </span><span class="mtk8">&quot;Computer Science&quot;</span><span class="mtk1">, </span><span class="mtk12">label:</span><span class="mtk1"> </span><span class="mtk8">&quot;Computer Science&quot;</span><span class="mtk1"> },</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> { </span><span class="mtk12">value:</span><span class="mtk1"> </span><span class="mtk8">&quot;Communications&quot;</span><span class="mtk1">, </span><span class="mtk12">label:</span><span class="mtk1"> </span><span class="mtk8">&quot;Communications&quot;</span><span class="mtk1"> },</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> { </span><span class="mtk12">value:</span><span class="mtk1"> </span><span class="mtk8">&quot;Business&quot;</span><span class="mtk1">, </span><span class="mtk12">label:</span><span class="mtk1"> </span><span class="mtk8">&quot;Business&quot;</span><span class="mtk1"> },</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> { </span><span class="mtk12">value:</span><span class="mtk1"> </span><span class="mtk8">&quot;Psychology&quot;</span><span class="mtk1">, </span><span class="mtk12">label:</span><span class="mtk1"> </span><span class="mtk8">&quot;Psychology&quot;</span><span class="mtk1"> },</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> ],</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> },</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> }),</span></span></span> <span class="grvsc-line grvsc-line-highlighted"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">columnHelper</span><span class="mtk1">.</span><span class="mtk11">display</span><span class="mtk1">({</span></span></span> <span class="grvsc-line grvsc-line-highlighted"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">id:</span><span class="mtk1"> </span><span class="mtk8">&quot;edit&quot;</span><span class="mtk1">,</span></span></span> <span class="grvsc-line grvsc-line-highlighted"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">cell:</span><span class="mtk1"> </span><span class="mtk12">EditCell</span><span class="mtk1">,</span></span></span> <span class="grvsc-line grvsc-line-highlighted"><span class="grvsc-source"><span class="mtk1"> }),</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1">]</span></span></span></code></pre> <p>Given what we have so far, the <code>TableCell</code> component can easily toggle between edit and non-edit modes by checking the <code>editedRows</code> in the table <code>meta</code> object.</p> <pre class="grvsc-container grvsc-has-line-highlighting default-dark" data-language="jsx" data-index="17"><code class="grvsc-code"><span class="grvsc-line"><span class="grvsc-source"><span class="mtk4">const</span><span class="mtk1"> </span><span class="mtk11">TableCell</span><span class="mtk1"> = ({ </span><span class="mtk12">getValue</span><span class="mtk1">, </span><span class="mtk12">row</span><span class="mtk1">, </span><span class="mtk12">column</span><span class="mtk1">, </span><span class="mtk12">table</span><span class="mtk1"> }) </span><span class="mtk4">=&gt;</span><span class="mtk1"> {</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk4">const</span><span class="mtk1"> </span><span class="mtk12">initialValue</span><span class="mtk1"> = </span><span class="mtk11">getValue</span><span class="mtk1">()</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk4">const</span><span class="mtk1"> </span><span class="mtk12">columnMeta</span><span class="mtk1"> = </span><span class="mtk12">column</span><span class="mtk1">.</span><span class="mtk12">columnDef</span><span class="mtk1">.</span><span class="mtk12">meta</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk4">const</span><span class="mtk1"> </span><span class="mtk12">tableMeta</span><span class="mtk1"> = </span><span class="mtk12">table</span><span class="mtk1">.</span><span class="mtk12">options</span><span class="mtk1">.</span><span class="mtk12">meta</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk4">const</span><span class="mtk1"> [</span><span class="mtk12">value</span><span class="mtk1">, </span><span class="mtk12">setValue</span><span class="mtk1">] = </span><span class="mtk11">useState</span><span class="mtk1">(</span><span class="mtk12">initialValue</span><span class="mtk1">)</span></span></span> <span class="grvsc-line"><span class="grvsc-source"></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk11">useEffect</span><span class="mtk1">(() </span><span class="mtk4">=&gt;</span><span class="mtk1"> {</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk11">setValue</span><span class="mtk1">(</span><span class="mtk12">initialValue</span><span class="mtk1">)</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> }, [</span><span class="mtk12">initialValue</span><span class="mtk1">])</span></span></span> <span class="grvsc-line"><span class="grvsc-source"></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk4">const</span><span class="mtk1"> </span><span class="mtk11">onBlur</span><span class="mtk1"> = () </span><span class="mtk4">=&gt;</span><span class="mtk1"> {</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">tableMeta</span><span class="mtk1">?.</span><span class="mtk11">updateData</span><span class="mtk1">(</span><span class="mtk12">row</span><span class="mtk1">.</span><span class="mtk12">index</span><span class="mtk1">, </span><span class="mtk12">column</span><span class="mtk1">.</span><span class="mtk12">id</span><span class="mtk1">, </span><span class="mtk12">value</span><span class="mtk1">)</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> }</span></span></span> <span class="grvsc-line"><span class="grvsc-source"></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk4">const</span><span class="mtk1"> </span><span class="mtk11">onSelectChange</span><span class="mtk1"> = (</span><span class="mtk12">e</span><span class="mtk1">: </span><span class="mtk10">ChangeEvent</span><span class="mtk1">&lt;</span><span class="mtk10">HTMLSelectElement</span><span class="mtk1">&gt;) </span><span class="mtk4">=&gt;</span><span class="mtk1"> {</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk11">setValue</span><span class="mtk1">(</span><span class="mtk12">e</span><span class="mtk1">.</span><span class="mtk12">target</span><span class="mtk1">.</span><span class="mtk12">value</span><span class="mtk1">)</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">tableMeta</span><span class="mtk1">?.</span><span class="mtk11">updateData</span><span class="mtk1">(</span><span class="mtk12">row</span><span class="mtk1">.</span><span class="mtk12">index</span><span class="mtk1">, </span><span class="mtk12">column</span><span class="mtk1">.</span><span class="mtk12">id</span><span class="mtk1">, </span><span class="mtk12">e</span><span class="mtk1">.</span><span class="mtk12">target</span><span class="mtk1">.</span><span class="mtk12">value</span><span class="mtk1">)</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> }</span></span></span> <span class="grvsc-line"><span class="grvsc-source"></span></span> <span class="grvsc-line grvsc-line-highlighted"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk15">if</span><span class="mtk1"> (</span><span class="mtk12">tableMeta</span><span class="mtk1">?.</span><span class="mtk12">editedRows</span><span class="mtk1">[</span><span class="mtk12">row</span><span class="mtk1">.</span><span class="mtk12">id</span><span class="mtk1">]) {</span></span></span> <span class="grvsc-line grvsc-line-highlighted"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk15">return</span><span class="mtk1"> </span><span class="mtk12">columnMeta</span><span class="mtk1">?.</span><span class="mtk12">type</span><span class="mtk1"> === </span><span class="mtk8">&quot;select&quot;</span><span class="mtk1"> ? (</span></span></span> <span class="grvsc-line grvsc-line-highlighted"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk17">&lt;</span><span class="mtk4">select</span><span class="mtk1"> </span><span class="mtk12">onChange</span><span class="mtk1">=</span><span class="mtk4">{</span><span class="mtk12">onSelectChange</span><span class="mtk4">}</span><span class="mtk1"> </span><span class="mtk12">value</span><span class="mtk1">=</span><span class="mtk4">{</span><span class="mtk12">initialValue</span><span class="mtk4">}</span><span class="mtk17">&gt;</span></span></span> <span class="grvsc-line grvsc-line-highlighted"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk4">{</span><span class="mtk12">columnMeta</span><span class="mtk1">?.</span><span class="mtk12">options</span><span class="mtk1">?.</span><span class="mtk11">map</span><span class="mtk1">((</span><span class="mtk12">option</span><span class="mtk1">: </span><span class="mtk10">Option</span><span class="mtk1">) </span><span class="mtk4">=&gt;</span><span class="mtk1"> (</span></span></span> <span class="grvsc-line grvsc-line-highlighted"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk17">&lt;</span><span class="mtk4">option</span><span class="mtk1"> </span><span class="mtk12">key</span><span class="mtk1">=</span><span class="mtk4">{</span><span class="mtk12">option</span><span class="mtk1">.</span><span class="mtk12">value</span><span class="mtk4">}</span><span class="mtk1"> </span><span class="mtk12">value</span><span class="mtk1">=</span><span class="mtk4">{</span><span class="mtk12">option</span><span class="mtk1">.</span><span class="mtk12">value</span><span class="mtk4">}</span><span class="mtk17">&gt;</span></span></span> <span class="grvsc-line grvsc-line-highlighted"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk4">{</span><span class="mtk12">option</span><span class="mtk1">.</span><span class="mtk12">label</span><span class="mtk4">}</span></span></span> <span class="grvsc-line grvsc-line-highlighted"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk17">&lt;/</span><span class="mtk4">option</span><span class="mtk17">&gt;</span></span></span> <span class="grvsc-line grvsc-line-highlighted"><span class="grvsc-source"><span class="mtk1"> ))</span><span class="mtk4">}</span></span></span> <span class="grvsc-line grvsc-line-highlighted"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk17">&lt;/</span><span class="mtk4">select</span><span class="mtk17">&gt;</span></span></span> <span class="grvsc-line grvsc-line-highlighted"><span class="grvsc-source"><span class="mtk1"> ) : (</span></span></span> <span class="grvsc-line grvsc-line-highlighted"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk17">&lt;</span><span class="mtk4">input</span></span></span> <span class="grvsc-line grvsc-line-highlighted"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">value</span><span class="mtk1">=</span><span class="mtk4">{</span><span class="mtk12">value</span><span class="mtk4">}</span></span></span> <span class="grvsc-line grvsc-line-highlighted"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">onChange</span><span class="mtk1">=</span><span class="mtk4">{</span><span class="mtk12">e</span><span class="mtk1"> </span><span class="mtk4">=&gt;</span><span class="mtk1"> </span><span class="mtk11">setValue</span><span class="mtk1">(</span><span class="mtk12">e</span><span class="mtk1">.</span><span class="mtk12">target</span><span class="mtk1">.</span><span class="mtk12">value</span><span class="mtk1">)</span><span class="mtk4">}</span></span></span> <span class="grvsc-line grvsc-line-highlighted"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">onBlur</span><span class="mtk1">=</span><span class="mtk4">{</span><span class="mtk12">onBlur</span><span class="mtk4">}</span></span></span> <span class="grvsc-line grvsc-line-highlighted"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">type</span><span class="mtk1">=</span><span class="mtk4">{</span><span class="mtk12">columnMeta</span><span class="mtk1">?.</span><span class="mtk12">type</span><span class="mtk1"> || </span><span class="mtk8">&quot;text&quot;</span><span class="mtk4">}</span></span></span> <span class="grvsc-line grvsc-line-highlighted"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk17">/&gt;</span></span></span> <span class="grvsc-line grvsc-line-highlighted"><span class="grvsc-source"><span class="mtk1"> )</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> }</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk15">return</span><span class="mtk1"> </span><span class="mtk17">&lt;</span><span class="mtk4">span</span><span class="mtk17">&gt;</span><span class="mtk4">{</span><span class="mtk12">value</span><span class="mtk4">}</span><span class="mtk17">&lt;/</span><span class="mtk4">span</span><span class="mtk17">&gt;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1">}</span></span></span></code></pre> <p>Last but not least, implementing a cancel action. While there are multiple ways to achieve that, depending on the business rules and the data flow, we’ll go with a simple approach for this tutorial.</p> <p>Let’s create an <code>originalData</code>, a copy of the <code>data</code> array. If the user chooses to save the row, it will update the <code>originalData</code> with the newly updated row. Otherwise, it will revert to the original row.</p> <p>In the Edtiable Table component, we can add a new state with a revert function.</p> <pre class="grvsc-container grvsc-has-line-highlighting default-dark" data-language="jsx" data-index="18"><code class="grvsc-code"><span class="grvsc-line"><span class="grvsc-source"><span class="mtk15">export</span><span class="mtk1"> </span><span class="mtk4">const</span><span class="mtk1"> </span><span class="mtk11">Table</span><span class="mtk1"> = () </span><span class="mtk4">=&gt;</span><span class="mtk1"> {</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk4">const</span><span class="mtk1"> [</span><span class="mtk12">data</span><span class="mtk1">, </span><span class="mtk12">setData</span><span class="mtk1">] = </span><span class="mtk11">useState</span><span class="mtk1">(() </span><span class="mtk4">=&gt;</span><span class="mtk1"> [...</span><span class="mtk12">defaultData</span><span class="mtk1">]);</span></span></span> <span class="grvsc-line grvsc-line-highlighted"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk4">const</span><span class="mtk1"> [</span><span class="mtk12">originalData</span><span class="mtk1">, </span><span class="mtk12">setOriginalData</span><span class="mtk1">] = </span><span class="mtk11">useState</span><span class="mtk1">(() </span><span class="mtk4">=&gt;</span><span class="mtk1"> [...</span><span class="mtk12">defaultData</span><span class="mtk1">]);</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk4">const</span><span class="mtk1"> [</span><span class="mtk12">editedRows</span><span class="mtk1">, </span><span class="mtk12">setEditedRows</span><span class="mtk1">] = </span><span class="mtk11">useState</span><span class="mtk1">({});</span></span></span> <span class="grvsc-line"><span class="grvsc-source"></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk4">const</span><span class="mtk1"> </span><span class="mtk12">table</span><span class="mtk1"> = </span><span class="mtk11">useReactTable</span><span class="mtk1">({</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">data</span><span class="mtk1">,</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">columns</span><span class="mtk1">,</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">getCoreRowModel:</span><span class="mtk1"> </span><span class="mtk11">getCoreRowModel</span><span class="mtk1">(),</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">meta:</span><span class="mtk1"> {</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">editedRows</span><span class="mtk1">,</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">setEditedRows</span><span class="mtk1">,</span></span></span> <span class="grvsc-line grvsc-line-highlighted"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk11">revertData</span><span class="mtk12">:</span><span class="mtk1"> (</span><span class="mtk12">rowIndex</span><span class="mtk1">: </span><span class="mtk10">number</span><span class="mtk1">, </span><span class="mtk12">revert</span><span class="mtk1">: </span><span class="mtk10">boolean</span><span class="mtk1">) </span><span class="mtk4">=&gt;</span><span class="mtk1"> {</span></span></span> <span class="grvsc-line grvsc-line-highlighted"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk15">if</span><span class="mtk1"> (</span><span class="mtk12">revert</span><span class="mtk1">) {</span></span></span> <span class="grvsc-line grvsc-line-highlighted"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk11">setData</span><span class="mtk1">((</span><span class="mtk12">old</span><span class="mtk1">) </span><span class="mtk4">=&gt;</span></span></span> <span class="grvsc-line grvsc-line-highlighted"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">old</span><span class="mtk1">.</span><span class="mtk11">map</span><span class="mtk1">((</span><span class="mtk12">row</span><span class="mtk1">, </span><span class="mtk12">index</span><span class="mtk1">) </span><span class="mtk4">=&gt;</span></span></span> <span class="grvsc-line grvsc-line-highlighted"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">index</span><span class="mtk1"> === </span><span class="mtk12">rowIndex</span><span class="mtk1"> ? </span><span class="mtk12">originalData</span><span class="mtk1">[</span><span class="mtk12">rowIndex</span><span class="mtk1">] : </span><span class="mtk12">row</span></span></span> <span class="grvsc-line grvsc-line-highlighted"><span class="grvsc-source"><span class="mtk1"> )</span></span></span> <span class="grvsc-line grvsc-line-highlighted"><span class="grvsc-source"><span class="mtk1"> );</span></span></span> <span class="grvsc-line grvsc-line-highlighted"><span class="grvsc-source"><span class="mtk1"> } </span><span class="mtk15">else</span><span class="mtk1"> {</span></span></span> <span class="grvsc-line grvsc-line-highlighted"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk11">setOriginalData</span><span class="mtk1">((</span><span class="mtk12">old</span><span class="mtk1">) </span><span class="mtk4">=&gt;</span></span></span> <span class="grvsc-line grvsc-line-highlighted"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">old</span><span class="mtk1">.</span><span class="mtk11">map</span><span class="mtk1">((</span><span class="mtk12">row</span><span class="mtk1">, </span><span class="mtk12">index</span><span class="mtk1">) </span><span class="mtk4">=&gt;</span><span class="mtk1"> (</span><span class="mtk12">index</span><span class="mtk1"> === </span><span class="mtk12">rowIndex</span><span class="mtk1"> ? </span><span class="mtk12">data</span><span class="mtk1">[</span><span class="mtk12">rowIndex</span><span class="mtk1">] : </span><span class="mtk12">row</span><span class="mtk1">))</span></span></span> <span class="grvsc-line grvsc-line-highlighted"><span class="grvsc-source"><span class="mtk1"> );</span></span></span> <span class="grvsc-line grvsc-line-highlighted"><span class="grvsc-source"><span class="mtk1"> }</span></span></span> <span class="grvsc-line grvsc-line-highlighted"><span class="grvsc-source"><span class="mtk1"> },</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">updateData:</span><span class="mtk1"> ...</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> });</span></span></span> <span class="grvsc-line"><span class="grvsc-source"></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk11">return</span><span class="mtk1"> (...);</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1">};</span></span></span></code></pre> <p>And in the <code>EditCell</code> component, we can call the function when the “cancel” or “done” buttons are triggered.</p> <pre class="grvsc-container grvsc-has-line-highlighting default-dark" data-language="jsx" data-index="19"><code class="grvsc-code"><span class="grvsc-line"><span class="grvsc-source"><span class="mtk4">const</span><span class="mtk1"> </span><span class="mtk11">EditCell</span><span class="mtk1"> = ({ </span><span class="mtk12">row</span><span class="mtk1">, </span><span class="mtk12">table</span><span class="mtk1"> }) </span><span class="mtk4">=&gt;</span><span class="mtk1"> {</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk4">const</span><span class="mtk1"> </span><span class="mtk12">meta</span><span class="mtk1"> = </span><span class="mtk12">table</span><span class="mtk1">.</span><span class="mtk12">options</span><span class="mtk1">.</span><span class="mtk12">meta</span></span></span> <span class="grvsc-line"><span class="grvsc-source"></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk4">const</span><span class="mtk1"> </span><span class="mtk11">setEditedRows</span><span class="mtk1"> = (</span><span class="mtk12">e</span><span class="mtk1">: </span><span class="mtk10">MouseEvent</span><span class="mtk1">&lt;</span><span class="mtk10">HTMLButtonElement</span><span class="mtk1">&gt;) </span><span class="mtk4">=&gt;</span><span class="mtk1"> {</span></span></span> <span class="grvsc-line grvsc-line-highlighted"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk4">const</span><span class="mtk1"> </span><span class="mtk12">elName</span><span class="mtk1"> = </span><span class="mtk12">e</span><span class="mtk1">.</span><span class="mtk12">currentTarget</span><span class="mtk1">.</span><span class="mtk12">name</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">meta</span><span class="mtk1">?.</span><span class="mtk11">setEditedRows</span><span class="mtk1">((</span><span class="mtk12">old</span><span class="mtk1">: []) </span><span class="mtk4">=&gt;</span><span class="mtk1"> ({</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> ...</span><span class="mtk12">old</span><span class="mtk1">,</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">[row.id]:</span><span class="mtk1"> !</span><span class="mtk12">old</span><span class="mtk1">[</span><span class="mtk12">row</span><span class="mtk1">.</span><span class="mtk12">id</span><span class="mtk1">],</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> }))</span></span></span> <span class="grvsc-line grvsc-line-highlighted"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk15">if</span><span class="mtk1"> (</span><span class="mtk12">elName</span><span class="mtk1"> !== </span><span class="mtk8">&quot;edit&quot;</span><span class="mtk1">) {</span></span></span> <span class="grvsc-line grvsc-line-highlighted"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">meta</span><span class="mtk1">?.</span><span class="mtk11">revertData</span><span class="mtk1">(</span><span class="mtk12">row</span><span class="mtk1">.</span><span class="mtk12">index</span><span class="mtk1">, </span><span class="mtk12">e</span><span class="mtk1">.</span><span class="mtk12">currentTarget</span><span class="mtk1">.</span><span class="mtk12">name</span><span class="mtk1"> === </span><span class="mtk8">&quot;cancel&quot;</span><span class="mtk1">)</span></span></span> <span class="grvsc-line grvsc-line-highlighted"><span class="grvsc-source"><span class="mtk1"> }</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> }</span></span></span> <span class="grvsc-line"><span class="grvsc-source"></span></span> <span class="grvsc-line grvsc-line-highlighted"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk15">return</span><span class="mtk1"> </span><span class="mtk12">meta</span><span class="mtk1">?.</span><span class="mtk12">editedRows</span><span class="mtk1">[</span><span class="mtk12">row</span><span class="mtk1">.</span><span class="mtk12">id</span><span class="mtk1">] ? (</span></span></span> <span class="grvsc-line grvsc-line-highlighted"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk17">&lt;&gt;</span></span></span> <span class="grvsc-line grvsc-line-highlighted"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk17">&lt;</span><span class="mtk4">button</span><span class="mtk1"> </span><span class="mtk12">onClick</span><span class="mtk1">=</span><span class="mtk4">{</span><span class="mtk12">setEditedRows</span><span class="mtk4">}</span><span class="mtk1"> </span><span class="mtk12">name</span><span class="mtk1">=</span><span class="mtk8">&quot;cancel&quot;</span><span class="mtk17">&gt;</span></span></span> <span class="grvsc-line grvsc-line-highlighted"><span class="grvsc-source"><span class="mtk1"> X</span></span></span> <span class="grvsc-line grvsc-line-highlighted"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk17">&lt;/</span><span class="mtk4">button</span><span class="mtk17">&gt;</span><span class="mtk4">{</span><span class="mtk8">&quot; &quot;</span><span class="mtk4">}</span></span></span> <span class="grvsc-line grvsc-line-highlighted"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk17">&lt;</span><span class="mtk4">button</span><span class="mtk1"> </span><span class="mtk12">onClick</span><span class="mtk1">=</span><span class="mtk4">{</span><span class="mtk12">setEditedRows</span><span class="mtk4">}</span><span class="mtk1"> </span><span class="mtk12">name</span><span class="mtk1">=</span><span class="mtk8">&quot;done&quot;</span><span class="mtk17">&gt;</span></span></span> <span class="grvsc-line grvsc-line-highlighted"><span class="grvsc-source"><span class="mtk1"> ✔</span></span></span> <span class="grvsc-line grvsc-line-highlighted"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk17">&lt;/</span><span class="mtk4">button</span><span class="mtk17">&gt;</span></span></span> <span class="grvsc-line grvsc-line-highlighted"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk17">&lt;/&gt;</span></span></span> <span class="grvsc-line grvsc-line-highlighted"><span class="grvsc-source"><span class="mtk1"> ) : (</span></span></span> <span class="grvsc-line grvsc-line-highlighted"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk17">&lt;</span><span class="mtk4">button</span><span class="mtk1"> </span><span class="mtk12">onClick</span><span class="mtk1">=</span><span class="mtk4">{</span><span class="mtk12">setEditedRows</span><span class="mtk4">}</span><span class="mtk1"> </span><span class="mtk12">name</span><span class="mtk1">=</span><span class="mtk8">&quot;edit&quot;</span><span class="mtk17">&gt;</span></span></span> <span class="grvsc-line grvsc-line-highlighted"><span class="grvsc-source"><span class="mtk1"> ✐</span></span></span> <span class="grvsc-line grvsc-line-highlighted"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk17">&lt;/</span><span class="mtk4">button</span><span class="mtk17">&gt;</span></span></span> <span class="grvsc-line grvsc-line-highlighted"><span class="grvsc-source"><span class="mtk1"> )</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1">}</span></span></span></code></pre> <p>Here is the code and demo of what we have so far.</p> <pre class="grvsc-container default-dark" data-language="jsx" data-index="20"><code class="grvsc-code"><span class="grvsc-line"><span class="grvsc-source"><span class="mtk15">import</span><span class="mtk1"> { </span><span class="mtk12">useState</span><span class="mtk1">, </span><span class="mtk12">useEffect</span><span class="mtk1">, </span><span class="mtk12">ChangeEvent</span><span class="mtk1">, </span><span class="mtk12">MouseEvent</span><span class="mtk1"> } </span><span class="mtk15">from</span><span class="mtk1"> </span><span class="mtk8">&quot;react&quot;</span><span class="mtk1">;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk15">import</span><span class="mtk1"> </span><span class="mtk8">&quot;./table.css&quot;</span><span class="mtk1">;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk15">import</span><span class="mtk1"> {</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">createColumnHelper</span><span class="mtk1">,</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">flexRender</span><span class="mtk1">,</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">getCoreRowModel</span><span class="mtk1">,</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">useReactTable</span><span class="mtk1">,</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1">} </span><span class="mtk15">from</span><span class="mtk1"> </span><span class="mtk8">&quot;@tanstack/react-table&quot;</span><span class="mtk1">;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk4">type</span><span class="mtk1"> </span><span class="mtk10">Student</span><span class="mtk1"> = {</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">studentId</span><span class="mtk1">: </span><span class="mtk10">number</span><span class="mtk1">;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">name</span><span class="mtk1">: </span><span class="mtk10">string</span><span class="mtk1">;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">dateOfBirth</span><span class="mtk1">: </span><span class="mtk10">string</span><span class="mtk1">;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">major</span><span class="mtk1">: </span><span class="mtk10">string</span><span class="mtk1">;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1">};</span></span></span> <span class="grvsc-line"><span class="grvsc-source"></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk4">type</span><span class="mtk1"> </span><span class="mtk10">Option</span><span class="mtk1"> = {</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">label</span><span class="mtk1">: </span><span class="mtk10">string</span><span class="mtk1">;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">value</span><span class="mtk1">: </span><span class="mtk10">string</span><span class="mtk1">;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1">};</span></span></span> <span class="grvsc-line"><span class="grvsc-source"></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk4">const</span><span class="mtk1"> </span><span class="mtk12">defaultData</span><span class="mtk1">: </span><span class="mtk10">Student</span><span class="mtk1">[] = [</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> {</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">studentId:</span><span class="mtk1"> </span><span class="mtk7">1111</span><span class="mtk1">,</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">name:</span><span class="mtk1"> </span><span class="mtk8">&quot;Bahar Constantia&quot;</span><span class="mtk1">,</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">dateOfBirth:</span><span class="mtk1"> </span><span class="mtk8">&quot;1984-01-04&quot;</span><span class="mtk1">,</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">major:</span><span class="mtk1"> </span><span class="mtk8">&quot;Computer Science&quot;</span><span class="mtk1">,</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> },</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> {</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">studentId:</span><span class="mtk1"> </span><span class="mtk7">2222</span><span class="mtk1">,</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">name:</span><span class="mtk1"> </span><span class="mtk8">&quot;Harold Nona&quot;</span><span class="mtk1">,</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">dateOfBirth:</span><span class="mtk1"> </span><span class="mtk8">&quot;1961-05-10&quot;</span><span class="mtk1">,</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">major:</span><span class="mtk1"> </span><span class="mtk8">&quot;Communications&quot;</span><span class="mtk1">,</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> },</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> {</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">studentId:</span><span class="mtk1"> </span><span class="mtk7">3333</span><span class="mtk1">,</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">name:</span><span class="mtk1"> </span><span class="mtk8">&quot;Raginolf Arnulf&quot;</span><span class="mtk1">,</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">dateOfBirth:</span><span class="mtk1"> </span><span class="mtk8">&quot;1991-10-12&quot;</span><span class="mtk1">,</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">major:</span><span class="mtk1"> </span><span class="mtk8">&quot;Business&quot;</span><span class="mtk1">,</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> },</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> {</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">studentId:</span><span class="mtk1"> </span><span class="mtk7">4444</span><span class="mtk1">,</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">name:</span><span class="mtk1"> </span><span class="mtk8">&quot;Marvyn Wendi&quot;</span><span class="mtk1">,</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">dateOfBirth:</span><span class="mtk1"> </span><span class="mtk8">&quot;1978-09-24&quot;</span><span class="mtk1">,</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">major:</span><span class="mtk1"> </span><span class="mtk8">&quot;Psychology&quot;</span><span class="mtk1">,</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> },</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1">];</span></span></span> <span class="grvsc-line"><span class="grvsc-source"></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk4">const</span><span class="mtk1"> </span><span class="mtk11">TableCell</span><span class="mtk1"> = ({ </span><span class="mtk12">getValue</span><span class="mtk1">, </span><span class="mtk12">row</span><span class="mtk1">, </span><span class="mtk12">column</span><span class="mtk1">, </span><span class="mtk12">table</span><span class="mtk1"> }) </span><span class="mtk4">=&gt;</span><span class="mtk1"> {</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk4">const</span><span class="mtk1"> </span><span class="mtk12">initialValue</span><span class="mtk1"> = </span><span class="mtk11">getValue</span><span class="mtk1">();</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk4">const</span><span class="mtk1"> </span><span class="mtk12">columnMeta</span><span class="mtk1"> = </span><span class="mtk12">column</span><span class="mtk1">.</span><span class="mtk12">columnDef</span><span class="mtk1">.</span><span class="mtk12">meta</span><span class="mtk1">;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk4">const</span><span class="mtk1"> </span><span class="mtk12">tableMeta</span><span class="mtk1"> = </span><span class="mtk12">table</span><span class="mtk1">.</span><span class="mtk12">options</span><span class="mtk1">.</span><span class="mtk12">meta</span><span class="mtk1">;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk4">const</span><span class="mtk1"> [</span><span class="mtk12">value</span><span class="mtk1">, </span><span class="mtk12">setValue</span><span class="mtk1">] = </span><span class="mtk11">useState</span><span class="mtk1">(</span><span class="mtk12">initialValue</span><span class="mtk1">);</span></span></span> <span class="grvsc-line"><span class="grvsc-source"></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk11">useEffect</span><span class="mtk1">(() </span><span class="mtk4">=&gt;</span><span class="mtk1"> {</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk11">setValue</span><span class="mtk1">(</span><span class="mtk12">initialValue</span><span class="mtk1">);</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> }, [</span><span class="mtk12">initialValue</span><span class="mtk1">]);</span></span></span> <span class="grvsc-line"><span class="grvsc-source"></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk4">const</span><span class="mtk1"> </span><span class="mtk11">onBlur</span><span class="mtk1"> = () </span><span class="mtk4">=&gt;</span><span class="mtk1"> {</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">tableMeta</span><span class="mtk1">?.</span><span class="mtk11">updateData</span><span class="mtk1">(</span><span class="mtk12">row</span><span class="mtk1">.</span><span class="mtk12">index</span><span class="mtk1">, </span><span class="mtk12">column</span><span class="mtk1">.</span><span class="mtk12">id</span><span class="mtk1">, </span><span class="mtk12">value</span><span class="mtk1">);</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> };</span></span></span> <span class="grvsc-line"><span class="grvsc-source"></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk4">const</span><span class="mtk1"> </span><span class="mtk11">onSelectChange</span><span class="mtk1"> = (</span><span class="mtk12">e</span><span class="mtk1">: </span><span class="mtk10">ChangeEvent</span><span class="mtk1">&lt;</span><span class="mtk10">HTMLSelectElement</span><span class="mtk1">&gt;) </span><span class="mtk4">=&gt;</span><span class="mtk1"> {</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk11">setValue</span><span class="mtk1">(</span><span class="mtk12">e</span><span class="mtk1">.</span><span class="mtk12">target</span><span class="mtk1">.</span><span class="mtk12">value</span><span class="mtk1">);</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">tableMeta</span><span class="mtk1">?.</span><span class="mtk11">updateData</span><span class="mtk1">(</span><span class="mtk12">row</span><span class="mtk1">.</span><span class="mtk12">index</span><span class="mtk1">, </span><span class="mtk12">column</span><span class="mtk1">.</span><span class="mtk12">id</span><span class="mtk1">, </span><span class="mtk12">e</span><span class="mtk1">.</span><span class="mtk12">target</span><span class="mtk1">.</span><span class="mtk12">value</span><span class="mtk1">);</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> };</span></span></span> <span class="grvsc-line"><span class="grvsc-source"></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk15">if</span><span class="mtk1"> (</span><span class="mtk12">tableMeta</span><span class="mtk1">?.</span><span class="mtk12">editedRows</span><span class="mtk1">[</span><span class="mtk12">row</span><span class="mtk1">.</span><span class="mtk12">id</span><span class="mtk1">]) {</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk15">return</span><span class="mtk1"> </span><span class="mtk12">columnMeta</span><span class="mtk1">?.</span><span class="mtk12">type</span><span class="mtk1"> === </span><span class="mtk8">&quot;select&quot;</span><span class="mtk1"> ? (</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk17">&lt;</span><span class="mtk4">select</span><span class="mtk1"> </span><span class="mtk12">onChange</span><span class="mtk1">=</span><span class="mtk4">{</span><span class="mtk12">onSelectChange</span><span class="mtk4">}</span><span class="mtk1"> </span><span class="mtk12">value</span><span class="mtk1">=</span><span class="mtk4">{</span><span class="mtk12">initialValue</span><span class="mtk4">}</span><span class="mtk17">&gt;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk4">{</span><span class="mtk12">columnMeta</span><span class="mtk1">?.</span><span class="mtk12">options</span><span class="mtk1">?.</span><span class="mtk11">map</span><span class="mtk1">((</span><span class="mtk12">option</span><span class="mtk1">: </span><span class="mtk10">Option</span><span class="mtk1">) </span><span class="mtk4">=&gt;</span><span class="mtk1"> (</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk17">&lt;</span><span class="mtk4">option</span><span class="mtk1"> </span><span class="mtk12">key</span><span class="mtk1">=</span><span class="mtk4">{</span><span class="mtk12">option</span><span class="mtk1">.</span><span class="mtk12">value</span><span class="mtk4">}</span><span class="mtk1"> </span><span class="mtk12">value</span><span class="mtk1">=</span><span class="mtk4">{</span><span class="mtk12">option</span><span class="mtk1">.</span><span class="mtk12">value</span><span class="mtk4">}</span><span class="mtk17">&gt;</span><span class="mtk4">{</span><span class="mtk12">option</span><span class="mtk1">.</span><span class="mtk12">label</span><span class="mtk4">}</span><span class="mtk17">&lt;/</span><span class="mtk4">option</span><span class="mtk17">&gt;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> ))</span><span class="mtk4">}</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk17">&lt;/</span><span class="mtk4">select</span><span class="mtk17">&gt;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> ) : (</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk17">&lt;</span><span class="mtk4">input</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">value</span><span class="mtk1">=</span><span class="mtk4">{</span><span class="mtk12">value</span><span class="mtk4">}</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">onChange</span><span class="mtk1">=</span><span class="mtk4">{</span><span class="mtk1">(</span><span class="mtk12">e</span><span class="mtk1">) </span><span class="mtk4">=&gt;</span><span class="mtk1"> </span><span class="mtk11">setValue</span><span class="mtk1">(</span><span class="mtk12">e</span><span class="mtk1">.</span><span class="mtk12">target</span><span class="mtk1">.</span><span class="mtk12">value</span><span class="mtk1">)</span><span class="mtk4">}</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">onBlur</span><span class="mtk1">=</span><span class="mtk4">{</span><span class="mtk12">onBlur</span><span class="mtk4">}</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">type</span><span class="mtk1">=</span><span class="mtk4">{</span><span class="mtk12">columnMeta</span><span class="mtk1">?.</span><span class="mtk12">type</span><span class="mtk1"> || </span><span class="mtk8">&quot;text&quot;</span><span class="mtk4">}</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk17">/&gt;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> );</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> }</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk15">return</span><span class="mtk1"> </span><span class="mtk17">&lt;</span><span class="mtk4">span</span><span class="mtk17">&gt;</span><span class="mtk4">{</span><span class="mtk12">value</span><span class="mtk4">}</span><span class="mtk17">&lt;/</span><span class="mtk4">span</span><span class="mtk17">&gt;</span><span class="mtk1">;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1">};</span></span></span> <span class="grvsc-line"><span class="grvsc-source"></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk4">const</span><span class="mtk1"> </span><span class="mtk11">EditCell</span><span class="mtk1"> = ({ </span><span class="mtk12">row</span><span class="mtk1">, </span><span class="mtk12">table</span><span class="mtk1"> }) </span><span class="mtk4">=&gt;</span><span class="mtk1"> {</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk4">const</span><span class="mtk1"> </span><span class="mtk12">meta</span><span class="mtk1"> = </span><span class="mtk12">table</span><span class="mtk1">.</span><span class="mtk12">options</span><span class="mtk1">.</span><span class="mtk12">meta</span><span class="mtk1">;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk4">const</span><span class="mtk1"> </span><span class="mtk11">setEditedRows</span><span class="mtk1"> = (</span><span class="mtk12">e</span><span class="mtk1">: </span><span class="mtk10">MouseEvent</span><span class="mtk1">&lt;</span><span class="mtk10">HTMLButtonElement</span><span class="mtk1">&gt;) </span><span class="mtk4">=&gt;</span><span class="mtk1"> {</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk4">const</span><span class="mtk1"> </span><span class="mtk12">elName</span><span class="mtk1"> = </span><span class="mtk12">e</span><span class="mtk1">.</span><span class="mtk12">currentTarget</span><span class="mtk1">.</span><span class="mtk12">name</span><span class="mtk1">;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">meta</span><span class="mtk1">?.</span><span class="mtk11">setEditedRows</span><span class="mtk1">((</span><span class="mtk12">old</span><span class="mtk1">: []) </span><span class="mtk4">=&gt;</span><span class="mtk1"> ({</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> ...</span><span class="mtk12">old</span><span class="mtk1">,</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">[row.id]:</span><span class="mtk1"> !</span><span class="mtk12">old</span><span class="mtk1">[</span><span class="mtk12">row</span><span class="mtk1">.</span><span class="mtk12">id</span><span class="mtk1">],</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> }));</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk15">if</span><span class="mtk1"> (</span><span class="mtk12">elName</span><span class="mtk1"> !== </span><span class="mtk8">&quot;edit&quot;</span><span class="mtk1">) {</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">meta</span><span class="mtk1">?.</span><span class="mtk11">revertData</span><span class="mtk1">(</span><span class="mtk12">row</span><span class="mtk1">.</span><span class="mtk12">index</span><span class="mtk1">, </span><span class="mtk12">e</span><span class="mtk1">.</span><span class="mtk12">currentTarget</span><span class="mtk1">.</span><span class="mtk12">name</span><span class="mtk1"> === </span><span class="mtk8">&quot;cancel&quot;</span><span class="mtk1">);</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> }</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> };</span></span></span> <span class="grvsc-line"><span class="grvsc-source"></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk15">return</span><span class="mtk1"> (</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk17">&lt;</span><span class="mtk4">div</span><span class="mtk1"> </span><span class="mtk12">className</span><span class="mtk1">=</span><span class="mtk8">&quot;edit-cell-container&quot;</span><span class="mtk17">&gt;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk4">{</span><span class="mtk12">meta</span><span class="mtk1">?.</span><span class="mtk12">editedRows</span><span class="mtk1">[</span><span class="mtk12">row</span><span class="mtk1">.</span><span class="mtk12">id</span><span class="mtk1">] ? (</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk17">&lt;</span><span class="mtk4">div</span><span class="mtk1"> </span><span class="mtk12">className</span><span class="mtk1">=</span><span class="mtk8">&quot;edit-cell&quot;</span><span class="mtk17">&gt;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk17">&lt;</span><span class="mtk4">button</span><span class="mtk1"> </span><span class="mtk12">onClick</span><span class="mtk1">=</span><span class="mtk4">{</span><span class="mtk12">setEditedRows</span><span class="mtk4">}</span><span class="mtk1"> </span><span class="mtk12">name</span><span class="mtk1">=</span><span class="mtk8">&quot;cancel&quot;</span><span class="mtk17">&gt;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> X</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk17">&lt;/</span><span class="mtk4">button</span><span class="mtk17">&gt;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk17">&lt;</span><span class="mtk4">button</span><span class="mtk1"> </span><span class="mtk12">onClick</span><span class="mtk1">=</span><span class="mtk4">{</span><span class="mtk12">setEditedRows</span><span class="mtk4">}</span><span class="mtk1"> </span><span class="mtk12">name</span><span class="mtk1">=</span><span class="mtk8">&quot;done&quot;</span><span class="mtk17">&gt;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> ✔</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk17">&lt;/</span><span class="mtk4">button</span><span class="mtk17">&gt;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk17">&lt;/</span><span class="mtk4">div</span><span class="mtk17">&gt;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> ) : (</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk17">&lt;</span><span class="mtk4">button</span><span class="mtk1"> </span><span class="mtk12">onClick</span><span class="mtk1">=</span><span class="mtk4">{</span><span class="mtk12">setEditedRows</span><span class="mtk4">}</span><span class="mtk1"> </span><span class="mtk12">name</span><span class="mtk1">=</span><span class="mtk8">&quot;edit&quot;</span><span class="mtk17">&gt;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> ✐</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk17">&lt;/</span><span class="mtk4">button</span><span class="mtk17">&gt;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> )</span><span class="mtk4">}</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk17">&lt;/</span><span class="mtk4">div</span><span class="mtk17">&gt;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> );</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1">};</span></span></span> <span class="grvsc-line"><span class="grvsc-source"></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk4">const</span><span class="mtk1"> </span><span class="mtk12">columnHelper</span><span class="mtk1"> = </span><span class="mtk11">createColumnHelper</span><span class="mtk1">&lt;</span><span class="mtk10">Student</span><span class="mtk1">&gt;();</span></span></span> <span class="grvsc-line"><span class="grvsc-source"></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk4">const</span><span class="mtk1"> </span><span class="mtk12">columns</span><span class="mtk1"> = [</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">columnHelper</span><span class="mtk1">.</span><span class="mtk11">accessor</span><span class="mtk1">(</span><span class="mtk8">&quot;studentId&quot;</span><span class="mtk1">, {</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">header:</span><span class="mtk1"> </span><span class="mtk8">&quot;Student ID&quot;</span><span class="mtk1">,</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">cell:</span><span class="mtk1"> </span><span class="mtk12">TableCell</span><span class="mtk1">,</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">meta:</span><span class="mtk1"> {</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">type:</span><span class="mtk1"> </span><span class="mtk8">&quot;number&quot;</span><span class="mtk1">,</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> },</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> }),</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">columnHelper</span><span class="mtk1">.</span><span class="mtk11">accessor</span><span class="mtk1">(</span><span class="mtk8">&quot;name&quot;</span><span class="mtk1">, {</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">header:</span><span class="mtk1"> </span><span class="mtk8">&quot;Full Name&quot;</span><span class="mtk1">,</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">cell:</span><span class="mtk1"> </span><span class="mtk12">TableCell</span><span class="mtk1">,</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">meta:</span><span class="mtk1"> {</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">type:</span><span class="mtk1"> </span><span class="mtk8">&quot;text&quot;</span><span class="mtk1">,</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> },</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> }),</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">columnHelper</span><span class="mtk1">.</span><span class="mtk11">accessor</span><span class="mtk1">(</span><span class="mtk8">&quot;dateOfBirth&quot;</span><span class="mtk1">, {</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">header:</span><span class="mtk1"> </span><span class="mtk8">&quot;Date Of Birth&quot;</span><span class="mtk1">,</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">cell:</span><span class="mtk1"> </span><span class="mtk12">TableCell</span><span class="mtk1">,</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">meta:</span><span class="mtk1"> {</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">type:</span><span class="mtk1"> </span><span class="mtk8">&quot;date&quot;</span><span class="mtk1">,</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> },</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> }),</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">columnHelper</span><span class="mtk1">.</span><span class="mtk11">accessor</span><span class="mtk1">(</span><span class="mtk8">&quot;major&quot;</span><span class="mtk1">, {</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">header:</span><span class="mtk1"> </span><span class="mtk8">&quot;Major&quot;</span><span class="mtk1">,</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">cell:</span><span class="mtk1"> </span><span class="mtk12">TableCell</span><span class="mtk1">,</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">meta:</span><span class="mtk1"> {</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">type:</span><span class="mtk1"> </span><span class="mtk8">&quot;select&quot;</span><span class="mtk1">,</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">options:</span><span class="mtk1"> [</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> { </span><span class="mtk12">value:</span><span class="mtk1"> </span><span class="mtk8">&quot;Computer Science&quot;</span><span class="mtk1">, </span><span class="mtk12">label:</span><span class="mtk1"> </span><span class="mtk8">&quot;Computer Science&quot;</span><span class="mtk1"> },</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> { </span><span class="mtk12">value:</span><span class="mtk1"> </span><span class="mtk8">&quot;Communications&quot;</span><span class="mtk1">, </span><span class="mtk12">label:</span><span class="mtk1"> </span><span class="mtk8">&quot;Communications&quot;</span><span class="mtk1"> },</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> { </span><span class="mtk12">value:</span><span class="mtk1"> </span><span class="mtk8">&quot;Business&quot;</span><span class="mtk1">, </span><span class="mtk12">label:</span><span class="mtk1"> </span><span class="mtk8">&quot;Business&quot;</span><span class="mtk1"> },</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> { </span><span class="mtk12">value:</span><span class="mtk1"> </span><span class="mtk8">&quot;Psychology&quot;</span><span class="mtk1">, </span><span class="mtk12">label:</span><span class="mtk1"> </span><span class="mtk8">&quot;Psychology&quot;</span><span class="mtk1"> },</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> ],</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> },</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> }),</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">columnHelper</span><span class="mtk1">.</span><span class="mtk11">display</span><span class="mtk1">({</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">id:</span><span class="mtk1"> </span><span class="mtk8">&quot;edit&quot;</span><span class="mtk1">,</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">cell:</span><span class="mtk1"> </span><span class="mtk12">EditCell</span><span class="mtk1">,</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> }),</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1">];</span></span></span> <span class="grvsc-line"><span class="grvsc-source"></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk15">export</span><span class="mtk1"> </span><span class="mtk4">const</span><span class="mtk1"> </span><span class="mtk11">Table</span><span class="mtk1"> = () </span><span class="mtk4">=&gt;</span><span class="mtk1"> {</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk4">const</span><span class="mtk1"> [</span><span class="mtk12">data</span><span class="mtk1">, </span><span class="mtk12">setData</span><span class="mtk1">] = </span><span class="mtk11">useState</span><span class="mtk1">(() </span><span class="mtk4">=&gt;</span><span class="mtk1"> [...</span><span class="mtk12">defaultData</span><span class="mtk1">]);</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk4">const</span><span class="mtk1"> [</span><span class="mtk12">originalData</span><span class="mtk1">, </span><span class="mtk12">setOriginalData</span><span class="mtk1">] = </span><span class="mtk11">useState</span><span class="mtk1">(() </span><span class="mtk4">=&gt;</span><span class="mtk1"> [...</span><span class="mtk12">defaultData</span><span class="mtk1">]);</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk4">const</span><span class="mtk1"> [</span><span class="mtk12">editedRows</span><span class="mtk1">, </span><span class="mtk12">setEditedRows</span><span class="mtk1">] = </span><span class="mtk11">useState</span><span class="mtk1">({});</span></span></span> <span class="grvsc-line"><span class="grvsc-source"></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk4">const</span><span class="mtk1"> </span><span class="mtk12">table</span><span class="mtk1"> = </span><span class="mtk11">useReactTable</span><span class="mtk1">({</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">data</span><span class="mtk1">,</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">columns</span><span class="mtk1">,</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">getCoreRowModel:</span><span class="mtk1"> </span><span class="mtk11">getCoreRowModel</span><span class="mtk1">(),</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">meta:</span><span class="mtk1"> {</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">editedRows</span><span class="mtk1">,</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">setEditedRows</span><span class="mtk1">,</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk11">revertData</span><span class="mtk12">:</span><span class="mtk1"> (</span><span class="mtk12">rowIndex</span><span class="mtk1">: </span><span class="mtk10">number</span><span class="mtk1">, </span><span class="mtk12">revert</span><span class="mtk1">: </span><span class="mtk10">boolean</span><span class="mtk1">) </span><span class="mtk4">=&gt;</span><span class="mtk1"> {</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk15">if</span><span class="mtk1"> (</span><span class="mtk12">revert</span><span class="mtk1">) {</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk11">setData</span><span class="mtk1">((</span><span class="mtk12">old</span><span class="mtk1">) </span><span class="mtk4">=&gt;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">old</span><span class="mtk1">.</span><span class="mtk11">map</span><span class="mtk1">((</span><span class="mtk12">row</span><span class="mtk1">, </span><span class="mtk12">index</span><span class="mtk1">) </span><span class="mtk4">=&gt;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">index</span><span class="mtk1"> === </span><span class="mtk12">rowIndex</span><span class="mtk1"> ? </span><span class="mtk12">originalData</span><span class="mtk1">[</span><span class="mtk12">rowIndex</span><span class="mtk1">] : </span><span class="mtk12">row</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> )</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> );</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> } </span><span class="mtk15">else</span><span class="mtk1"> {</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk11">setOriginalData</span><span class="mtk1">((</span><span class="mtk12">old</span><span class="mtk1">) </span><span class="mtk4">=&gt;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">old</span><span class="mtk1">.</span><span class="mtk11">map</span><span class="mtk1">((</span><span class="mtk12">row</span><span class="mtk1">, </span><span class="mtk12">index</span><span class="mtk1">) </span><span class="mtk4">=&gt;</span><span class="mtk1"> (</span><span class="mtk12">index</span><span class="mtk1"> === </span><span class="mtk12">rowIndex</span><span class="mtk1"> ? </span><span class="mtk12">data</span><span class="mtk1">[</span><span class="mtk12">rowIndex</span><span class="mtk1">] : </span><span class="mtk12">row</span><span class="mtk1">))</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> );</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> }</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> },</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk11">updateData</span><span class="mtk12">:</span><span class="mtk1"> (</span><span class="mtk12">rowIndex</span><span class="mtk1">: </span><span class="mtk10">number</span><span class="mtk1">, </span><span class="mtk12">columnId</span><span class="mtk1">: </span><span class="mtk10">string</span><span class="mtk1">, </span><span class="mtk12">value</span><span class="mtk1">: </span><span class="mtk10">string</span><span class="mtk1">) </span><span class="mtk4">=&gt;</span><span class="mtk1"> {</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk11">setData</span><span class="mtk1">((</span><span class="mtk12">old</span><span class="mtk1">) </span><span class="mtk4">=&gt;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">old</span><span class="mtk1">.</span><span class="mtk11">map</span><span class="mtk1">((</span><span class="mtk12">row</span><span class="mtk1">, </span><span class="mtk12">index</span><span class="mtk1">) </span><span class="mtk4">=&gt;</span><span class="mtk1"> {</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk15">if</span><span class="mtk1"> (</span><span class="mtk12">index</span><span class="mtk1"> === </span><span class="mtk12">rowIndex</span><span class="mtk1">) {</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk15">return</span><span class="mtk1"> {</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> ...</span><span class="mtk12">old</span><span class="mtk1">[</span><span class="mtk12">rowIndex</span><span class="mtk1">],</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">[columnId]:</span><span class="mtk1"> </span><span class="mtk12">value</span><span class="mtk1">,</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> };</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> }</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk15">return</span><span class="mtk1"> </span><span class="mtk12">row</span><span class="mtk1">;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> })</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> );</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> },</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> },</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> });</span></span></span> <span class="grvsc-line"><span class="grvsc-source"></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk15">return</span><span class="mtk1"> (</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk17">&lt;&gt;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk17">&lt;</span><span class="mtk4">table</span><span class="mtk17">&gt;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk17">&lt;</span><span class="mtk4">thead</span><span class="mtk17">&gt;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk4">{</span><span class="mtk12">table</span><span class="mtk1">.</span><span class="mtk11">getHeaderGroups</span><span class="mtk1">().</span><span class="mtk11">map</span><span class="mtk1">((</span><span class="mtk12">headerGroup</span><span class="mtk1">) </span><span class="mtk4">=&gt;</span><span class="mtk1"> (</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk17">&lt;</span><span class="mtk4">tr</span><span class="mtk1"> </span><span class="mtk12">key</span><span class="mtk1">=</span><span class="mtk4">{</span><span class="mtk12">headerGroup</span><span class="mtk1">.</span><span class="mtk12">id</span><span class="mtk4">}</span><span class="mtk17">&gt;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk4">{</span><span class="mtk12">headerGroup</span><span class="mtk1">.</span><span class="mtk12">headers</span><span class="mtk1">.</span><span class="mtk11">map</span><span class="mtk1">((</span><span class="mtk12">header</span><span class="mtk1">) </span><span class="mtk4">=&gt;</span><span class="mtk1"> (</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk17">&lt;</span><span class="mtk4">th</span><span class="mtk1"> </span><span class="mtk12">key</span><span class="mtk1">=</span><span class="mtk4">{</span><span class="mtk12">header</span><span class="mtk1">.</span><span class="mtk12">id</span><span class="mtk4">}</span><span class="mtk17">&gt;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk4">{</span><span class="mtk12">header</span><span class="mtk1">.</span><span class="mtk12">isPlaceholder</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> ? </span><span class="mtk4">null</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> : </span><span class="mtk11">flexRender</span><span class="mtk1">(</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">header</span><span class="mtk1">.</span><span class="mtk12">column</span><span class="mtk1">.</span><span class="mtk12">columnDef</span><span class="mtk1">.</span><span class="mtk12">header</span><span class="mtk1">,</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">header</span><span class="mtk1">.</span><span class="mtk11">getContext</span><span class="mtk1">()</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> )</span><span class="mtk4">}</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk17">&lt;/</span><span class="mtk4">th</span><span class="mtk17">&gt;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> ))</span><span class="mtk4">}</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk17">&lt;/</span><span class="mtk4">tr</span><span class="mtk17">&gt;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> ))</span><span class="mtk4">}</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk17">&lt;/</span><span class="mtk4">thead</span><span class="mtk17">&gt;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk17">&lt;</span><span class="mtk4">tbody</span><span class="mtk17">&gt;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk4">{</span><span class="mtk12">table</span><span class="mtk1">.</span><span class="mtk11">getRowModel</span><span class="mtk1">().</span><span class="mtk12">rows</span><span class="mtk1">.</span><span class="mtk11">map</span><span class="mtk1">((</span><span class="mtk12">row</span><span class="mtk1">) </span><span class="mtk4">=&gt;</span><span class="mtk1"> (</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk17">&lt;</span><span class="mtk4">tr</span><span class="mtk1"> </span><span class="mtk12">key</span><span class="mtk1">=</span><span class="mtk4">{</span><span class="mtk12">row</span><span class="mtk1">.</span><span class="mtk12">id</span><span class="mtk4">}</span><span class="mtk17">&gt;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk4">{</span><span class="mtk12">row</span><span class="mtk1">.</span><span class="mtk11">getVisibleCells</span><span class="mtk1">().</span><span class="mtk11">map</span><span class="mtk1">((</span><span class="mtk12">cell</span><span class="mtk1">) </span><span class="mtk4">=&gt;</span><span class="mtk1"> (</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk17">&lt;</span><span class="mtk4">td</span><span class="mtk1"> </span><span class="mtk12">key</span><span class="mtk1">=</span><span class="mtk4">{</span><span class="mtk12">cell</span><span class="mtk1">.</span><span class="mtk12">id</span><span class="mtk4">}</span><span class="mtk17">&gt;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk4">{</span><span class="mtk11">flexRender</span><span class="mtk1">(</span><span class="mtk12">cell</span><span class="mtk1">.</span><span class="mtk12">column</span><span class="mtk1">.</span><span class="mtk12">columnDef</span><span class="mtk1">.</span><span class="mtk12">cell</span><span class="mtk1">, </span><span class="mtk12">cell</span><span class="mtk1">.</span><span class="mtk11">getContext</span><span class="mtk1">())</span><span class="mtk4">}</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk17">&lt;/</span><span class="mtk4">td</span><span class="mtk17">&gt;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> ))</span><span class="mtk4">}</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk17">&lt;/</span><span class="mtk4">tr</span><span class="mtk17">&gt;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> ))</span><span class="mtk4">}</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk17">&lt;/</span><span class="mtk4">tbody</span><span class="mtk17">&gt;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk17">&lt;/</span><span class="mtk4">table</span><span class="mtk17">&gt;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk17">&lt;</span><span class="mtk4">pre</span><span class="mtk17">&gt;</span><span class="mtk4">{</span><span class="mtk10">JSON</span><span class="mtk1">.</span><span class="mtk11">stringify</span><span class="mtk1">(</span><span class="mtk12">data</span><span class="mtk1">, </span><span class="mtk4">null</span><span class="mtk1">, </span><span class="mtk8">&quot;</span><span class="mtk6">\t</span><span class="mtk8">&quot;</span><span class="mtk1">)</span><span class="mtk4">}</span><span class="mtk17">&lt;/</span><span class="mtk4">pre</span><span class="mtk17">&gt;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk17">&lt;/&gt;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> );</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1">};</span></span></span></code></pre> <div id="ReactEditableTableFour" data-code data-height="800px"></div> <h2 id="table-styling-and-restructuring" style="position:relative;"><a href="#table-styling-and-restructuring" aria-label="table styling and restructuring permalink" class="anchor before"><svg aria-hidden="true" focusable="false" height="16" version="1.1" viewBox="0 0 16 16" width="16"><path fill-rule="evenodd" d="M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z"></path></svg></a>Table styling and restructuring</h2> <p>Restructuring is as simple as extracting each component into its own <code>tsx</code> file to make the main table component smaller and leaner and eventually easier to maintain.</p> <p>Here are all the components that we would like to extract into a separate file:</p> <p><span class="gatsby-resp-image-wrapper" style="position: relative; display: block; margin-left: auto; margin-right: auto; max-width: 472px; " > <a class="gatsby-resp-image-link" href="/static/0b8bd7a5146d29ff80e36f74a8ee75a3/3c5de/code-restructure.png" style="display: block" target="_blank" rel="noopener" > <span class="gatsby-resp-image-background-image" style="padding-bottom: 155.55555555555554%; position: relative; bottom: 0; left: 0; background-image: url('data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABQAAAAfCAYAAADnTu3OAAAACXBIWXMAACToAAAk6AGCYwUcAAADsUlEQVR42pVVaW/aWBTlN7AYbIN3jAEbYygQFi8QAyGk01StKnU0UjsaJeky///rmfsegcBkAT5cvUXXx3c597yMLJchSSIM00S1WoX5uOq6DqdWQ63m8DMzRVFgWRbfW9bmXCwWUSqVdpbRdYMcLFyv3+Pf37/x7dt3zBcLfP70CQ/39/j69U/cPfzAr58/cbNe4fb2I+7o/u7+AUkcI5fNQhTFJ8D9gyRJfM3n87Ru7guFAl+3fiwikfxkWdr5H0TILgVBQKPRgGkYtDbR6Xbhex5Pz2v5CNptuHRm97Wavfl4L5ADQPbnIm3K5TL9Vea1MwnIIHC2Z7WqUS2rto16vc7v/1+3ZxEyB+aoqgqqBOB7LQR+mxe9QOmzDJix9IWi8CrYM8B6s444SXA5u0RK5jgOARUOin7MeMo7I/qwtJ8aUzrbHrss8vqwWs0Xc9SoXrybZ0T2jDZbOlQqFZRon6d6sZq91YBXABmYwD9kNTMtE+PRGOPJBFEcEZU0Aqb0uc9xyyiKhq0ZhgnbdtDvDxAE79Dt9ij9GlFKxb7fW5YJgj4BhLi4iCiqGabTBRbLG9y8v0UUpej1xhgMwp31+5M3LdPpDDjYxTDGNJkjiWb48uUvfP/7H3y4/cwBe9x5zG0f/CXbpVypKFANC7rd3Ow1HTqZQXemae3Woynz0aOGCMQ7hepXHadE8CbS9BLLqytMoxBhnGA2SzEaDiE/zj775iU7UJsSB85ycrPZZqPHVEWmPZtrTdOOcvOJh0QN1XFhTxawSVSvr1YU0QWGoxEn/amcPIiQ70nBGX0GvR48kizf96HTnOdzORQF4YxJIeeKaUPzulT8KlzXJUCfk91zPbRIF5n0vySqr4yegLJmQGm20fIDLJcLTMYRYpL5JIoxmYSIwpCP5pt6uEuZnKRyBRJRZpv+VtpEUeI/3Hb3xKYUoNoNWMMZ/E4Hq9UC6/U16eOUa+RkPOKAJ3d5W0eBus1ow4zRhtGHEZ2r0Dl6KORz0N0AzvQGjm1RhNdIkphEIiCR6FJjmmfSZltDPkIKzTDRhjrdpKlhHbbprclmczztk7vMadN6xyXLp0fKdRv8WbXtKjyfqOO5/GkVT+NhAbKiQiUeMr6tVmvM5zMk0ylCEtswDhHTXA9pnpkovw74SA2WrqybEGkvSzJ/pDZ02Qw9Hz2heHRaNs8oRVcheaqOUjRbbfzx8QOWqxVvSprOScbUk9+Wg6YwYLY3qE4OCYKmqqQw+tFx27f/AFLEYRQNv5BcAAAAAElFTkSuQmCC'); background-size: cover; display: block;" ></span> <img class="gatsby-resp-image-image" alt="code restructure" title="" src="/static/0b8bd7a5146d29ff80e36f74a8ee75a3/3c5de/code-restructure.png" srcset="/static/0b8bd7a5146d29ff80e36f74a8ee75a3/e9ff0/code-restructure.png 180w, /static/0b8bd7a5146d29ff80e36f74a8ee75a3/f21e7/code-restructure.png 360w, /static/0b8bd7a5146d29ff80e36f74a8ee75a3/3c5de/code-restructure.png 472w" sizes="(max-width: 472px) 100vw, 472px" style="width:100%;height:100%;margin:0;vertical-align:middle;position:absolute;top:0;left:0;" loading="lazy" decoding="async" /> </a> </span></p> <p><code>index</code> will have the main table component that can be imported by the consumer as follows.</p> <pre class="grvsc-container default-dark" data-language="tsx" data-index="21"><code class="grvsc-code"><span class="grvsc-line"><span class="grvsc-source"><span class="mtk15">import</span><span class="mtk1"> { </span><span class="mtk12">Table</span><span class="mtk1"> } </span><span class="mtk15">from</span><span class="mtk1"> </span><span class="mtk8">&quot;./Table&quot;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk4">function</span><span class="mtk1"> </span><span class="mtk11">App</span><span class="mtk1">() {</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk15">return</span><span class="mtk1"> </span><span class="mtk17">&lt;</span><span class="mtk10">Table</span><span class="mtk1"> </span><span class="mtk17">/&gt;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1">}</span></span></span> <span class="grvsc-line"><span class="grvsc-source"></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk15">export</span><span class="mtk1"> </span><span class="mtk15">default</span><span class="mtk1"> </span><span class="mtk12">App</span></span></span></code></pre> <p>The rest are the same components we worked on in the previous sections but moved to a separate file as an isolated component and imported when required.</p> <p>All files and code restructures are available in the next section.</p> <p>To finish up this tutorial, let’s treat ourselves a bit and style the table with a simple yet effective CSS 🙂</p> <pre class="grvsc-container default-dark" data-language="css" data-index="22"><code class="grvsc-code"><span class="grvsc-line"><span class="grvsc-source"><span class="mtk6">table</span><span class="mtk1"> {</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">border-collapse</span><span class="mtk1">: </span><span class="mtk8">collapse</span><span class="mtk1">;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">margin</span><span class="mtk1">: </span><span class="mtk7">25px</span><span class="mtk1"> </span><span class="mtk7">0</span><span class="mtk1">;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">font-size</span><span class="mtk1">: </span><span class="mtk7">14px</span><span class="mtk1">;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">font-family</span><span class="mtk1">: </span><span class="mtk8">sans-serif</span><span class="mtk1">;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">box-shadow</span><span class="mtk1">: </span><span class="mtk7">0</span><span class="mtk1"> </span><span class="mtk7">0</span><span class="mtk1"> </span><span class="mtk7">20px</span><span class="mtk1"> </span><span class="mtk11">rgba</span><span class="mtk1">(</span><span class="mtk7">0</span><span class="mtk1">, </span><span class="mtk7">0</span><span class="mtk1">, </span><span class="mtk7">0</span><span class="mtk1">, </span><span class="mtk7">0.15</span><span class="mtk1">);</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">width</span><span class="mtk1">: </span><span class="mtk7">720px</span><span class="mtk1">;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1">}</span></span></span> <span class="grvsc-line"><span class="grvsc-source"></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk6">table</span><span class="mtk1"> </span><span class="mtk6">thead</span><span class="mtk1"> </span><span class="mtk6">tr</span><span class="mtk1"> {</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">background-color</span><span class="mtk1">: </span><span class="mtk8">#4bbd7f</span><span class="mtk1">;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">color</span><span class="mtk1">: </span><span class="mtk8">#ffffff</span><span class="mtk1">;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">text-align</span><span class="mtk1">: </span><span class="mtk8">left</span><span class="mtk1">;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1">}</span></span></span> <span class="grvsc-line"><span class="grvsc-source"></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk6">table</span><span class="mtk1"> </span><span class="mtk6">th</span><span class="mtk1">,</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk6">table</span><span class="mtk1"> </span><span class="mtk6">td</span><span class="mtk1"> {</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">padding</span><span class="mtk1">: </span><span class="mtk7">10px</span><span class="mtk1"> </span><span class="mtk7">15px</span><span class="mtk1">;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1">}</span></span></span> <span class="grvsc-line"><span class="grvsc-source"></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk6">table</span><span class="mtk1"> </span><span class="mtk6">tbody</span><span class="mtk1"> </span><span class="mtk6">tr</span><span class="mtk1"> {</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">border-bottom</span><span class="mtk1">: </span><span class="mtk7">1px</span><span class="mtk1"> </span><span class="mtk8">solid</span><span class="mtk1"> </span><span class="mtk8">#dddddd</span><span class="mtk1">;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1">}</span></span></span> <span class="grvsc-line"><span class="grvsc-source"></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk6">table</span><span class="mtk1"> </span><span class="mtk6">tbody</span><span class="mtk1"> </span><span class="mtk6">tr:nth-of-type</span><span class="mtk1">(even) {</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">background-color</span><span class="mtk1">: </span><span class="mtk8">#f6f6f6</span><span class="mtk1">;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1">}</span></span></span> <span class="grvsc-line"><span class="grvsc-source"></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk6">table</span><span class="mtk1"> </span><span class="mtk6">tbody</span><span class="mtk1"> </span><span class="mtk6">tr:last-of-type</span><span class="mtk1"> {</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">border-bottom</span><span class="mtk1">: </span><span class="mtk7">2px</span><span class="mtk1"> </span><span class="mtk8">solid</span><span class="mtk1"> </span><span class="mtk8">#4bbd7f</span><span class="mtk1">;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1">}</span></span></span> <span class="grvsc-line"><span class="grvsc-source"></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk6">table</span><span class="mtk1"> </span><span class="mtk6">tbody</span><span class="mtk1"> </span><span class="mtk6">tr.active-row</span><span class="mtk1"> {</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">font-weight</span><span class="mtk1">: </span><span class="mtk8">bold</span><span class="mtk1">;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">color</span><span class="mtk1">: </span><span class="mtk8">#4bbd7f</span><span class="mtk1">;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1">}</span></span></span> <span class="grvsc-line"><span class="grvsc-source"></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk6">table</span><span class="mtk1"> </span><span class="mtk6">td:first-child</span><span class="mtk1"> </span><span class="mtk6">input</span><span class="mtk1"> {</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">width</span><span class="mtk1">: </span><span class="mtk7">50px</span><span class="mtk1">;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1">}</span></span></span> <span class="grvsc-line"><span class="grvsc-source"></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk6">table</span><span class="mtk1"> </span><span class="mtk6">td:nth-child</span><span class="mtk1">(</span><span class="mtk7">2</span><span class="mtk1">) </span><span class="mtk6">input</span><span class="mtk1"> {</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">width</span><span class="mtk1">: </span><span class="mtk7">120px</span><span class="mtk1">;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1">}</span></span></span> <span class="grvsc-line"><span class="grvsc-source"></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk6">table</span><span class="mtk1"> </span><span class="mtk6">.edit-cell-container</span><span class="mtk1"> </span><span class="mtk6">button</span><span class="mtk1"> {</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">border-radius</span><span class="mtk1">: </span><span class="mtk7">50px</span><span class="mtk1">;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">height</span><span class="mtk1">: </span><span class="mtk7">26px</span><span class="mtk1">;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">width</span><span class="mtk1">: </span><span class="mtk7">26px</span><span class="mtk1">;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">border</span><span class="mtk1">: </span><span class="mtk7">1px</span><span class="mtk1"> </span><span class="mtk8">solid</span><span class="mtk1"> </span><span class="mtk8">#ccc</span><span class="mtk1">;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">color</span><span class="mtk1">: </span><span class="mtk8">#ffb918</span><span class="mtk1">;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1">}</span></span></span> <span class="grvsc-line"><span class="grvsc-source"></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk6">table</span><span class="mtk1"> </span><span class="mtk6">button</span><span class="mtk1">[</span><span class="mtk12">name</span><span class="mtk1">=</span><span class="mtk8">&quot;cancel&quot;</span><span class="mtk1">] {</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">color</span><span class="mtk1">: </span><span class="mtk8">#7b7b7b</span><span class="mtk1">;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1">}</span></span></span> <span class="grvsc-line"><span class="grvsc-source"></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk6">table</span><span class="mtk1"> </span><span class="mtk6">button</span><span class="mtk1">[</span><span class="mtk12">name</span><span class="mtk1">=</span><span class="mtk8">&quot;done&quot;</span><span class="mtk1">] {</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">color</span><span class="mtk1">: </span><span class="mtk8">#4bbd7f</span><span class="mtk1">;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1">}</span></span></span> <span class="grvsc-line"><span class="grvsc-source"></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk6">table</span><span class="mtk1"> </span><span class="mtk6">input</span><span class="mtk1">,</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk6">select</span><span class="mtk1"> {</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">border</span><span class="mtk1">: </span><span class="mtk7">1px</span><span class="mtk1"> </span><span class="mtk8">solid</span><span class="mtk1"> </span><span class="mtk8">#ccc</span><span class="mtk1">;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">border-radius</span><span class="mtk1">: </span><span class="mtk7">4px</span><span class="mtk1">;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">padding</span><span class="mtk1">: </span><span class="mtk7">5px</span><span class="mtk1">;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1">}</span></span></span> <span class="grvsc-line"><span class="grvsc-source"></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk6">table</span><span class="mtk1"> </span><span class="mtk6">.edit-cell</span><span class="mtk1"> {</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">display</span><span class="mtk1">: </span><span class="mtk8">flex</span><span class="mtk1">;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">gap</span><span class="mtk1">: </span><span class="mtk7">5px</span><span class="mtk1">;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1">}</span></span></span></code></pre> <div id="ReactEditableTableFinal" data-code data-height="275px"></div> <p>Nothing out of the ordinary here, some table shadow with row colors, borders, margin, and width!</p> <h2 id="complete-code-and-live-demo" style="position:relative;"><a href="#complete-code-and-live-demo" aria-label="complete code and live demo permalink" class="anchor before"><svg aria-hidden="true" focusable="false" height="16" version="1.1" viewBox="0 0 16 16" width="16"><path fill-rule="evenodd" d="M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z"></path></svg></a>Complete code and live demo</h2> <p>The complete code is available in <a href="https://github.com/muhimasri/react-editable-table">this repository</a>. If you liked the tutorial, please <a href="https://github.com/muhimasri/react-editable-table/stargazers">star the repository</a>, and feel free to request new features!</p> <p>Alternatively, you can access the code on StackBlitz below.</p> <div data-stackblitz="vitejs-vite-hzowq6"> <button>Run Code</button> </div> <h2 id="summary" style="position:relative;"><a href="#summary" aria-label="summary permalink" class="anchor before"><svg aria-hidden="true" focusable="false" height="16" version="1.1" viewBox="0 0 16 16" width="16"><path fill-rule="evenodd" d="M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z"></path></svg></a>Summary</h2> <p>In this tutorial, we learned how to utilize TanckStack to build a dynamic React editable table that supports custom column schema and row editing, saving, and canceling actions.</p> <p>The solution we explored together is one of several different approaches that we can take. We also didn’t consider any performance impact. So it’s highly recommended, based on the business requirement, to conduct performance tests and asses if the code might require design pattern adjustments such as using React memo, signals, or a state management to enhance performance level.</p> <p>Bye for now 👋</p> <style class="grvsc-styles"> .grvsc-container { overflow: auto; position: relative; -webkit-overflow-scrolling: touch; padding-top: 1rem; padding-top: var(--grvsc-padding-top, var(--grvsc-padding-v, 1rem)); padding-bottom: 1rem; padding-bottom: var(--grvsc-padding-bottom, var(--grvsc-padding-v, 1rem)); border-radius: 8px; border-radius: var(--grvsc-border-radius, 8px); font-feature-settings: normal; line-height: 1.4; } .grvsc-code { display: table; } .grvsc-line { display: table-row; box-sizing: border-box; width: 100%; position: relative; } .grvsc-line > * { position: relative; } .grvsc-gutter-pad { display: table-cell; padding-left: 0.75rem; padding-left: calc(var(--grvsc-padding-left, var(--grvsc-padding-h, 1.5rem)) / 2); } .grvsc-gutter { display: table-cell; -webkit-user-select: none; -moz-user-select: none; user-select: none; } .grvsc-gutter::before { content: attr(data-content); } .grvsc-source { display: table-cell; padding-left: 1.5rem; padding-left: var(--grvsc-padding-left, var(--grvsc-padding-h, 1.5rem)); padding-right: 1.5rem; padding-right: var(--grvsc-padding-right, var(--grvsc-padding-h, 1.5rem)); } .grvsc-source:empty::after { content: ' '; -webkit-user-select: none; -moz-user-select: none; user-select: none; } .grvsc-gutter + .grvsc-source { padding-left: 0.75rem; padding-left: calc(var(--grvsc-padding-left, var(--grvsc-padding-h, 1.5rem)) / 2); } /* Line transformer styles */ .grvsc-has-line-highlighting > .grvsc-code > .grvsc-line::before { content: ' '; position: absolute; width: 100%; } .grvsc-line-diff-add::before { background-color: var(--grvsc-line-diff-add-background-color, rgba(0, 255, 60, 0.2)); } .grvsc-line-diff-del::before { background-color: var(--grvsc-line-diff-del-background-color, rgba(255, 0, 20, 0.2)); } .grvsc-line-number { padding: 0 2px; text-align: right; opacity: 0.7; } .default-dark { background-color: #1E1E1E; color: #D4D4D4; } .default-dark .mtk4 { color: #569CD6; } .default-dark .mtk1 { color: #D4D4D4; } .default-dark .mtk12 { color: #9CDCFE; } .default-dark .mtk7 { color: #B5CEA8; } .default-dark .mtk8 { color: #CE9178; } .default-dark .mtk10 { color: #4EC9B0; } .default-dark .mtk11 { color: #DCDCAA; } .default-dark .mtk15 { color: #C586C0; } .default-dark .mtk17 { color: #808080; } .default-dark .mtk6 { color: #D7BA7D; } .default-dark .grvsc-line-highlighted::before { background-color: var(--grvsc-line-highlighted-background-color, rgba(255, 255, 255, 0.1)); box-shadow: inset var(--grvsc-line-highlighted-border-width, 4px) 0 0 0 var(--grvsc-line-highlighted-border-color, rgba(255, 255, 255, 0.5)); } </style><![CDATA[How to Create Skeleton Table Loaders with Material UI (MUI)]]>https://muhimasri.commui-table-skeleton-loaderhttps://muhimasri.commui-table-skeleton-loader<p>Many of us developers encountered the scenario where a data table stays empty and idle until data arrives from an API call and the table gets filled. Even if the API is fast, the approach of not adding a table loading placeholder makes the UI feels slow and laggy.</p> <p>In this tutorial, we will learn how to replace table cells with skeleton loaders using MUI <code>Skeleton</code> and <code>Table</code> components. We will also use a real API call to make it more exciting!</p> <p>Here is what the final code will look like:</p> <div data-codesandbox="mui-table-skeleton-loading-s1dfwh"> <button>Run Code</button> </div> <p><em>If this is your first time working with MUI, please follow the <a href="https://mui.com/material-ui/getting-started/installation/">installation instructions</a> from the official documentation to get started.</em></p> <h2 id="create-a-basic-mui-table" style="position:relative;"><a href="#create-a-basic-mui-table" aria-label="create a basic mui table permalink" class="anchor before"><svg aria-hidden="true" focusable="false" height="16" version="1.1" viewBox="0 0 16 16" width="16"><path fill-rule="evenodd" d="M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z"></path></svg></a>Create a Basic MUI Table</h2> <p>MUI <code>Table</code> component is made of several parts that are required to create a basic table - <code>TableContainer</code>, <code>TableHead</code>, <code>TableRow</code>, <code>TableCell</code>, and <code>TableBody</code>.</p> <p>For example, here is a table with a few headers and rows:</p> <pre class="grvsc-container default-dark" data-language="jsx" data-index="0"><code class="grvsc-code"><span class="grvsc-line"><span class="grvsc-source"><span class="mtk15">import</span><span class="mtk1"> </span><span class="mtk12">React</span><span class="mtk1"> </span><span class="mtk15">from</span><span class="mtk1"> </span><span class="mtk8">&quot;react&quot;</span><span class="mtk1">;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk15">import</span><span class="mtk1"> </span><span class="mtk12">Table</span><span class="mtk1"> </span><span class="mtk15">from</span><span class="mtk1"> </span><span class="mtk8">&quot;@mui/material/Table&quot;</span><span class="mtk1">;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk15">import</span><span class="mtk1"> </span><span class="mtk12">TableBody</span><span class="mtk1"> </span><span class="mtk15">from</span><span class="mtk1"> </span><span class="mtk8">&quot;@mui/material/TableBody&quot;</span><span class="mtk1">;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk15">import</span><span class="mtk1"> </span><span class="mtk12">TableCell</span><span class="mtk1"> </span><span class="mtk15">from</span><span class="mtk1"> </span><span class="mtk8">&quot;@mui/material/TableCell&quot;</span><span class="mtk1">;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk15">import</span><span class="mtk1"> </span><span class="mtk12">TableContainer</span><span class="mtk1"> </span><span class="mtk15">from</span><span class="mtk1"> </span><span class="mtk8">&quot;@mui/material/TableContainer&quot;</span><span class="mtk1">;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk15">import</span><span class="mtk1"> </span><span class="mtk12">TableHead</span><span class="mtk1"> </span><span class="mtk15">from</span><span class="mtk1"> </span><span class="mtk8">&quot;@mui/material/TableHead&quot;</span><span class="mtk1">;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk15">import</span><span class="mtk1"> </span><span class="mtk12">TableRow</span><span class="mtk1"> </span><span class="mtk15">from</span><span class="mtk1"> </span><span class="mtk8">&quot;@mui/material/TableRow&quot;</span><span class="mtk1">;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk15">import</span><span class="mtk1"> </span><span class="mtk12">Paper</span><span class="mtk1"> </span><span class="mtk15">from</span><span class="mtk1"> </span><span class="mtk8">&quot;@mui/material/Paper&quot;</span><span class="mtk1">;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk15">export</span><span class="mtk1"> </span><span class="mtk15">default</span><span class="mtk1"> </span><span class="mtk4">function</span><span class="mtk1"> </span><span class="mtk11">App</span><span class="mtk1">() {</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk15">return</span><span class="mtk1"> (</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk17">&lt;</span><span class="mtk10">TableContainer</span><span class="mtk1"> </span><span class="mtk12">component</span><span class="mtk1">=</span><span class="mtk4">{</span><span class="mtk12">Paper</span><span class="mtk4">}</span><span class="mtk17">&gt;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk17">&lt;</span><span class="mtk10">Table</span><span class="mtk17">&gt;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk17">&lt;</span><span class="mtk10">TableHead</span><span class="mtk17">&gt;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk17">&lt;</span><span class="mtk10">TableRow</span><span class="mtk17">&gt;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk17">&lt;</span><span class="mtk10">TableCell</span><span class="mtk17">&gt;</span><span class="mtk1">Name</span><span class="mtk17">&lt;/</span><span class="mtk10">TableCell</span><span class="mtk17">&gt;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk17">&lt;</span><span class="mtk10">TableCell</span><span class="mtk17">&gt;</span><span class="mtk1">Email</span><span class="mtk17">&lt;/</span><span class="mtk10">TableCell</span><span class="mtk17">&gt;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk17">&lt;</span><span class="mtk10">TableCell</span><span class="mtk17">&gt;</span><span class="mtk1">Phone</span><span class="mtk17">&lt;/</span><span class="mtk10">TableCell</span><span class="mtk17">&gt;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk17">&lt;</span><span class="mtk10">TableCell</span><span class="mtk17">&gt;</span><span class="mtk1">Website</span><span class="mtk17">&lt;/</span><span class="mtk10">TableCell</span><span class="mtk17">&gt;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk17">&lt;/</span><span class="mtk10">TableRow</span><span class="mtk17">&gt;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk17">&lt;/</span><span class="mtk10">TableHead</span><span class="mtk17">&gt;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk17">&lt;</span><span class="mtk10">TableBody</span><span class="mtk17">&gt;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk17">&lt;</span><span class="mtk10">TableRow</span><span class="mtk17">&gt;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk17">&lt;</span><span class="mtk10">TableCell</span><span class="mtk17">&gt;</span><span class="mtk1">Leanne Graham</span><span class="mtk17">&lt;/</span><span class="mtk10">TableCell</span><span class="mtk17">&gt;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk17">&lt;</span><span class="mtk10">TableCell</span><span class="mtk17">&gt;</span><span class="mtk1">[email protected]</span><span class="mtk17">&lt;/</span><span class="mtk10">TableCell</span><span class="mtk17">&gt;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk17">&lt;</span><span class="mtk10">TableCell</span><span class="mtk17">&gt;</span><span class="mtk1">1-770-736-8031 x56442</span><span class="mtk17">&lt;/</span><span class="mtk10">TableCell</span><span class="mtk17">&gt;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk17">&lt;</span><span class="mtk10">TableCell</span><span class="mtk17">&gt;</span><span class="mtk1">hildegard.org</span><span class="mtk17">&lt;/</span><span class="mtk10">TableCell</span><span class="mtk17">&gt;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk17">&lt;/</span><span class="mtk10">TableRow</span><span class="mtk17">&gt;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk17">&lt;</span><span class="mtk10">TableRow</span><span class="mtk17">&gt;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk17">&lt;</span><span class="mtk10">TableCell</span><span class="mtk17">&gt;</span><span class="mtk1">Ervin Howell</span><span class="mtk17">&lt;/</span><span class="mtk10">TableCell</span><span class="mtk17">&gt;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk17">&lt;</span><span class="mtk10">TableCell</span><span class="mtk17">&gt;</span><span class="mtk1">[email protected]</span><span class="mtk17">&lt;/</span><span class="mtk10">TableCell</span><span class="mtk17">&gt;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk17">&lt;</span><span class="mtk10">TableCell</span><span class="mtk17">&gt;</span><span class="mtk1">010-692-6593 x09125</span><span class="mtk17">&lt;/</span><span class="mtk10">TableCell</span><span class="mtk17">&gt;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk17">&lt;</span><span class="mtk10">TableCell</span><span class="mtk17">&gt;</span><span class="mtk1">anastasia.net</span><span class="mtk17">&lt;/</span><span class="mtk10">TableCell</span><span class="mtk17">&gt;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk17">&lt;/</span><span class="mtk10">TableRow</span><span class="mtk17">&gt;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk17">&lt;/</span><span class="mtk10">TableBody</span><span class="mtk17">&gt;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk17">&lt;/</span><span class="mtk10">Table</span><span class="mtk17">&gt;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk17">&lt;/</span><span class="mtk10">TableContainer</span><span class="mtk17">&gt;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> );</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1">}</span></span></span></code></pre> <div id="TableSkeletonLoaderOne" data-code data-height="200px"></div> <p>More details on the <code>Table</code> component are available in the <a href="https://mui.com/material-ui/react-table/">official Material UI documentation</a></p> <h3 id="fetch-data-from-an-api" style="position:relative;"><a href="#fetch-data-from-an-api" aria-label="fetch data from an api permalink" class="anchor before"><svg aria-hidden="true" focusable="false" height="16" version="1.1" viewBox="0 0 16 16" width="16"><path fill-rule="evenodd" d="M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z"></path></svg></a>Fetch Data from an API</h3> <p>We’re going to create a <code>useFetch</code> hook to load the data on the first component cycle by triggering a real API call with fake users using <a href="https://jsonplaceholder.typicode.com/">{JSON} Placeholder</a>.</p> <pre class="grvsc-container default-dark" data-language="jsx" data-index="1"><code class="grvsc-code"><span class="grvsc-line"><span class="grvsc-source"><span class="mtk4">const</span><span class="mtk1"> </span><span class="mtk11">useFetch</span><span class="mtk1"> = () </span><span class="mtk4">=&gt;</span><span class="mtk1"> {</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk4">const</span><span class="mtk1"> [</span><span class="mtk12">data</span><span class="mtk1">, </span><span class="mtk12">setData</span><span class="mtk1">] = </span><span class="mtk11">useState</span><span class="mtk1">();</span></span></span> <span class="grvsc-line"><span class="grvsc-source"></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk4">const</span><span class="mtk1"> </span><span class="mtk11">fetchData</span><span class="mtk1"> = </span><span class="mtk4">async</span><span class="mtk1"> () </span><span class="mtk4">=&gt;</span><span class="mtk1"> {</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk4">const</span><span class="mtk1"> </span><span class="mtk12">response</span><span class="mtk1"> = </span><span class="mtk15">await</span><span class="mtk1"> </span><span class="mtk11">fetch</span><span class="mtk1">(</span><span class="mtk8">&quot;https://jsonplaceholder.typicode.com/users&quot;</span><span class="mtk1">);</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk4">const</span><span class="mtk1"> </span><span class="mtk12">newData</span><span class="mtk1"> = </span><span class="mtk15">await</span><span class="mtk1"> </span><span class="mtk12">response</span><span class="mtk1">.</span><span class="mtk11">json</span><span class="mtk1">();</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk11">setData</span><span class="mtk1">(</span><span class="mtk12">newData</span><span class="mtk1">);</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> };</span></span></span> <span class="grvsc-line"><span class="grvsc-source"></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk11">useEffect</span><span class="mtk1">(() </span><span class="mtk4">=&gt;</span><span class="mtk1"> {</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk11">fetchData</span><span class="mtk1">();</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> }, []);</span></span></span> <span class="grvsc-line"><span class="grvsc-source"></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk15">return</span><span class="mtk1"> { </span><span class="mtk12">data</span><span class="mtk1">, </span><span class="mtk12">fetchData</span><span class="mtk1"> };</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1">};</span></span></span></code></pre> <p>The hook exposes two parts:</p> <ol> <li><code>data</code> - for populating the table</li> <li><code>fetchData</code> function - for refreshing the table when necessary.</li> </ol> <p>Now let’s consume the <code>useFetch</code> hook in our main component and populate the data table.</p> <pre class="grvsc-container grvsc-has-line-highlighting default-dark" data-language="jsx" data-index="2"><code class="grvsc-code"><span class="grvsc-line"><span class="grvsc-source"><span class="mtk15">import</span><span class="mtk1"> </span><span class="mtk12">React</span><span class="mtk1">, { </span><span class="mtk12">useEffect</span><span class="mtk1">, </span><span class="mtk12">useState</span><span class="mtk1"> } </span><span class="mtk15">from</span><span class="mtk1"> </span><span class="mtk8">&quot;react&quot;</span><span class="mtk1">;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk15">import</span><span class="mtk1"> </span><span class="mtk12">Table</span><span class="mtk1"> </span><span class="mtk15">from</span><span class="mtk1"> </span><span class="mtk8">&quot;@mui/material/Table&quot;</span><span class="mtk1">;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk15">import</span><span class="mtk1"> </span><span class="mtk12">TableBody</span><span class="mtk1"> </span><span class="mtk15">from</span><span class="mtk1"> </span><span class="mtk8">&quot;@mui/material/TableBody&quot;</span><span class="mtk1">;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk15">import</span><span class="mtk1"> </span><span class="mtk12">TableCell</span><span class="mtk1"> </span><span class="mtk15">from</span><span class="mtk1"> </span><span class="mtk8">&quot;@mui/material/TableCell&quot;</span><span class="mtk1">;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk15">import</span><span class="mtk1"> </span><span class="mtk12">TableContainer</span><span class="mtk1"> </span><span class="mtk15">from</span><span class="mtk1"> </span><span class="mtk8">&quot;@mui/material/TableContainer&quot;</span><span class="mtk1">;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk15">import</span><span class="mtk1"> </span><span class="mtk12">TableHead</span><span class="mtk1"> </span><span class="mtk15">from</span><span class="mtk1"> </span><span class="mtk8">&quot;@mui/material/TableHead&quot;</span><span class="mtk1">;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk15">import</span><span class="mtk1"> </span><span class="mtk12">TableRow</span><span class="mtk1"> </span><span class="mtk15">from</span><span class="mtk1"> </span><span class="mtk8">&quot;@mui/material/TableRow&quot;</span><span class="mtk1">;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk15">import</span><span class="mtk1"> </span><span class="mtk12">Paper</span><span class="mtk1"> </span><span class="mtk15">from</span><span class="mtk1"> </span><span class="mtk8">&quot;@mui/material/Paper&quot;</span><span class="mtk1">;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk15">export</span><span class="mtk1"> </span><span class="mtk15">default</span><span class="mtk1"> </span><span class="mtk4">function</span><span class="mtk1"> </span><span class="mtk11">App</span><span class="mtk1">() {</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk4">const</span><span class="mtk1"> { </span><span class="mtk12">data</span><span class="mtk1"> } = </span><span class="mtk11">useFetch</span><span class="mtk1">();</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk15">return</span><span class="mtk1"> (</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk17">&lt;</span><span class="mtk10">TableContainer</span><span class="mtk1"> </span><span class="mtk12">component</span><span class="mtk1">=</span><span class="mtk4">{</span><span class="mtk12">Paper</span><span class="mtk4">}</span><span class="mtk17">&gt;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk17">&lt;</span><span class="mtk10">Table</span><span class="mtk17">&gt;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk17">&lt;</span><span class="mtk10">TableHead</span><span class="mtk17">&gt;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk17">&lt;</span><span class="mtk10">TableRow</span><span class="mtk17">&gt;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk17">&lt;</span><span class="mtk10">TableCell</span><span class="mtk17">&gt;</span><span class="mtk1">Name</span><span class="mtk17">&lt;/</span><span class="mtk10">TableCell</span><span class="mtk17">&gt;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk17">&lt;</span><span class="mtk10">TableCell</span><span class="mtk17">&gt;</span><span class="mtk1">Email</span><span class="mtk17">&lt;/</span><span class="mtk10">TableCell</span><span class="mtk17">&gt;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk17">&lt;</span><span class="mtk10">TableCell</span><span class="mtk17">&gt;</span><span class="mtk1">Phone</span><span class="mtk17">&lt;/</span><span class="mtk10">TableCell</span><span class="mtk17">&gt;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk17">&lt;</span><span class="mtk10">TableCell</span><span class="mtk17">&gt;</span><span class="mtk1">Website</span><span class="mtk17">&lt;/</span><span class="mtk10">TableCell</span><span class="mtk17">&gt;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk17">&lt;/</span><span class="mtk10">TableRow</span><span class="mtk17">&gt;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk17">&lt;/</span><span class="mtk10">TableHead</span><span class="mtk17">&gt;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk17">&lt;</span><span class="mtk10">TableBody</span><span class="mtk17">&gt;</span></span></span> <span class="grvsc-line grvsc-line-highlighted"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk4">{</span><span class="mtk12">data</span><span class="mtk1">?.</span><span class="mtk11">map</span><span class="mtk1">((</span><span class="mtk12">row</span><span class="mtk1">) </span><span class="mtk4">=&gt;</span><span class="mtk1"> (</span></span></span> <span class="grvsc-line grvsc-line-highlighted"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk17">&lt;</span><span class="mtk10">TableRow</span><span class="mtk1"> </span><span class="mtk12">key</span><span class="mtk1">=</span><span class="mtk4">{</span><span class="mtk12">row</span><span class="mtk1">.</span><span class="mtk12">name</span><span class="mtk4">}</span><span class="mtk17">&gt;</span></span></span> <span class="grvsc-line grvsc-line-highlighted"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk17">&lt;</span><span class="mtk10">TableCell</span><span class="mtk1"> </span><span class="mtk12">component</span><span class="mtk1">=</span><span class="mtk8">&quot;th&quot;</span><span class="mtk1"> </span><span class="mtk12">scope</span><span class="mtk1">=</span><span class="mtk8">&quot;row&quot;</span><span class="mtk17">&gt;</span></span></span> <span class="grvsc-line grvsc-line-highlighted"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk4">{</span><span class="mtk12">row</span><span class="mtk1">.</span><span class="mtk12">name</span><span class="mtk4">}</span></span></span> <span class="grvsc-line grvsc-line-highlighted"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk17">&lt;/</span><span class="mtk10">TableCell</span><span class="mtk17">&gt;</span></span></span> <span class="grvsc-line grvsc-line-highlighted"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk17">&lt;</span><span class="mtk10">TableCell</span><span class="mtk17">&gt;</span><span class="mtk4">{</span><span class="mtk12">row</span><span class="mtk1">.</span><span class="mtk12">email</span><span class="mtk4">}</span><span class="mtk17">&lt;/</span><span class="mtk10">TableCell</span><span class="mtk17">&gt;</span></span></span> <span class="grvsc-line grvsc-line-highlighted"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk17">&lt;</span><span class="mtk10">TableCell</span><span class="mtk17">&gt;</span><span class="mtk4">{</span><span class="mtk12">row</span><span class="mtk1">.</span><span class="mtk12">phone</span><span class="mtk4">}</span><span class="mtk17">&lt;/</span><span class="mtk10">TableCell</span><span class="mtk17">&gt;</span></span></span> <span class="grvsc-line grvsc-line-highlighted"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk17">&lt;</span><span class="mtk10">TableCell</span><span class="mtk17">&gt;</span><span class="mtk4">{</span><span class="mtk12">row</span><span class="mtk1">.</span><span class="mtk12">website</span><span class="mtk4">}</span><span class="mtk17">&lt;/</span><span class="mtk10">TableCell</span><span class="mtk17">&gt;</span></span></span> <span class="grvsc-line grvsc-line-highlighted"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk17">&lt;/</span><span class="mtk10">TableRow</span><span class="mtk17">&gt;</span></span></span> <span class="grvsc-line grvsc-line-highlighted"><span class="grvsc-source"><span class="mtk1"> ))</span><span class="mtk4">}</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk17">&lt;/</span><span class="mtk10">TableBody</span><span class="mtk17">&gt;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk17">&lt;/</span><span class="mtk10">Table</span><span class="mtk17">&gt;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk17">&lt;/</span><span class="mtk10">TableContainer</span><span class="mtk17">&gt;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> );</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1">}</span></span></span> <span class="grvsc-line"><span class="grvsc-source"></span></span> <span class="grvsc-line grvsc-line-highlighted"><span class="grvsc-source"><span class="mtk4">const</span><span class="mtk1"> </span><span class="mtk11">useFetch</span><span class="mtk1"> = () </span><span class="mtk4">=&gt;</span><span class="mtk1"> {</span></span></span> <span class="grvsc-line grvsc-line-highlighted"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk4">const</span><span class="mtk1"> [</span><span class="mtk12">data</span><span class="mtk1">, </span><span class="mtk12">setData</span><span class="mtk1">] = </span><span class="mtk11">useState</span><span class="mtk1">();</span></span></span> <span class="grvsc-line grvsc-line-highlighted"><span class="grvsc-source"></span></span> <span class="grvsc-line grvsc-line-highlighted"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk4">const</span><span class="mtk1"> </span><span class="mtk11">fetchData</span><span class="mtk1"> = </span><span class="mtk4">async</span><span class="mtk1"> () </span><span class="mtk4">=&gt;</span><span class="mtk1"> {</span></span></span> <span class="grvsc-line grvsc-line-highlighted"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk4">const</span><span class="mtk1"> </span><span class="mtk12">response</span><span class="mtk1"> = </span><span class="mtk15">await</span><span class="mtk1"> </span><span class="mtk11">fetch</span><span class="mtk1">(</span><span class="mtk8">&quot;https://jsonplaceholder.typicode.com/users&quot;</span><span class="mtk1">);</span></span></span> <span class="grvsc-line grvsc-line-highlighted"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk4">const</span><span class="mtk1"> </span><span class="mtk12">newData</span><span class="mtk1"> = </span><span class="mtk15">await</span><span class="mtk1"> </span><span class="mtk12">response</span><span class="mtk1">.</span><span class="mtk11">json</span><span class="mtk1">();</span></span></span> <span class="grvsc-line grvsc-line-highlighted"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk11">setData</span><span class="mtk1">(</span><span class="mtk12">newData</span><span class="mtk1">);</span></span></span> <span class="grvsc-line grvsc-line-highlighted"><span class="grvsc-source"><span class="mtk1"> };</span></span></span> <span class="grvsc-line grvsc-line-highlighted"><span class="grvsc-source"></span></span> <span class="grvsc-line grvsc-line-highlighted"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk11">useEffect</span><span class="mtk1">(() </span><span class="mtk4">=&gt;</span><span class="mtk1"> {</span></span></span> <span class="grvsc-line grvsc-line-highlighted"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk11">fetchData</span><span class="mtk1">();</span></span></span> <span class="grvsc-line grvsc-line-highlighted"><span class="grvsc-source"><span class="mtk1"> }, []);</span></span></span> <span class="grvsc-line grvsc-line-highlighted"><span class="grvsc-source"></span></span> <span class="grvsc-line grvsc-line-highlighted"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk15">return</span><span class="mtk1"> { </span><span class="mtk12">data</span><span class="mtk1">, </span><span class="mtk12">fetchData</span><span class="mtk1"> };</span></span></span> <span class="grvsc-line grvsc-line-highlighted"><span class="grvsc-source"><span class="mtk1">};</span></span></span></code></pre> <div id="TableSkeletonLoaderTwo" data-code data-height="400px"></div> <h2 id="using-skeleton-loaders" style="position:relative;"><a href="#using-skeleton-loaders" aria-label="using skeleton loaders permalink" class="anchor before"><svg aria-hidden="true" focusable="false" height="16" version="1.1" viewBox="0 0 16 16" width="16"><path fill-rule="evenodd" d="M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z"></path></svg></a>Using Skeleton Loaders</h2> <p>Now that we have the data table receiving and populating data let’s do the fun part!</p> <p>There are multiple variants of the skeleton loading in Material UI, but we’re specifically interested in the <code>text</code> variant as it closely depicts the text data.</p> <pre class="grvsc-container default-dark" data-language="jsx" data-index="3"><code class="grvsc-code"><span class="grvsc-line"><span class="grvsc-source"><span class="mtk17">&lt;</span><span class="mtk10">Skeleton</span><span class="mtk1"> </span><span class="mtk12">animation</span><span class="mtk1">=</span><span class="mtk8">&quot;wave&quot;</span><span class="mtk1"> </span><span class="mtk12">variant</span><span class="mtk1">=</span><span class="mtk8">&quot;text&quot;</span><span class="mtk1"> </span><span class="mtk17">/&gt;</span></span></span></code></pre> <div id="TableSkeletonLoaderThree" data-code data-height="50px"></div> <p>We also added a <code>wave</code> style to animate from left to right while waiting.</p> <h3 id="create-a-row-loader-component" style="position:relative;"><a href="#create-a-row-loader-component" aria-label="create a row loader component permalink" class="anchor before"><svg aria-hidden="true" focusable="false" height="16" version="1.1" viewBox="0 0 16 16" width="16"><path fill-rule="evenodd" d="M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z"></path></svg></a>Create a Row Loader Component</h3> <p>Let’s create a component that returns N number of row skeleton loading elements; N can be a parameter that the consumer passes.</p> <pre class="grvsc-container default-dark" data-language="jsx" data-index="4"><code class="grvsc-code"><span class="grvsc-line"><span class="grvsc-source"><span class="mtk4">const</span><span class="mtk1"> </span><span class="mtk11">TableRowsLoader</span><span class="mtk1"> = ({ </span><span class="mtk12">rowsNum</span><span class="mtk1"> }) </span><span class="mtk4">=&gt;</span><span class="mtk1"> {</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk15">return</span><span class="mtk1"> [...</span><span class="mtk10">Array</span><span class="mtk1">(</span><span class="mtk12">rowsNum</span><span class="mtk1">)].</span><span class="mtk11">map</span><span class="mtk1">((</span><span class="mtk12">row</span><span class="mtk1">, </span><span class="mtk12">index</span><span class="mtk1">) </span><span class="mtk4">=&gt;</span><span class="mtk1"> (</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk17">&lt;</span><span class="mtk10">TableRow</span><span class="mtk1"> </span><span class="mtk12">key</span><span class="mtk1">=</span><span class="mtk4">{</span><span class="mtk12">index</span><span class="mtk4">}</span><span class="mtk17">&gt;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk17">&lt;</span><span class="mtk10">TableCell</span><span class="mtk1"> </span><span class="mtk12">component</span><span class="mtk1">=</span><span class="mtk8">&quot;th&quot;</span><span class="mtk1"> </span><span class="mtk12">scope</span><span class="mtk1">=</span><span class="mtk8">&quot;row&quot;</span><span class="mtk17">&gt;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk17">&lt;</span><span class="mtk10">Skeleton</span><span class="mtk1"> </span><span class="mtk12">animation</span><span class="mtk1">=</span><span class="mtk8">&quot;wave&quot;</span><span class="mtk1"> </span><span class="mtk12">variant</span><span class="mtk1">=</span><span class="mtk8">&quot;text&quot;</span><span class="mtk1"> </span><span class="mtk17">/&gt;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk17">&lt;/</span><span class="mtk10">TableCell</span><span class="mtk17">&gt;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk17">&lt;</span><span class="mtk10">TableCell</span><span class="mtk17">&gt;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk17">&lt;</span><span class="mtk10">Skeleton</span><span class="mtk1"> </span><span class="mtk12">animation</span><span class="mtk1">=</span><span class="mtk8">&quot;wave&quot;</span><span class="mtk1"> </span><span class="mtk12">variant</span><span class="mtk1">=</span><span class="mtk8">&quot;text&quot;</span><span class="mtk1"> </span><span class="mtk17">/&gt;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk17">&lt;/</span><span class="mtk10">TableCell</span><span class="mtk17">&gt;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk17">&lt;</span><span class="mtk10">TableCell</span><span class="mtk17">&gt;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk17">&lt;</span><span class="mtk10">Skeleton</span><span class="mtk1"> </span><span class="mtk12">animation</span><span class="mtk1">=</span><span class="mtk8">&quot;wave&quot;</span><span class="mtk1"> </span><span class="mtk12">variant</span><span class="mtk1">=</span><span class="mtk8">&quot;text&quot;</span><span class="mtk1"> </span><span class="mtk17">/&gt;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk17">&lt;/</span><span class="mtk10">TableCell</span><span class="mtk17">&gt;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk17">&lt;</span><span class="mtk10">TableCell</span><span class="mtk17">&gt;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk17">&lt;</span><span class="mtk10">Skeleton</span><span class="mtk1"> </span><span class="mtk12">animation</span><span class="mtk1">=</span><span class="mtk8">&quot;wave&quot;</span><span class="mtk1"> </span><span class="mtk12">variant</span><span class="mtk1">=</span><span class="mtk8">&quot;text&quot;</span><span class="mtk1"> </span><span class="mtk17">/&gt;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk17">&lt;/</span><span class="mtk10">TableCell</span><span class="mtk17">&gt;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk17">&lt;/</span><span class="mtk10">TableRow</span><span class="mtk17">&gt;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> ));</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1">};</span></span></span></code></pre> <p>Then, we’re going to make two modifications to the <code>fetchData</code> function:</p> <ol> <li>Add a two seconds timeout to demonstrate the loading part clearly.</li> <li>Set data to <code>undefined</code> at the beginning of the function; this will be used as an indicator to trigger the loading component.</li> </ol> <pre class="grvsc-container grvsc-has-line-highlighting default-dark" data-language="jsx" data-index="5"><code class="grvsc-code"><span class="grvsc-line"><span class="grvsc-source"><span class="mtk4">const</span><span class="mtk1"> </span><span class="mtk11">useFetch</span><span class="mtk1"> = () </span><span class="mtk4">=&gt;</span><span class="mtk1"> {</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk4">const</span><span class="mtk1"> [</span><span class="mtk12">data</span><span class="mtk1">, </span><span class="mtk12">setData</span><span class="mtk1">] = </span><span class="mtk11">useState</span><span class="mtk1">();</span></span></span> <span class="grvsc-line"><span class="grvsc-source"></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk4">const</span><span class="mtk1"> </span><span class="mtk11">fetchData</span><span class="mtk1"> = </span><span class="mtk4">async</span><span class="mtk1"> () </span><span class="mtk4">=&gt;</span><span class="mtk1"> {</span></span></span> <span class="grvsc-line grvsc-line-highlighted"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk11">setData</span><span class="mtk1">();</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk4">const</span><span class="mtk1"> </span><span class="mtk12">response</span><span class="mtk1"> = </span><span class="mtk15">await</span><span class="mtk1"> </span><span class="mtk11">fetch</span><span class="mtk1">(</span><span class="mtk8">&quot;https://jsonplaceholder.typicode.com/users&quot;</span><span class="mtk1">);</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk4">const</span><span class="mtk1"> </span><span class="mtk12">newData</span><span class="mtk1"> = </span><span class="mtk15">await</span><span class="mtk1"> </span><span class="mtk12">response</span><span class="mtk1">.</span><span class="mtk11">json</span><span class="mtk1">();</span></span></span> <span class="grvsc-line grvsc-line-highlighted"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk11">setTimeout</span><span class="mtk1">(() </span><span class="mtk4">=&gt;</span><span class="mtk1"> </span><span class="mtk11">setData</span><span class="mtk1">(</span><span class="mtk12">newData</span><span class="mtk1">), </span><span class="mtk7">2000</span><span class="mtk1">);</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> };</span></span></span> <span class="grvsc-line"><span class="grvsc-source"></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk11">useEffect</span><span class="mtk1">(() </span><span class="mtk4">=&gt;</span><span class="mtk1"> {</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk11">fetchData</span><span class="mtk1">();</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> }, []);</span></span></span> <span class="grvsc-line"><span class="grvsc-source"></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk15">return</span><span class="mtk1"> { </span><span class="mtk12">data</span><span class="mtk1">, </span><span class="mtk12">fetchData</span><span class="mtk1"> };</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1">};</span></span></span></code></pre> <p>Lastly, let’s consume the new Row Loader component we created and see the results in action!</p> <pre class="grvsc-container grvsc-has-line-highlighting default-dark" data-language="jsx" data-index="6"><code class="grvsc-code"><span class="grvsc-line"><span class="grvsc-source"><span class="mtk15">import</span><span class="mtk1"> </span><span class="mtk12">React</span><span class="mtk1">, { </span><span class="mtk12">useState</span><span class="mtk1">, </span><span class="mtk12">useEffect</span><span class="mtk1"> } </span><span class="mtk15">from</span><span class="mtk1"> </span><span class="mtk8">&quot;react&quot;</span><span class="mtk1">;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk15">import</span><span class="mtk1"> </span><span class="mtk12">Table</span><span class="mtk1"> </span><span class="mtk15">from</span><span class="mtk1"> </span><span class="mtk8">&quot;@mui/material/Table&quot;</span><span class="mtk1">;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk15">import</span><span class="mtk1"> </span><span class="mtk12">TableBody</span><span class="mtk1"> </span><span class="mtk15">from</span><span class="mtk1"> </span><span class="mtk8">&quot;@mui/material/TableBody&quot;</span><span class="mtk1">;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk15">import</span><span class="mtk1"> </span><span class="mtk12">TableCell</span><span class="mtk1"> </span><span class="mtk15">from</span><span class="mtk1"> </span><span class="mtk8">&quot;@mui/material/TableCell&quot;</span><span class="mtk1">;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk15">import</span><span class="mtk1"> </span><span class="mtk12">TableContainer</span><span class="mtk1"> </span><span class="mtk15">from</span><span class="mtk1"> </span><span class="mtk8">&quot;@mui/material/TableContainer&quot;</span><span class="mtk1">;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk15">import</span><span class="mtk1"> </span><span class="mtk12">TableHead</span><span class="mtk1"> </span><span class="mtk15">from</span><span class="mtk1"> </span><span class="mtk8">&quot;@mui/material/TableHead&quot;</span><span class="mtk1">;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk15">import</span><span class="mtk1"> </span><span class="mtk12">TableRow</span><span class="mtk1"> </span><span class="mtk15">from</span><span class="mtk1"> </span><span class="mtk8">&quot;@mui/material/TableRow&quot;</span><span class="mtk1">;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk15">import</span><span class="mtk1"> </span><span class="mtk12">Paper</span><span class="mtk1"> </span><span class="mtk15">from</span><span class="mtk1"> </span><span class="mtk8">&quot;@mui/material/Paper&quot;</span><span class="mtk1">;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk15">import</span><span class="mtk1"> { </span><span class="mtk12">Box</span><span class="mtk1">, </span><span class="mtk12">Button</span><span class="mtk1">, </span><span class="mtk12">Skeleton</span><span class="mtk1"> } </span><span class="mtk15">from</span><span class="mtk1"> </span><span class="mtk8">&quot;@mui/material&quot;</span><span class="mtk1">;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk15">export</span><span class="mtk1"> </span><span class="mtk15">default</span><span class="mtk1"> </span><span class="mtk4">function</span><span class="mtk1"> </span><span class="mtk11">App</span><span class="mtk1">() {</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk4">const</span><span class="mtk1"> { </span><span class="mtk12">data</span><span class="mtk1">, </span><span class="mtk12">fetchData</span><span class="mtk1"> } = </span><span class="mtk11">useFetch</span><span class="mtk1">();</span></span></span> <span class="grvsc-line"><span class="grvsc-source"></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk15">return</span><span class="mtk1"> (</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk17">&lt;</span><span class="mtk10">Box</span><span class="mtk17">&gt;</span></span></span> <span class="grvsc-line grvsc-line-highlighted"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk17">&lt;</span><span class="mtk10">Button</span><span class="mtk1"> </span><span class="mtk12">onClick</span><span class="mtk1">=</span><span class="mtk4">{</span><span class="mtk12">fetchData</span><span class="mtk4">}</span><span class="mtk1"> </span><span class="mtk12">variant</span><span class="mtk1">=</span><span class="mtk8">&quot;contained&quot;</span><span class="mtk17">&gt;</span></span></span> <span class="grvsc-line grvsc-line-highlighted"><span class="grvsc-source"><span class="mtk1"> Fetch Data</span></span></span> <span class="grvsc-line grvsc-line-highlighted"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk17">&lt;/</span><span class="mtk10">Button</span><span class="mtk17">&gt;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk17">&lt;</span><span class="mtk10">TableContainer</span><span class="mtk1"> </span><span class="mtk12">component</span><span class="mtk1">=</span><span class="mtk4">{</span><span class="mtk12">Paper</span><span class="mtk4">}</span><span class="mtk17">&gt;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk17">&lt;</span><span class="mtk10">Table</span><span class="mtk17">&gt;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk17">&lt;</span><span class="mtk10">TableHead</span><span class="mtk17">&gt;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk17">&lt;</span><span class="mtk10">TableRow</span><span class="mtk17">&gt;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk17">&lt;</span><span class="mtk10">TableCell</span><span class="mtk17">&gt;</span><span class="mtk1">Name</span><span class="mtk17">&lt;/</span><span class="mtk10">TableCell</span><span class="mtk17">&gt;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk17">&lt;</span><span class="mtk10">TableCell</span><span class="mtk17">&gt;</span><span class="mtk1">Email</span><span class="mtk17">&lt;/</span><span class="mtk10">TableCell</span><span class="mtk17">&gt;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk17">&lt;</span><span class="mtk10">TableCell</span><span class="mtk17">&gt;</span><span class="mtk1">Phone</span><span class="mtk17">&lt;/</span><span class="mtk10">TableCell</span><span class="mtk17">&gt;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk17">&lt;</span><span class="mtk10">TableCell</span><span class="mtk17">&gt;</span><span class="mtk1">Website</span><span class="mtk17">&lt;/</span><span class="mtk10">TableCell</span><span class="mtk17">&gt;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk17">&lt;/</span><span class="mtk10">TableRow</span><span class="mtk17">&gt;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk17">&lt;/</span><span class="mtk10">TableHead</span><span class="mtk17">&gt;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk17">&lt;</span><span class="mtk10">TableBody</span><span class="mtk17">&gt;</span></span></span> <span class="grvsc-line grvsc-line-highlighted"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk4">{</span><span class="mtk1">!</span><span class="mtk12">data</span><span class="mtk1"> ? (</span></span></span> <span class="grvsc-line grvsc-line-highlighted"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk17">&lt;</span><span class="mtk10">TableRowsLoader</span><span class="mtk1"> </span><span class="mtk12">rowsNum</span><span class="mtk1">=</span><span class="mtk4">{</span><span class="mtk7">10</span><span class="mtk4">}</span><span class="mtk1"> </span><span class="mtk17">/&gt;</span></span></span> <span class="grvsc-line grvsc-line-highlighted"><span class="grvsc-source"><span class="mtk1"> ) : (</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">data</span><span class="mtk1">?.</span><span class="mtk11">map</span><span class="mtk1">((</span><span class="mtk12">row</span><span class="mtk1">) </span><span class="mtk4">=&gt;</span><span class="mtk1"> (</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk17">&lt;</span><span class="mtk10">TableRow</span><span class="mtk1"> </span><span class="mtk12">key</span><span class="mtk1">=</span><span class="mtk4">{</span><span class="mtk12">row</span><span class="mtk1">.</span><span class="mtk12">name</span><span class="mtk4">}</span><span class="mtk17">&gt;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk17">&lt;</span><span class="mtk10">TableCell</span><span class="mtk1"> </span><span class="mtk12">component</span><span class="mtk1">=</span><span class="mtk8">&quot;th&quot;</span><span class="mtk1"> </span><span class="mtk12">scope</span><span class="mtk1">=</span><span class="mtk8">&quot;row&quot;</span><span class="mtk17">&gt;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk4">{</span><span class="mtk12">row</span><span class="mtk1">.</span><span class="mtk12">name</span><span class="mtk4">}</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk17">&lt;/</span><span class="mtk10">TableCell</span><span class="mtk17">&gt;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk17">&lt;</span><span class="mtk10">TableCell</span><span class="mtk17">&gt;</span><span class="mtk4">{</span><span class="mtk12">row</span><span class="mtk1">.</span><span class="mtk12">email</span><span class="mtk4">}</span><span class="mtk17">&lt;/</span><span class="mtk10">TableCell</span><span class="mtk17">&gt;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk17">&lt;</span><span class="mtk10">TableCell</span><span class="mtk17">&gt;</span><span class="mtk4">{</span><span class="mtk12">row</span><span class="mtk1">.</span><span class="mtk12">phone</span><span class="mtk4">}</span><span class="mtk17">&lt;/</span><span class="mtk10">TableCell</span><span class="mtk17">&gt;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk17">&lt;</span><span class="mtk10">TableCell</span><span class="mtk17">&gt;</span><span class="mtk4">{</span><span class="mtk12">row</span><span class="mtk1">.</span><span class="mtk12">website</span><span class="mtk4">}</span><span class="mtk17">&lt;/</span><span class="mtk10">TableCell</span><span class="mtk17">&gt;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk17">&lt;/</span><span class="mtk10">TableRow</span><span class="mtk17">&gt;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> ))</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> )</span><span class="mtk4">}</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk17">&lt;/</span><span class="mtk10">TableBody</span><span class="mtk17">&gt;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk17">&lt;/</span><span class="mtk10">Table</span><span class="mtk17">&gt;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk17">&lt;/</span><span class="mtk10">TableContainer</span><span class="mtk17">&gt;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk17">&lt;/</span><span class="mtk10">Box</span><span class="mtk17">&gt;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> );</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1">}</span></span></span> <span class="grvsc-line"><span class="grvsc-source"></span></span> <span class="grvsc-line grvsc-line-highlighted"><span class="grvsc-source"><span class="mtk4">const</span><span class="mtk1"> </span><span class="mtk11">TableRowsLoader</span><span class="mtk1"> = ({ </span><span class="mtk12">rowsNum</span><span class="mtk1"> }) </span><span class="mtk4">=&gt;</span><span class="mtk1"> {</span></span></span> <span class="grvsc-line grvsc-line-highlighted"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk15">return</span><span class="mtk1"> [...</span><span class="mtk10">Array</span><span class="mtk1">(</span><span class="mtk12">rowsNum</span><span class="mtk1">)].</span><span class="mtk11">map</span><span class="mtk1">((</span><span class="mtk12">row</span><span class="mtk1">, </span><span class="mtk12">index</span><span class="mtk1">) </span><span class="mtk4">=&gt;</span><span class="mtk1"> (</span></span></span> <span class="grvsc-line grvsc-line-highlighted"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk17">&lt;</span><span class="mtk10">TableRow</span><span class="mtk1"> </span><span class="mtk12">key</span><span class="mtk1">=</span><span class="mtk4">{</span><span class="mtk12">index</span><span class="mtk4">}</span><span class="mtk17">&gt;</span></span></span> <span class="grvsc-line grvsc-line-highlighted"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk17">&lt;</span><span class="mtk10">TableCell</span><span class="mtk1"> </span><span class="mtk12">component</span><span class="mtk1">=</span><span class="mtk8">&quot;th&quot;</span><span class="mtk1"> </span><span class="mtk12">scope</span><span class="mtk1">=</span><span class="mtk8">&quot;row&quot;</span><span class="mtk17">&gt;</span></span></span> <span class="grvsc-line grvsc-line-highlighted"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk17">&lt;</span><span class="mtk10">Skeleton</span><span class="mtk1"> </span><span class="mtk12">animation</span><span class="mtk1">=</span><span class="mtk8">&quot;wave&quot;</span><span class="mtk1"> </span><span class="mtk12">variant</span><span class="mtk1">=</span><span class="mtk8">&quot;text&quot;</span><span class="mtk1"> </span><span class="mtk17">/&gt;</span></span></span> <span class="grvsc-line grvsc-line-highlighted"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk17">&lt;/</span><span class="mtk10">TableCell</span><span class="mtk17">&gt;</span></span></span> <span class="grvsc-line grvsc-line-highlighted"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk17">&lt;</span><span class="mtk10">TableCell</span><span class="mtk17">&gt;</span></span></span> <span class="grvsc-line grvsc-line-highlighted"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk17">&lt;</span><span class="mtk10">Skeleton</span><span class="mtk1"> </span><span class="mtk12">animation</span><span class="mtk1">=</span><span class="mtk8">&quot;wave&quot;</span><span class="mtk1"> </span><span class="mtk12">variant</span><span class="mtk1">=</span><span class="mtk8">&quot;text&quot;</span><span class="mtk1"> </span><span class="mtk17">/&gt;</span></span></span> <span class="grvsc-line grvsc-line-highlighted"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk17">&lt;/</span><span class="mtk10">TableCell</span><span class="mtk17">&gt;</span></span></span> <span class="grvsc-line grvsc-line-highlighted"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk17">&lt;</span><span class="mtk10">TableCell</span><span class="mtk17">&gt;</span></span></span> <span class="grvsc-line grvsc-line-highlighted"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk17">&lt;</span><span class="mtk10">Skeleton</span><span class="mtk1"> </span><span class="mtk12">animation</span><span class="mtk1">=</span><span class="mtk8">&quot;wave&quot;</span><span class="mtk1"> </span><span class="mtk12">variant</span><span class="mtk1">=</span><span class="mtk8">&quot;text&quot;</span><span class="mtk1"> </span><span class="mtk17">/&gt;</span></span></span> <span class="grvsc-line grvsc-line-highlighted"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk17">&lt;/</span><span class="mtk10">TableCell</span><span class="mtk17">&gt;</span></span></span> <span class="grvsc-line grvsc-line-highlighted"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk17">&lt;</span><span class="mtk10">TableCell</span><span class="mtk17">&gt;</span></span></span> <span class="grvsc-line grvsc-line-highlighted"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk17">&lt;</span><span class="mtk10">Skeleton</span><span class="mtk1"> </span><span class="mtk12">animation</span><span class="mtk1">=</span><span class="mtk8">&quot;wave&quot;</span><span class="mtk1"> </span><span class="mtk12">variant</span><span class="mtk1">=</span><span class="mtk8">&quot;text&quot;</span><span class="mtk1"> </span><span class="mtk17">/&gt;</span></span></span> <span class="grvsc-line grvsc-line-highlighted"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk17">&lt;/</span><span class="mtk10">TableCell</span><span class="mtk17">&gt;</span></span></span> <span class="grvsc-line grvsc-line-highlighted"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk17">&lt;/</span><span class="mtk10">TableRow</span><span class="mtk17">&gt;</span></span></span> <span class="grvsc-line grvsc-line-highlighted"><span class="grvsc-source"><span class="mtk1"> ));</span></span></span> <span class="grvsc-line grvsc-line-highlighted"><span class="grvsc-source"><span class="mtk1">};</span></span></span> <span class="grvsc-line"><span class="grvsc-source"></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk4">const</span><span class="mtk1"> </span><span class="mtk11">useFetch</span><span class="mtk1"> = () </span><span class="mtk4">=&gt;</span><span class="mtk1"> {</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk4">const</span><span class="mtk1"> [</span><span class="mtk12">data</span><span class="mtk1">, </span><span class="mtk12">setData</span><span class="mtk1">] = </span><span class="mtk11">useState</span><span class="mtk1">();</span></span></span> <span class="grvsc-line"><span class="grvsc-source"></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk4">const</span><span class="mtk1"> </span><span class="mtk11">fetchData</span><span class="mtk1"> = </span><span class="mtk4">async</span><span class="mtk1"> () </span><span class="mtk4">=&gt;</span><span class="mtk1"> {</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk11">setData</span><span class="mtk1">();</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk4">const</span><span class="mtk1"> </span><span class="mtk12">response</span><span class="mtk1"> = </span><span class="mtk15">await</span><span class="mtk1"> </span><span class="mtk11">fetch</span><span class="mtk1">(</span><span class="mtk8">&quot;https://jsonplaceholder.typicode.com/users&quot;</span><span class="mtk1">);</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk4">const</span><span class="mtk1"> </span><span class="mtk12">newData</span><span class="mtk1"> = </span><span class="mtk15">await</span><span class="mtk1"> </span><span class="mtk12">response</span><span class="mtk1">.</span><span class="mtk11">json</span><span class="mtk1">();</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk11">setTimeout</span><span class="mtk1">(() </span><span class="mtk4">=&gt;</span><span class="mtk1"> </span><span class="mtk11">setData</span><span class="mtk1">(</span><span class="mtk12">newData</span><span class="mtk1">), </span><span class="mtk7">2000</span><span class="mtk1">);</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> };</span></span></span> <span class="grvsc-line"><span class="grvsc-source"></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk11">useEffect</span><span class="mtk1">(() </span><span class="mtk4">=&gt;</span><span class="mtk1"> {</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk11">fetchData</span><span class="mtk1">();</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> }, []);</span></span></span> <span class="grvsc-line"><span class="grvsc-source"></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk15">return</span><span class="mtk1"> { </span><span class="mtk12">data</span><span class="mtk1">, </span><span class="mtk12">fetchData</span><span class="mtk1"> };</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1">};</span></span></span> <span class="grvsc-line"><span class="grvsc-source"></span></span></code></pre> <div id="TableSkeletonLoaderFour" data-code data-height="400px"></div> <p>We also added a “Fetch Data” button to re-fetch and illustrate the Table loading action again.</p> <h2 id="summary" style="position:relative;"><a href="#summary" aria-label="summary permalink" class="anchor before"><svg aria-hidden="true" focusable="false" height="16" version="1.1" viewBox="0 0 16 16" width="16"><path fill-rule="evenodd" d="M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z"></path></svg></a>Summary</h2> <p>Skeleton loaders are an excellent option for loading content and improving the user experience. They’re particularly helpful for lazy loading independent components on the screen to enhance the speed to when users can first interact with elements.</p> <p>Bye for now 👋</p> <style class="grvsc-styles"> .grvsc-container { overflow: auto; position: relative; -webkit-overflow-scrolling: touch; padding-top: 1rem; padding-top: var(--grvsc-padding-top, var(--grvsc-padding-v, 1rem)); padding-bottom: 1rem; padding-bottom: var(--grvsc-padding-bottom, var(--grvsc-padding-v, 1rem)); border-radius: 8px; border-radius: var(--grvsc-border-radius, 8px); font-feature-settings: normal; line-height: 1.4; } .grvsc-code { display: table; } .grvsc-line { display: table-row; box-sizing: border-box; width: 100%; position: relative; } .grvsc-line > * { position: relative; } .grvsc-gutter-pad { display: table-cell; padding-left: 0.75rem; padding-left: calc(var(--grvsc-padding-left, var(--grvsc-padding-h, 1.5rem)) / 2); } .grvsc-gutter { display: table-cell; -webkit-user-select: none; -moz-user-select: none; user-select: none; } .grvsc-gutter::before { content: attr(data-content); } .grvsc-source { display: table-cell; padding-left: 1.5rem; padding-left: var(--grvsc-padding-left, var(--grvsc-padding-h, 1.5rem)); padding-right: 1.5rem; padding-right: var(--grvsc-padding-right, var(--grvsc-padding-h, 1.5rem)); } .grvsc-source:empty::after { content: ' '; -webkit-user-select: none; -moz-user-select: none; user-select: none; } .grvsc-gutter + .grvsc-source { padding-left: 0.75rem; padding-left: calc(var(--grvsc-padding-left, var(--grvsc-padding-h, 1.5rem)) / 2); } /* Line transformer styles */ .grvsc-has-line-highlighting > .grvsc-code > .grvsc-line::before { content: ' '; position: absolute; width: 100%; } .grvsc-line-diff-add::before { background-color: var(--grvsc-line-diff-add-background-color, rgba(0, 255, 60, 0.2)); } .grvsc-line-diff-del::before { background-color: var(--grvsc-line-diff-del-background-color, rgba(255, 0, 20, 0.2)); } .grvsc-line-number { padding: 0 2px; text-align: right; opacity: 0.7; } .default-dark { background-color: #1E1E1E; color: #D4D4D4; } .default-dark .mtk15 { color: #C586C0; } .default-dark .mtk1 { color: #D4D4D4; } .default-dark .mtk12 { color: #9CDCFE; } .default-dark .mtk8 { color: #CE9178; } .default-dark .mtk4 { color: #569CD6; } .default-dark .mtk11 { color: #DCDCAA; } .default-dark .mtk17 { color: #808080; } .default-dark .mtk10 { color: #4EC9B0; } .default-dark .mtk7 { color: #B5CEA8; } .default-dark .grvsc-line-highlighted::before { background-color: var(--grvsc-line-highlighted-background-color, rgba(255, 255, 255, 0.1)); box-shadow: inset var(--grvsc-line-highlighted-border-width, 4px) 0 0 0 var(--grvsc-line-highlighted-border-color, rgba(255, 255, 255, 0.5)); } </style><![CDATA[How to Create a Multiselect Component with Material UI (MUI)]]>https://muhimasri.commui-multiselecthttps://muhimasri.commui-multiselect<p>Multiselect in Material UI is an extended feature to the regular select or dropdown menu that enables users to select multiple values within the same input field.</p> <p>MUI provides a couple of convenient options to get a feature-rich multiselect component included in our project.</p> <p>In this tutorial, we’ll learn how to create a multiselect component using <code>Select</code> and <code>Autocomplete</code> with a customized menu list and removable tags/chips as values.</p> <p>Here is what the final code will look like:</p> <div data-codesandbox="mui-multi-select-kptq04"> <button>Run Code</button> </div> <p><em>If this is your first time working with MUI, please follow the <a href="https://mui.com/material-ui/getting-started/installation/">installation instructions</a> from the official documentation to get started.</em></p> <h2 id="using-select-component" style="position:relative;"><a href="#using-select-component" aria-label="using select component permalink" class="anchor before"><svg aria-hidden="true" focusable="false" height="16" version="1.1" viewBox="0 0 16 16" width="16"><path fill-rule="evenodd" d="M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z"></path></svg></a>Using Select Component</h2> <p>Multiselect at a basic level is similar to the regular <code>Select</code> component syntax except for adding <code>multiple</code> prop to enable multiple selections.</p> <pre class="grvsc-container grvsc-has-line-highlighting default-dark" data-language="jsx" data-index="0"><code class="grvsc-code"><span class="grvsc-line"><span class="grvsc-source"><span class="mtk15">import</span><span class="mtk1"> </span><span class="mtk12">React</span><span class="mtk1">, { </span><span class="mtk12">useState</span><span class="mtk1"> } </span><span class="mtk15">from</span><span class="mtk1"> </span><span class="mtk8">&quot;react&quot;</span><span class="mtk1">;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk15">import</span><span class="mtk1"> {</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">OutlinedInput</span><span class="mtk1">,</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">InputLabel</span><span class="mtk1">,</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">MenuItem</span><span class="mtk1">,</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">Select</span><span class="mtk1">,</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">FormControl</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1">} </span><span class="mtk15">from</span><span class="mtk1"> </span><span class="mtk8">&quot;@mui/material&quot;</span><span class="mtk1">;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk4">const</span><span class="mtk1"> </span><span class="mtk12">names</span><span class="mtk1"> = [</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk8">&quot;Humaira Sims&quot;</span><span class="mtk1">,</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk8">&quot;Santiago Solis&quot;</span><span class="mtk1">,</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk8">&quot;Dawid Floyd&quot;</span><span class="mtk1">,</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk8">&quot;Mateo Barlow&quot;</span><span class="mtk1">,</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk8">&quot;Samia Navarro&quot;</span><span class="mtk1">,</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk8">&quot;Kaden Fields&quot;</span><span class="mtk1">,</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk8">&quot;Genevieve Watkins&quot;</span><span class="mtk1">,</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk8">&quot;Mariah Hickman&quot;</span><span class="mtk1">,</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk8">&quot;Rocco Richardson&quot;</span><span class="mtk1">,</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk8">&quot;Harris Glenn&quot;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1">];</span></span></span> <span class="grvsc-line"><span class="grvsc-source"></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk15">export</span><span class="mtk1"> </span><span class="mtk15">default</span><span class="mtk1"> </span><span class="mtk4">function</span><span class="mtk1"> </span><span class="mtk11">MultiSelect</span><span class="mtk1">() {</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk4">const</span><span class="mtk1"> [</span><span class="mtk12">selectedNames</span><span class="mtk1">, </span><span class="mtk12">setSelectedNames</span><span class="mtk1">] = </span><span class="mtk11">useState</span><span class="mtk1">([]);</span></span></span> <span class="grvsc-line"><span class="grvsc-source"></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk15">return</span><span class="mtk1"> (</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk17">&lt;</span><span class="mtk10">FormControl</span><span class="mtk1"> </span><span class="mtk12">sx</span><span class="mtk1">=</span><span class="mtk4">{</span><span class="mtk1">{ </span><span class="mtk12">m:</span><span class="mtk1"> </span><span class="mtk7">1</span><span class="mtk1">, </span><span class="mtk12">width:</span><span class="mtk1"> </span><span class="mtk7">500</span><span class="mtk1"> }</span><span class="mtk4">}</span><span class="mtk17">&gt;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk17">&lt;</span><span class="mtk10">InputLabel</span><span class="mtk17">&gt;</span><span class="mtk1">Multiple Select</span><span class="mtk17">&lt;/</span><span class="mtk10">InputLabel</span><span class="mtk17">&gt;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk17">&lt;</span><span class="mtk10">Select</span></span></span> <span class="grvsc-line grvsc-line-highlighted"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">multiple</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">value</span><span class="mtk1">=</span><span class="mtk4">{</span><span class="mtk12">selectedNames</span><span class="mtk4">}</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">onChange</span><span class="mtk1">=</span><span class="mtk4">{</span><span class="mtk1">(</span><span class="mtk12">e</span><span class="mtk1">) </span><span class="mtk4">=&gt;</span><span class="mtk1"> </span><span class="mtk11">setSelectedNames</span><span class="mtk1">(</span><span class="mtk12">e</span><span class="mtk1">.</span><span class="mtk12">target</span><span class="mtk1">.</span><span class="mtk12">value</span><span class="mtk1">)</span><span class="mtk4">}</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">input</span><span class="mtk1">=</span><span class="mtk4">{</span><span class="mtk17">&lt;</span><span class="mtk10">OutlinedInput</span><span class="mtk1"> </span><span class="mtk12">label</span><span class="mtk1">=</span><span class="mtk8">&quot;Multiple Select&quot;</span><span class="mtk1"> </span><span class="mtk17">/&gt;</span><span class="mtk4">}</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk17">&gt;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk4">{</span><span class="mtk12">names</span><span class="mtk1">.</span><span class="mtk11">map</span><span class="mtk1">((</span><span class="mtk12">name</span><span class="mtk1">) </span><span class="mtk4">=&gt;</span><span class="mtk1"> (</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk17">&lt;</span><span class="mtk10">MenuItem</span><span class="mtk1"> </span><span class="mtk12">key</span><span class="mtk1">=</span><span class="mtk4">{</span><span class="mtk12">name</span><span class="mtk4">}</span><span class="mtk1"> </span><span class="mtk12">value</span><span class="mtk1">=</span><span class="mtk4">{</span><span class="mtk12">name</span><span class="mtk4">}</span><span class="mtk17">&gt;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk4">{</span><span class="mtk12">name</span><span class="mtk4">}</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk17">&lt;/</span><span class="mtk10">MenuItem</span><span class="mtk17">&gt;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> ))</span><span class="mtk4">}</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk17">&lt;/</span><span class="mtk10">Select</span><span class="mtk17">&gt;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk17">&lt;/</span><span class="mtk10">FormControl</span><span class="mtk17">&gt;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> );</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1">}</span></span></span></code></pre> <div id="MultiSelectOne" data-code></div> <h3 id="customize-selected-values" style="position:relative;"><a href="#customize-selected-values" aria-label="customize selected values permalink" class="anchor before"><svg aria-hidden="true" focusable="false" height="16" version="1.1" viewBox="0 0 16 16" width="16"><path fill-rule="evenodd" d="M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z"></path></svg></a>Customize Selected Values</h3> <p>To customize the selected values, we need to use the <code>renderValue</code> prop and loop through the selected values to insert them into the component of our choice. We use <code>Chip</code> in this example to make it look like tags.</p> <pre class="grvsc-container grvsc-has-line-highlighting default-dark" data-language="jsx" data-index="1"><code class="grvsc-code"><span class="grvsc-line"><span class="grvsc-source"><span class="mtk15">import</span><span class="mtk1"> </span><span class="mtk12">React</span><span class="mtk1">, { </span><span class="mtk12">useState</span><span class="mtk1"> } </span><span class="mtk15">from</span><span class="mtk1"> </span><span class="mtk8">&quot;react&quot;</span><span class="mtk1">;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk15">import</span><span class="mtk1"> {</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">OutlinedInput</span><span class="mtk1">,</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">InputLabel</span><span class="mtk1">,</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">MenuItem</span><span class="mtk1">,</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">Select</span><span class="mtk1">,</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">FormControl</span><span class="mtk1">,</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">Stack</span><span class="mtk1">,</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">Chip</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1">} </span><span class="mtk15">from</span><span class="mtk1"> </span><span class="mtk8">&quot;@mui/material&quot;</span><span class="mtk1">;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk4">const</span><span class="mtk1"> </span><span class="mtk12">names</span><span class="mtk1"> = [</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk8">&quot;Humaira Sims&quot;</span><span class="mtk1">,</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk8">&quot;Santiago Solis&quot;</span><span class="mtk1">,</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk8">&quot;Dawid Floyd&quot;</span><span class="mtk1">,</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk8">&quot;Mateo Barlow&quot;</span><span class="mtk1">,</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk8">&quot;Samia Navarro&quot;</span><span class="mtk1">,</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk8">&quot;Kaden Fields&quot;</span><span class="mtk1">,</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk8">&quot;Genevieve Watkins&quot;</span><span class="mtk1">,</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk8">&quot;Mariah Hickman&quot;</span><span class="mtk1">,</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk8">&quot;Rocco Richardson&quot;</span><span class="mtk1">,</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk8">&quot;Harris Glenn&quot;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1">];</span></span></span> <span class="grvsc-line"><span class="grvsc-source"></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk15">export</span><span class="mtk1"> </span><span class="mtk15">default</span><span class="mtk1"> </span><span class="mtk4">function</span><span class="mtk1"> </span><span class="mtk11">MultiSelect</span><span class="mtk1">() {</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk4">const</span><span class="mtk1"> [</span><span class="mtk12">selectedNames</span><span class="mtk1">, </span><span class="mtk12">setSelectedNames</span><span class="mtk1">] = </span><span class="mtk11">useState</span><span class="mtk1">([]);</span></span></span> <span class="grvsc-line"><span class="grvsc-source"></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk15">return</span><span class="mtk1"> (</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk17">&lt;</span><span class="mtk10">FormControl</span><span class="mtk1"> </span><span class="mtk12">sx</span><span class="mtk1">=</span><span class="mtk4">{</span><span class="mtk1">{ </span><span class="mtk12">m:</span><span class="mtk1"> </span><span class="mtk7">1</span><span class="mtk1">, </span><span class="mtk12">width:</span><span class="mtk1"> </span><span class="mtk7">500</span><span class="mtk1"> }</span><span class="mtk4">}</span><span class="mtk17">&gt;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk17">&lt;</span><span class="mtk10">InputLabel</span><span class="mtk17">&gt;</span><span class="mtk1">Multiple Select</span><span class="mtk17">&lt;/</span><span class="mtk10">InputLabel</span><span class="mtk17">&gt;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk17">&lt;</span><span class="mtk10">Select</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">multiple</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">value</span><span class="mtk1">=</span><span class="mtk4">{</span><span class="mtk12">selectedNames</span><span class="mtk4">}</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">onChange</span><span class="mtk1">=</span><span class="mtk4">{</span><span class="mtk1">(</span><span class="mtk12">e</span><span class="mtk1">) </span><span class="mtk4">=&gt;</span><span class="mtk1"> </span><span class="mtk11">setSelectedNames</span><span class="mtk1">(</span><span class="mtk12">e</span><span class="mtk1">.</span><span class="mtk12">target</span><span class="mtk1">.</span><span class="mtk12">value</span><span class="mtk1">)</span><span class="mtk4">}</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">input</span><span class="mtk1">=</span><span class="mtk4">{</span><span class="mtk17">&lt;</span><span class="mtk10">OutlinedInput</span><span class="mtk1"> </span><span class="mtk12">label</span><span class="mtk1">=</span><span class="mtk8">&quot;Multiple Select&quot;</span><span class="mtk1"> </span><span class="mtk17">/&gt;</span><span class="mtk4">}</span></span></span> <span class="grvsc-line grvsc-line-highlighted"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">renderValue</span><span class="mtk1">=</span><span class="mtk4">{</span><span class="mtk1">(</span><span class="mtk12">selected</span><span class="mtk1">) </span><span class="mtk4">=&gt;</span><span class="mtk1"> (</span></span></span> <span class="grvsc-line grvsc-line-highlighted"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk17">&lt;</span><span class="mtk10">Stack</span><span class="mtk1"> </span><span class="mtk12">gap</span><span class="mtk1">=</span><span class="mtk4">{</span><span class="mtk7">1</span><span class="mtk4">}</span><span class="mtk1"> </span><span class="mtk12">direction</span><span class="mtk1">=</span><span class="mtk8">&quot;row&quot;</span><span class="mtk1"> </span><span class="mtk12">flexWrap</span><span class="mtk1">=</span><span class="mtk8">&quot;wrap&quot;</span><span class="mtk17">&gt;</span></span></span> <span class="grvsc-line grvsc-line-highlighted"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk4">{</span><span class="mtk12">selected</span><span class="mtk1">.</span><span class="mtk11">map</span><span class="mtk1">((</span><span class="mtk12">value</span><span class="mtk1">) </span><span class="mtk4">=&gt;</span><span class="mtk1"> (</span></span></span> <span class="grvsc-line grvsc-line-highlighted"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk17">&lt;</span><span class="mtk10">Chip</span><span class="mtk1"> </span><span class="mtk12">key</span><span class="mtk1">=</span><span class="mtk4">{</span><span class="mtk12">value</span><span class="mtk4">}</span><span class="mtk1"> </span><span class="mtk12">label</span><span class="mtk1">=</span><span class="mtk4">{</span><span class="mtk12">value</span><span class="mtk4">}</span><span class="mtk1"> </span><span class="mtk17">/&gt;</span></span></span> <span class="grvsc-line grvsc-line-highlighted"><span class="grvsc-source"><span class="mtk1"> ))</span><span class="mtk4">}</span></span></span> <span class="grvsc-line grvsc-line-highlighted"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk17">&lt;/</span><span class="mtk10">Stack</span><span class="mtk17">&gt;</span></span></span> <span class="grvsc-line grvsc-line-highlighted"><span class="grvsc-source"><span class="mtk1"> )</span><span class="mtk4">}</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk17">&gt;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk4">{</span><span class="mtk12">names</span><span class="mtk1">.</span><span class="mtk11">map</span><span class="mtk1">((</span><span class="mtk12">name</span><span class="mtk1">) </span><span class="mtk4">=&gt;</span><span class="mtk1"> (</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk17">&lt;</span><span class="mtk10">MenuItem</span><span class="mtk1"> </span><span class="mtk12">key</span><span class="mtk1">=</span><span class="mtk4">{</span><span class="mtk12">name</span><span class="mtk4">}</span><span class="mtk1"> </span><span class="mtk12">value</span><span class="mtk1">=</span><span class="mtk4">{</span><span class="mtk12">name</span><span class="mtk4">}</span><span class="mtk17">&gt;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk4">{</span><span class="mtk12">name</span><span class="mtk4">}</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk17">&lt;/</span><span class="mtk10">MenuItem</span><span class="mtk17">&gt;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> ))</span><span class="mtk4">}</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk17">&lt;/</span><span class="mtk10">Select</span><span class="mtk17">&gt;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk17">&lt;/</span><span class="mtk10">FormControl</span><span class="mtk17">&gt;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> );</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1">}</span></span></span></code></pre> <div id="MultiSelectTwo" data-code></div> <p>We also added a <code>Stack</code> wrapper to align tags horizontally.</p> <h3 id="remove-selected-values" style="position:relative;"><a href="#remove-selected-values" aria-label="remove selected values permalink" class="anchor before"><svg aria-hidden="true" focusable="false" height="16" version="1.1" viewBox="0 0 16 16" width="16"><path fill-rule="evenodd" d="M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z"></path></svg></a>Remove Selected Values</h3> <p>To delete selected values, we need to define an <code>onDelete</code> handler and add a <code>deleteIcon</code> to display on the <code>Chip</code> component.</p> <div class="code-example"> <pre class="grvsc-container grvsc-has-line-highlighting default-dark" data-language="jsx" data-index="2"><code class="grvsc-code"><span class="grvsc-line"><span class="grvsc-source"><span class="mtk15">import</span><span class="mtk1"> </span><span class="mtk12">React</span><span class="mtk1">, { </span><span class="mtk12">useState</span><span class="mtk1"> } </span><span class="mtk15">from</span><span class="mtk1"> </span><span class="mtk8">&quot;react&quot;</span><span class="mtk1">;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk15">import</span><span class="mtk1"> {</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">OutlinedInput</span><span class="mtk1">,</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">InputLabel</span><span class="mtk1">,</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">MenuItem</span><span class="mtk1">,</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">Select</span><span class="mtk1">,</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">FormControl</span><span class="mtk1">,</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">Stack</span><span class="mtk1">,</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">Chip</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1">} </span><span class="mtk15">from</span><span class="mtk1"> </span><span class="mtk8">&quot;@mui/material&quot;</span><span class="mtk1">;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk15">import</span><span class="mtk1"> </span><span class="mtk12">CancelIcon</span><span class="mtk1"> </span><span class="mtk15">from</span><span class="mtk1"> </span><span class="mtk8">&quot;@mui/icons-material/Cancel&quot;</span><span class="mtk1">;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk4">const</span><span class="mtk1"> </span><span class="mtk12">names</span><span class="mtk1"> = [</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk8">&quot;Humaira Sims&quot;</span><span class="mtk1">,</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk8">&quot;Santiago Solis&quot;</span><span class="mtk1">,</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk8">&quot;Dawid Floyd&quot;</span><span class="mtk1">,</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk8">&quot;Mateo Barlow&quot;</span><span class="mtk1">,</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk8">&quot;Samia Navarro&quot;</span><span class="mtk1">,</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk8">&quot;Kaden Fields&quot;</span><span class="mtk1">,</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk8">&quot;Genevieve Watkins&quot;</span><span class="mtk1">,</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk8">&quot;Mariah Hickman&quot;</span><span class="mtk1">,</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk8">&quot;Rocco Richardson&quot;</span><span class="mtk1">,</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk8">&quot;Harris Glenn&quot;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1">];</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk15">export</span><span class="mtk1"> </span><span class="mtk15">default</span><span class="mtk1"> </span><span class="mtk4">function</span><span class="mtk1"> </span><span class="mtk11">MultiSelect</span><span class="mtk1">() {</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk4">const</span><span class="mtk1"> [</span><span class="mtk12">selectedNames</span><span class="mtk1">, </span><span class="mtk12">setSelectedNames</span><span class="mtk1">] = </span><span class="mtk11">useState</span><span class="mtk1">([]);</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk15">return</span><span class="mtk1"> (</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk17">&lt;</span><span class="mtk10">FormControl</span><span class="mtk1"> </span><span class="mtk12">sx</span><span class="mtk1">=</span><span class="mtk4">{</span><span class="mtk1">{ </span><span class="mtk12">m:</span><span class="mtk1"> </span><span class="mtk7">1</span><span class="mtk1">, </span><span class="mtk12">width:</span><span class="mtk1"> </span><span class="mtk7">500</span><span class="mtk1"> }</span><span class="mtk4">}</span><span class="mtk17">&gt;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk17">&lt;</span><span class="mtk10">InputLabel</span><span class="mtk17">&gt;</span><span class="mtk1">Multiple Select</span><span class="mtk17">&lt;/</span><span class="mtk10">InputLabel</span><span class="mtk17">&gt;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk17">&lt;</span><span class="mtk10">Select</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">multiple</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">value</span><span class="mtk1">=</span><span class="mtk4">{</span><span class="mtk12">selectedNames</span><span class="mtk4">}</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">onChange</span><span class="mtk1">=</span><span class="mtk4">{</span><span class="mtk1">(</span><span class="mtk12">e</span><span class="mtk1">) </span><span class="mtk4">=&gt;</span><span class="mtk1"> </span><span class="mtk11">setSelectedNames</span><span class="mtk1">(</span><span class="mtk12">e</span><span class="mtk1">.</span><span class="mtk12">target</span><span class="mtk1">.</span><span class="mtk12">value</span><span class="mtk1">)</span><span class="mtk4">}</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">input</span><span class="mtk1">=</span><span class="mtk4">{</span><span class="mtk17">&lt;</span><span class="mtk10">OutlinedInput</span><span class="mtk1"> </span><span class="mtk12">label</span><span class="mtk1">=</span><span class="mtk8">&quot;Multiple Select&quot;</span><span class="mtk1"> </span><span class="mtk17">/&gt;</span><span class="mtk4">}</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">renderValue</span><span class="mtk1">=</span><span class="mtk4">{</span><span class="mtk1">(</span><span class="mtk12">selected</span><span class="mtk1">) </span><span class="mtk4">=&gt;</span><span class="mtk1"> (</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk17">&lt;</span><span class="mtk10">Stack</span><span class="mtk1"> </span><span class="mtk12">gap</span><span class="mtk1">=</span><span class="mtk4">{</span><span class="mtk7">1</span><span class="mtk4">}</span><span class="mtk1"> </span><span class="mtk12">direction</span><span class="mtk1">=</span><span class="mtk8">&quot;row&quot;</span><span class="mtk1"> </span><span class="mtk12">flexWrap</span><span class="mtk1">=</span><span class="mtk8">&quot;wrap&quot;</span><span class="mtk17">&gt;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk4">{</span><span class="mtk12">selected</span><span class="mtk1">.</span><span class="mtk11">map</span><span class="mtk1">((</span><span class="mtk12">value</span><span class="mtk1">) </span><span class="mtk4">=&gt;</span><span class="mtk1"> (</span></span></span> <span class="grvsc-line grvsc-line-highlighted"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk17">&lt;</span><span class="mtk10">Chip</span></span></span> <span class="grvsc-line grvsc-line-highlighted"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">key</span><span class="mtk1">=</span><span class="mtk4">{</span><span class="mtk12">value</span><span class="mtk4">}</span></span></span> <span class="grvsc-line grvsc-line-highlighted"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">label</span><span class="mtk1">=</span><span class="mtk4">{</span><span class="mtk12">value</span><span class="mtk4">}</span></span></span> <span class="grvsc-line grvsc-line-highlighted"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">onDelete</span><span class="mtk1">=</span><span class="mtk4">{</span><span class="mtk1">() </span><span class="mtk4">=&gt;</span></span></span> <span class="grvsc-line grvsc-line-highlighted"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk11">setSelectedNames</span><span class="mtk1">(</span></span></span> <span class="grvsc-line grvsc-line-highlighted"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">selectedNames</span><span class="mtk1">.</span><span class="mtk11">filter</span><span class="mtk1">((</span><span class="mtk12">item</span><span class="mtk1">) </span><span class="mtk4">=&gt;</span><span class="mtk1"> </span><span class="mtk12">item</span><span class="mtk1"> !== </span><span class="mtk12">value</span><span class="mtk1">)</span></span></span> <span class="grvsc-line grvsc-line-highlighted"><span class="grvsc-source"><span class="mtk1"> )</span></span></span> <span class="grvsc-line grvsc-line-highlighted"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk4">}</span></span></span> <span class="grvsc-line grvsc-line-highlighted"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">deleteIcon</span><span class="mtk1">=</span><span class="mtk4">{</span></span></span> <span class="grvsc-line grvsc-line-highlighted"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk17">&lt;</span><span class="mtk10">CancelIcon</span></span></span> <span class="grvsc-line grvsc-line-highlighted"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">onMouseDown</span><span class="mtk1">=</span><span class="mtk4">{</span><span class="mtk1">(</span><span class="mtk12">event</span><span class="mtk1">) </span><span class="mtk4">=&gt;</span><span class="mtk1"> </span><span class="mtk12">event</span><span class="mtk1">.</span><span class="mtk11">stopPropagation</span><span class="mtk1">()</span><span class="mtk4">}</span></span></span> <span class="grvsc-line grvsc-line-highlighted"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk17">/&gt;</span></span></span> <span class="grvsc-line grvsc-line-highlighted"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk4">}</span></span></span> <span class="grvsc-line grvsc-line-highlighted"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk17">/&gt;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> ))</span><span class="mtk4">}</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk17">&lt;/</span><span class="mtk10">Stack</span><span class="mtk17">&gt;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> )</span><span class="mtk4">}</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk17">&gt;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk4">{</span><span class="mtk12">names</span><span class="mtk1">.</span><span class="mtk11">map</span><span class="mtk1">((</span><span class="mtk12">name</span><span class="mtk1">) </span><span class="mtk4">=&gt;</span><span class="mtk1"> (</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk17">&lt;</span><span class="mtk10">MenuItem</span><span class="mtk1"> </span><span class="mtk12">key</span><span class="mtk1">=</span><span class="mtk4">{</span><span class="mtk12">name</span><span class="mtk4">}</span><span class="mtk1"> </span><span class="mtk12">value</span><span class="mtk1">=</span><span class="mtk4">{</span><span class="mtk12">name</span><span class="mtk4">}</span><span class="mtk17">&gt;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk4">{</span><span class="mtk12">name</span><span class="mtk4">}</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk17">&lt;/</span><span class="mtk10">MenuItem</span><span class="mtk17">&gt;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> ))</span><span class="mtk4">}</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk17">&lt;/</span><span class="mtk10">Select</span><span class="mtk17">&gt;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk17">&lt;/</span><span class="mtk10">FormControl</span><span class="mtk17">&gt;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> );</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1">}</span></span></span></code></pre> <div id="MultiSelectThree" data-code></div> <p>Notice that we added an <code>onMouseDown</code> handler to stop the <code>Select</code> from opening the list as the user clicks the “Cancel” icon. It’s a small required hack because of some limitations on the <code>Select</code> component.</p> <h3 id="customize-menu-item" style="position:relative;"><a href="#customize-menu-item" aria-label="customize menu item permalink" class="anchor before"><svg aria-hidden="true" focusable="false" height="16" version="1.1" viewBox="0 0 16 16" width="16"><path fill-rule="evenodd" d="M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z"></path></svg></a>Customize Menu Item</h3> <p><code>MenuItem</code> is the component used to display all available options, and currently, any selected value has a light background color. Below, we will enhance it by adding a checkmark icon to make selections more visible.</p> <pre class="grvsc-container grvsc-has-line-highlighting default-dark" data-language="jsx" data-index="3"><code class="grvsc-code"><span class="grvsc-line"><span class="grvsc-source"><span class="mtk15">import</span><span class="mtk1"> </span><span class="mtk12">React</span><span class="mtk1">, { </span><span class="mtk12">useState</span><span class="mtk1"> } </span><span class="mtk15">from</span><span class="mtk1"> </span><span class="mtk8">&quot;react&quot;</span><span class="mtk1">;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk15">import</span><span class="mtk1"> {</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">OutlinedInput</span><span class="mtk1">,</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">InputLabel</span><span class="mtk1">,</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">MenuItem</span><span class="mtk1">,</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">Select</span><span class="mtk1">,</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">FormControl</span><span class="mtk1">,</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">Stack</span><span class="mtk1">,</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">Chip</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1">} </span><span class="mtk15">from</span><span class="mtk1"> </span><span class="mtk8">&quot;@mui/material&quot;</span><span class="mtk1">;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk15">import</span><span class="mtk1"> </span><span class="mtk12">CancelIcon</span><span class="mtk1"> </span><span class="mtk15">from</span><span class="mtk1"> </span><span class="mtk8">&quot;@mui/icons-material/Cancel&quot;</span><span class="mtk1">;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk15">import</span><span class="mtk1"> </span><span class="mtk12">CheckIcon</span><span class="mtk1"> </span><span class="mtk15">from</span><span class="mtk1"> </span><span class="mtk8">&quot;@mui/icons-material/Check&quot;</span><span class="mtk1">;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk4">const</span><span class="mtk1"> </span><span class="mtk12">names</span><span class="mtk1"> = [</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk8">&quot;Humaira Sims&quot;</span><span class="mtk1">,</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk8">&quot;Santiago Solis&quot;</span><span class="mtk1">,</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk8">&quot;Dawid Floyd&quot;</span><span class="mtk1">,</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk8">&quot;Mateo Barlow&quot;</span><span class="mtk1">,</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk8">&quot;Samia Navarro&quot;</span><span class="mtk1">,</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk8">&quot;Kaden Fields&quot;</span><span class="mtk1">,</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk8">&quot;Genevieve Watkins&quot;</span><span class="mtk1">,</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk8">&quot;Mariah Hickman&quot;</span><span class="mtk1">,</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk8">&quot;Rocco Richardson&quot;</span><span class="mtk1">,</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk8">&quot;Harris Glenn&quot;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1">];</span></span></span> <span class="grvsc-line"><span class="grvsc-source"></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk15">export</span><span class="mtk1"> </span><span class="mtk15">default</span><span class="mtk1"> </span><span class="mtk4">function</span><span class="mtk1"> </span><span class="mtk11">MultiSelect</span><span class="mtk1">() {</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk4">const</span><span class="mtk1"> [</span><span class="mtk12">selectedNames</span><span class="mtk1">, </span><span class="mtk12">setSelectedNames</span><span class="mtk1">] = </span><span class="mtk11">useState</span><span class="mtk1">([]);</span></span></span> <span class="grvsc-line"><span class="grvsc-source"></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk15">return</span><span class="mtk1"> (</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk17">&lt;</span><span class="mtk10">FormControl</span><span class="mtk1"> </span><span class="mtk12">sx</span><span class="mtk1">=</span><span class="mtk4">{</span><span class="mtk1">{ </span><span class="mtk12">m:</span><span class="mtk1"> </span><span class="mtk7">1</span><span class="mtk1">, </span><span class="mtk12">width:</span><span class="mtk1"> </span><span class="mtk7">500</span><span class="mtk1"> }</span><span class="mtk4">}</span><span class="mtk17">&gt;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk17">&lt;</span><span class="mtk10">InputLabel</span><span class="mtk17">&gt;</span><span class="mtk1">Multiple Select</span><span class="mtk17">&lt;/</span><span class="mtk10">InputLabel</span><span class="mtk17">&gt;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk17">&lt;</span><span class="mtk10">Select</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">multiple</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">value</span><span class="mtk1">=</span><span class="mtk4">{</span><span class="mtk12">selectedNames</span><span class="mtk4">}</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">onChange</span><span class="mtk1">=</span><span class="mtk4">{</span><span class="mtk1">(</span><span class="mtk12">e</span><span class="mtk1">) </span><span class="mtk4">=&gt;</span><span class="mtk1"> </span><span class="mtk11">setSelectedNames</span><span class="mtk1">(</span><span class="mtk12">e</span><span class="mtk1">.</span><span class="mtk12">target</span><span class="mtk1">.</span><span class="mtk12">value</span><span class="mtk1">)</span><span class="mtk4">}</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">input</span><span class="mtk1">=</span><span class="mtk4">{</span><span class="mtk17">&lt;</span><span class="mtk10">OutlinedInput</span><span class="mtk1"> </span><span class="mtk12">label</span><span class="mtk1">=</span><span class="mtk8">&quot;Multiple Select&quot;</span><span class="mtk1"> </span><span class="mtk17">/&gt;</span><span class="mtk4">}</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">renderValue</span><span class="mtk1">=</span><span class="mtk4">{</span><span class="mtk1">(</span><span class="mtk12">selected</span><span class="mtk1">) </span><span class="mtk4">=&gt;</span><span class="mtk1"> (</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk17">&lt;</span><span class="mtk10">Stack</span><span class="mtk1"> </span><span class="mtk12">gap</span><span class="mtk1">=</span><span class="mtk4">{</span><span class="mtk7">1</span><span class="mtk4">}</span><span class="mtk1"> </span><span class="mtk12">direction</span><span class="mtk1">=</span><span class="mtk8">&quot;row&quot;</span><span class="mtk1"> </span><span class="mtk12">flexWrap</span><span class="mtk1">=</span><span class="mtk8">&quot;wrap&quot;</span><span class="mtk17">&gt;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk4">{</span><span class="mtk12">selected</span><span class="mtk1">.</span><span class="mtk11">map</span><span class="mtk1">((</span><span class="mtk12">value</span><span class="mtk1">) </span><span class="mtk4">=&gt;</span><span class="mtk1"> (</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk17">&lt;</span><span class="mtk10">Chip</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">key</span><span class="mtk1">=</span><span class="mtk4">{</span><span class="mtk12">value</span><span class="mtk4">}</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">label</span><span class="mtk1">=</span><span class="mtk4">{</span><span class="mtk12">value</span><span class="mtk4">}</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">onDelete</span><span class="mtk1">=</span><span class="mtk4">{</span><span class="mtk1">() </span><span class="mtk4">=&gt;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk11">setSelectedNames</span><span class="mtk1">(</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">selectedNames</span><span class="mtk1">.</span><span class="mtk11">filter</span><span class="mtk1">((</span><span class="mtk12">item</span><span class="mtk1">) </span><span class="mtk4">=&gt;</span><span class="mtk1"> </span><span class="mtk12">item</span><span class="mtk1"> !== </span><span class="mtk12">value</span><span class="mtk1">)</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> )</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk4">}</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">deleteIcon</span><span class="mtk1">=</span><span class="mtk4">{</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk17">&lt;</span><span class="mtk10">CancelIcon</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">onMouseDown</span><span class="mtk1">=</span><span class="mtk4">{</span><span class="mtk1">(</span><span class="mtk12">event</span><span class="mtk1">) </span><span class="mtk4">=&gt;</span><span class="mtk1"> </span><span class="mtk12">event</span><span class="mtk1">.</span><span class="mtk11">stopPropagation</span><span class="mtk1">()</span><span class="mtk4">}</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk17">/&gt;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk4">}</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk17">/&gt;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> ))</span><span class="mtk4">}</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk17">&lt;/</span><span class="mtk10">Stack</span><span class="mtk17">&gt;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> )</span><span class="mtk4">}</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk17">&gt;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk4">{</span><span class="mtk12">names</span><span class="mtk1">.</span><span class="mtk11">map</span><span class="mtk1">((</span><span class="mtk12">name</span><span class="mtk1">) </span><span class="mtk4">=&gt;</span><span class="mtk1"> (</span></span></span> <span class="grvsc-line grvsc-line-highlighted"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk17">&lt;</span><span class="mtk10">MenuItem</span></span></span> <span class="grvsc-line grvsc-line-highlighted"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">key</span><span class="mtk1">=</span><span class="mtk4">{</span><span class="mtk12">name</span><span class="mtk4">}</span></span></span> <span class="grvsc-line grvsc-line-highlighted"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">value</span><span class="mtk1">=</span><span class="mtk4">{</span><span class="mtk12">name</span><span class="mtk4">}</span></span></span> <span class="grvsc-line grvsc-line-highlighted"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">sx</span><span class="mtk1">=</span><span class="mtk4">{</span><span class="mtk1">{ </span><span class="mtk12">justifyContent:</span><span class="mtk1"> </span><span class="mtk8">&quot;space-between&quot;</span><span class="mtk1"> }</span><span class="mtk4">}</span></span></span> <span class="grvsc-line grvsc-line-highlighted"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk17">&gt;</span></span></span> <span class="grvsc-line grvsc-line-highlighted"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk4">{</span><span class="mtk12">name</span><span class="mtk4">}</span></span></span> <span class="grvsc-line grvsc-line-highlighted"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk4">{</span><span class="mtk12">selectedNames</span><span class="mtk1">.</span><span class="mtk11">includes</span><span class="mtk1">(</span><span class="mtk12">name</span><span class="mtk1">) ? </span><span class="mtk17">&lt;</span><span class="mtk10">CheckIcon</span><span class="mtk1"> </span><span class="mtk12">color</span><span class="mtk1">=</span><span class="mtk8">&quot;info&quot;</span><span class="mtk1"> </span><span class="mtk17">/&gt;</span><span class="mtk1"> : </span><span class="mtk4">null}</span></span></span> <span class="grvsc-line grvsc-line-highlighted"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk17">&lt;/</span><span class="mtk10">MenuItem</span><span class="mtk17">&gt;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> ))</span><span class="mtk4">}</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk17">&lt;/</span><span class="mtk10">Select</span><span class="mtk17">&gt;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk17">&lt;/</span><span class="mtk10">FormControl</span><span class="mtk17">&gt;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> );</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1">}</span></span></span></code></pre> <div id="MultiSelectFour" data-code></div> <h2 id="using-autocomplete-component" style="position:relative;"><a href="#using-autocomplete-component" aria-label="using autocomplete component permalink" class="anchor before"><svg aria-hidden="true" focusable="false" height="16" version="1.1" viewBox="0 0 16 16" width="16"><path fill-rule="evenodd" d="M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z"></path></svg></a>Using Autocomplete Component</h2> <p><code>Autocomplete</code> is similar to the <code>Select</code> component in terms of providing a list of options with a multiselect feature. However, it’s a regular text input enhanced by a panel of suggested options and can be an excellent alternative for more advanced features.</p> <p>For example, the basic usage below will provide us with all the features we customized in the previous section and more!</p> <pre class="grvsc-container default-dark" data-language="jsx" data-index="4"><code class="grvsc-code"><span class="grvsc-line"><span class="grvsc-source"><span class="mtk15">import</span><span class="mtk1"> </span><span class="mtk12">React</span><span class="mtk1"> </span><span class="mtk15">from</span><span class="mtk1"> </span><span class="mtk8">&quot;react&quot;</span><span class="mtk1">;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk15">import</span><span class="mtk1"> { </span><span class="mtk12">TextField</span><span class="mtk1">, </span><span class="mtk12">Autocomplete</span><span class="mtk1"> } </span><span class="mtk15">from</span><span class="mtk1"> </span><span class="mtk8">&quot;@mui/material&quot;</span><span class="mtk1">;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk4">const</span><span class="mtk1"> </span><span class="mtk12">names</span><span class="mtk1"> = [</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk8">&quot;Humaira Sims&quot;</span><span class="mtk1">,</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk8">&quot;Santiago Solis&quot;</span><span class="mtk1">,</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk8">&quot;Dawid Floyd&quot;</span><span class="mtk1">,</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk8">&quot;Mateo Barlow&quot;</span><span class="mtk1">,</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk8">&quot;Samia Navarro&quot;</span><span class="mtk1">,</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk8">&quot;Kaden Fields&quot;</span><span class="mtk1">,</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk8">&quot;Genevieve Watkins&quot;</span><span class="mtk1">,</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk8">&quot;Mariah Hickman&quot;</span><span class="mtk1">,</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk8">&quot;Rocco Richardson&quot;</span><span class="mtk1">,</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk8">&quot;Harris Glenn&quot;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1">];</span></span></span> <span class="grvsc-line"><span class="grvsc-source"></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk15">export</span><span class="mtk1"> </span><span class="mtk15">default</span><span class="mtk1"> </span><span class="mtk4">function</span><span class="mtk1"> </span><span class="mtk11">MultiSelect</span><span class="mtk1">() {</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk15">return</span><span class="mtk1"> (</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk17">&lt;</span><span class="mtk10">Autocomplete</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">sx</span><span class="mtk1">=</span><span class="mtk4">{</span><span class="mtk1">{ </span><span class="mtk12">m:</span><span class="mtk1"> </span><span class="mtk7">1</span><span class="mtk1">, </span><span class="mtk12">width:</span><span class="mtk1"> </span><span class="mtk7">500</span><span class="mtk1"> }</span><span class="mtk4">}</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">multiple</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">options</span><span class="mtk1">=</span><span class="mtk4">{</span><span class="mtk12">names</span><span class="mtk4">}</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">getOptionLabel</span><span class="mtk1">=</span><span class="mtk4">{</span><span class="mtk1">(</span><span class="mtk12">option</span><span class="mtk1">) </span><span class="mtk4">=&gt;</span><span class="mtk1"> </span><span class="mtk12">option</span><span class="mtk4">}</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">disableCloseOnSelect</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">renderInput</span><span class="mtk1">=</span><span class="mtk4">{</span><span class="mtk1">(</span><span class="mtk12">params</span><span class="mtk1">) </span><span class="mtk4">=&gt;</span><span class="mtk1"> (</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk17">&lt;</span><span class="mtk10">TextField</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk4">{</span><span class="mtk1">...</span><span class="mtk12">params</span><span class="mtk4">}</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">variant</span><span class="mtk1">=</span><span class="mtk8">&quot;outlined&quot;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">label</span><span class="mtk1">=</span><span class="mtk8">&quot;Multiple Autocomplete&quot;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">placeholder</span><span class="mtk1">=</span><span class="mtk8">&quot;Multiple Autocomplete&quot;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk17">/&gt;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> )</span><span class="mtk4">}</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk17">/&gt;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> );</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1">}</span></span></span></code></pre> <div id="MultiSelectFive" data-height="300px" data-code></div> <p>As we can see above, the code is shorter than the <code>Select</code> component, and we get the following functionalities out of the box:</p> <ul> <li>Autocomplete on user input.</li> <li><code>Chip</code> component for selected values by default.</li> <li>Multiselect with adding and removing all values option.</li> </ul> <p>Additionally, we are no longer required to add <code>useState</code> to the manage list. Instead, we can use the <code>onChange</code> prop to detect any value changes in the list.</p> <p>For reference, <a href="https://mui.com/material-ui/api/autocomplete/">this link has the official <code>Autocomplete</code> component API from Material UI</a></p> <p>The only thing we are missing is adding a check mark on selected values. We can use similar code from the previous section using the <code>MenuItem</code> component, but we no longer need to loop through the list. Instead, <code>Autocomplete</code> provides a <code>renderOption</code> prop fired on every item.</p> <pre class="grvsc-container grvsc-has-line-highlighting default-dark" data-language="jsx" data-index="5"><code class="grvsc-code"><span class="grvsc-line"><span class="grvsc-source"><span class="mtk15">import</span><span class="mtk1"> </span><span class="mtk12">React</span><span class="mtk1"> </span><span class="mtk15">from</span><span class="mtk1"> </span><span class="mtk8">&quot;react&quot;</span><span class="mtk1">;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk15">import</span><span class="mtk1"> { </span><span class="mtk12">TextField</span><span class="mtk1">, </span><span class="mtk12">Autocomplete</span><span class="mtk1">, </span><span class="mtk12">MenuItem</span><span class="mtk1"> } </span><span class="mtk15">from</span><span class="mtk1"> </span><span class="mtk8">&quot;@mui/material&quot;</span><span class="mtk1">;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk15">import</span><span class="mtk1"> </span><span class="mtk12">CheckIcon</span><span class="mtk1"> </span><span class="mtk15">from</span><span class="mtk1"> </span><span class="mtk8">&quot;@mui/icons-material/Check&quot;</span><span class="mtk1">;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk4">const</span><span class="mtk1"> </span><span class="mtk12">names</span><span class="mtk1"> = [</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk8">&quot;Humaira Sims&quot;</span><span class="mtk1">,</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk8">&quot;Santiago Solis&quot;</span><span class="mtk1">,</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk8">&quot;Dawid Floyd&quot;</span><span class="mtk1">,</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk8">&quot;Mateo Barlow&quot;</span><span class="mtk1">,</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk8">&quot;Samia Navarro&quot;</span><span class="mtk1">,</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk8">&quot;Kaden Fields&quot;</span><span class="mtk1">,</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk8">&quot;Genevieve Watkins&quot;</span><span class="mtk1">,</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk8">&quot;Mariah Hickman&quot;</span><span class="mtk1">,</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk8">&quot;Rocco Richardson&quot;</span><span class="mtk1">,</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk8">&quot;Harris Glenn&quot;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1">];</span></span></span> <span class="grvsc-line"><span class="grvsc-source"></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk15">export</span><span class="mtk1"> </span><span class="mtk15">default</span><span class="mtk1"> </span><span class="mtk4">function</span><span class="mtk1"> </span><span class="mtk11">MultiSelect</span><span class="mtk1">() {</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk15">return</span><span class="mtk1"> (</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk17">&lt;</span><span class="mtk10">Autocomplete</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">sx</span><span class="mtk1">=</span><span class="mtk4">{</span><span class="mtk1">{ </span><span class="mtk12">m:</span><span class="mtk1"> </span><span class="mtk7">1</span><span class="mtk1">, </span><span class="mtk12">width:</span><span class="mtk1"> </span><span class="mtk7">500</span><span class="mtk1"> }</span><span class="mtk4">}</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">multiple</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">options</span><span class="mtk1">=</span><span class="mtk4">{</span><span class="mtk12">names</span><span class="mtk4">}</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">getOptionLabel</span><span class="mtk1">=</span><span class="mtk4">{</span><span class="mtk1">(</span><span class="mtk12">option</span><span class="mtk1">) </span><span class="mtk4">=&gt;</span><span class="mtk1"> </span><span class="mtk12">option</span><span class="mtk4">}</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">disableCloseOnSelect</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">renderInput</span><span class="mtk1">=</span><span class="mtk4">{</span><span class="mtk1">(</span><span class="mtk12">params</span><span class="mtk1">) </span><span class="mtk4">=&gt;</span><span class="mtk1"> (</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk17">&lt;</span><span class="mtk10">TextField</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk4">{</span><span class="mtk1">...</span><span class="mtk12">params</span><span class="mtk4">}</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">variant</span><span class="mtk1">=</span><span class="mtk8">&quot;outlined&quot;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">label</span><span class="mtk1">=</span><span class="mtk8">&quot;Multiple Autocomplete&quot;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">placeholder</span><span class="mtk1">=</span><span class="mtk8">&quot;Multiple Autocomplete&quot;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk17">/&gt;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> )</span><span class="mtk4">}</span></span></span> <span class="grvsc-line grvsc-line-highlighted"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">renderOption</span><span class="mtk1">=</span><span class="mtk4">{</span><span class="mtk1">(</span><span class="mtk12">props</span><span class="mtk1">, </span><span class="mtk12">option</span><span class="mtk1">, { </span><span class="mtk12">selected</span><span class="mtk1"> }) </span><span class="mtk4">=&gt;</span><span class="mtk1"> (</span></span></span> <span class="grvsc-line grvsc-line-highlighted"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk17">&lt;</span><span class="mtk10">MenuItem</span></span></span> <span class="grvsc-line grvsc-line-highlighted"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk4">{</span><span class="mtk1">...</span><span class="mtk12">props</span><span class="mtk4">}</span></span></span> <span class="grvsc-line grvsc-line-highlighted"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">key</span><span class="mtk1">=</span><span class="mtk4">{</span><span class="mtk12">option</span><span class="mtk4">}</span></span></span> <span class="grvsc-line grvsc-line-highlighted"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">value</span><span class="mtk1">=</span><span class="mtk4">{</span><span class="mtk12">option</span><span class="mtk4">}</span></span></span> <span class="grvsc-line grvsc-line-highlighted"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">sx</span><span class="mtk1">=</span><span class="mtk4">{</span><span class="mtk1">{ </span><span class="mtk12">justifyContent:</span><span class="mtk1"> </span><span class="mtk8">&quot;space-between&quot;</span><span class="mtk1"> }</span><span class="mtk4">}</span></span></span> <span class="grvsc-line grvsc-line-highlighted"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk17">&gt;</span></span></span> <span class="grvsc-line grvsc-line-highlighted"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk4">{</span><span class="mtk12">option</span><span class="mtk4">}</span></span></span> <span class="grvsc-line grvsc-line-highlighted"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk4">{</span><span class="mtk12">selected</span><span class="mtk1"> ? </span><span class="mtk17">&lt;</span><span class="mtk10">CheckIcon</span><span class="mtk1"> </span><span class="mtk12">color</span><span class="mtk1">=</span><span class="mtk8">&quot;info&quot;</span><span class="mtk1"> </span><span class="mtk17">/&gt;</span><span class="mtk1"> : </span><span class="mtk4">null}</span></span></span> <span class="grvsc-line grvsc-line-highlighted"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk17">&lt;/</span><span class="mtk10">MenuItem</span><span class="mtk17">&gt;</span></span></span> <span class="grvsc-line grvsc-line-highlighted"><span class="grvsc-source"><span class="mtk1"> )</span><span class="mtk4">}</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk17">/&gt;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> );</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1">}</span></span></span></code></pre> <div id="MultiSelectSix" data-height="300px" data-code></div> <h2 id="summary" style="position:relative;"><a href="#summary" aria-label="summary permalink" class="anchor before"><svg aria-hidden="true" focusable="false" height="16" version="1.1" viewBox="0 0 16 16" width="16"><path fill-rule="evenodd" d="M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z"></path></svg></a>Summary</h2> <p>Both components are great for implementing a multiselect feature. However, the <code>Select</code> component is sufficient if we are looking for a simple solution without adding, removing, and auto-completing. Otherwise, <code>Autocomplete</code> is recommended for more advanced features.</p> <p>Bye for now 👋</p> <style class="grvsc-styles"> .grvsc-container { overflow: auto; position: relative; -webkit-overflow-scrolling: touch; padding-top: 1rem; padding-top: var(--grvsc-padding-top, var(--grvsc-padding-v, 1rem)); padding-bottom: 1rem; padding-bottom: var(--grvsc-padding-bottom, var(--grvsc-padding-v, 1rem)); border-radius: 8px; border-radius: var(--grvsc-border-radius, 8px); font-feature-settings: normal; line-height: 1.4; } .grvsc-code { display: table; } .grvsc-line { display: table-row; box-sizing: border-box; width: 100%; position: relative; } .grvsc-line > * { position: relative; } .grvsc-gutter-pad { display: table-cell; padding-left: 0.75rem; padding-left: calc(var(--grvsc-padding-left, var(--grvsc-padding-h, 1.5rem)) / 2); } .grvsc-gutter { display: table-cell; -webkit-user-select: none; -moz-user-select: none; user-select: none; } .grvsc-gutter::before { content: attr(data-content); } .grvsc-source { display: table-cell; padding-left: 1.5rem; padding-left: var(--grvsc-padding-left, var(--grvsc-padding-h, 1.5rem)); padding-right: 1.5rem; padding-right: var(--grvsc-padding-right, var(--grvsc-padding-h, 1.5rem)); } .grvsc-source:empty::after { content: ' '; -webkit-user-select: none; -moz-user-select: none; user-select: none; } .grvsc-gutter + .grvsc-source { padding-left: 0.75rem; padding-left: calc(var(--grvsc-padding-left, var(--grvsc-padding-h, 1.5rem)) / 2); } /* Line transformer styles */ .grvsc-has-line-highlighting > .grvsc-code > .grvsc-line::before { content: ' '; position: absolute; width: 100%; } .grvsc-line-diff-add::before { background-color: var(--grvsc-line-diff-add-background-color, rgba(0, 255, 60, 0.2)); } .grvsc-line-diff-del::before { background-color: var(--grvsc-line-diff-del-background-color, rgba(255, 0, 20, 0.2)); } .grvsc-line-number { padding: 0 2px; text-align: right; opacity: 0.7; } .default-dark { background-color: #1E1E1E; color: #D4D4D4; } .default-dark .mtk15 { color: #C586C0; } .default-dark .mtk1 { color: #D4D4D4; } .default-dark .mtk12 { color: #9CDCFE; } .default-dark .mtk8 { color: #CE9178; } .default-dark .mtk4 { color: #569CD6; } .default-dark .mtk11 { color: #DCDCAA; } .default-dark .mtk17 { color: #808080; } .default-dark .mtk10 { color: #4EC9B0; } .default-dark .mtk7 { color: #B5CEA8; } .default-dark .grvsc-line-highlighted::before { background-color: var(--grvsc-line-highlighted-background-color, rgba(255, 255, 255, 0.1)); box-shadow: inset var(--grvsc-line-highlighted-border-width, 4px) 0 0 0 var(--grvsc-line-highlighted-border-color, rgba(255, 255, 255, 0.5)); } </style><![CDATA[How to Create and Customize Variants with Material UI (MUI)]]>https://muhimasri.comcreate-and-customize-variants-with-muihttps://muhimasri.comcreate-and-customize-variants-with-mui<p><code>variant</code> is a built-in property used in MUI components. Its primary usage is to provide different look and feel options to fulfill the products’ branding and design. For example, a Button can have an “outlined” or “contained” variant.</p> <p><span class="gatsby-resp-image-wrapper" style="position: relative; display: block; margin-left: auto; margin-right: auto; max-width: 665px; " > <a class="gatsby-resp-image-link" href="/static/410d5bded7201ebf462003ab47fd1312/5f4af/button-variants.png" style="display: block" target="_blank" rel="noopener" > <span class="gatsby-resp-image-background-image" style="padding-bottom: 29.444444444444446%; position: relative; bottom: 0; left: 0; background-image: url('data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABQAAAAGCAYAAADDl76dAAAACXBIWXMAACToAAAk6AGCYwUcAAABFUlEQVR42q2Qz0rDQBDG+w4e9eYTePSkgrSI4MVXERSseBK8VFJF8Am0SvQt9BALguaQ5o+WiKVQYg81Js2f/bmbaPDowWFnvtmZnY/5tsY/W00F4+WDjhFweR9wIfGqW2JH3lX91p0Uj+NUkOVIF5ULAWkmmMpeRbh55jC7/cTasUNds1k8tGi0HdZPHOabJg2tR5LmyIP/ntAbxnijGHMQ0e2HjCYpiSTNJXtBuHHqMLP1yFLLZvnIZuHAYlVzqbdd5nZMVloWcZLJAXgdJ/SDKX6QYL598uCHjMOs2LIi1I0hu7rH/o3H3rXCZ5p6mav6+d1AShNEUlb6LTlVkkUpWW0XqcaP5L+aGs5/e0Fe5pRfyBeaKbS9exEJ1AAAAABJRU5ErkJggg=='); background-size: cover; display: block;" ></span> <img class="gatsby-resp-image-image" alt="Button Variants" title="" src="/static/410d5bded7201ebf462003ab47fd1312/5f4af/button-variants.png" srcset="/static/410d5bded7201ebf462003ab47fd1312/e9ff0/button-variants.png 180w, /static/410d5bded7201ebf462003ab47fd1312/f21e7/button-variants.png 360w, /static/410d5bded7201ebf462003ab47fd1312/5f4af/button-variants.png 665w" sizes="(max-width: 665px) 100vw, 665px" style="width:100%;height:100%;margin:0;vertical-align:middle;position:absolute;top:0;left:0;" loading="lazy" decoding="async" /> </a> </span></p> <p>Or a Text Field can have an “outlined” or “filled” variant.</p> <p><span class="gatsby-resp-image-wrapper" style="position: relative; display: block; margin-left: auto; margin-right: auto; max-width: 720px; " > <a class="gatsby-resp-image-link" href="/static/bd74b51592dbc98efd1ae7890d16a329/7a4b2/textfield-variants.png" style="display: block" target="_blank" rel="noopener" > <span class="gatsby-resp-image-background-image" style="padding-bottom: 21.111111111111114%; position: relative; bottom: 0; left: 0; background-image: url('data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABQAAAAECAYAAACOXx+WAAAACXBIWXMAACToAAAk6AGCYwUcAAAAdElEQVR42oWO2QrDIBRE8/9f6YMPguCCS9ynTENKWoQOHNDrcbjHWgvkzn3f8c9hDh7O80QIATlnzDm3Mt+klNBaw3sP59wX1lrUWq9CypRijNiFTkoJQggopT4FT4wxKKVchU+44S+c997RWnvDjzvGGHgBwDM5LW4ADckAAAAASUVORK5CYII='); background-size: cover; display: block;" ></span> <img class="gatsby-resp-image-image" alt="Button Variants" title="" src="/static/bd74b51592dbc98efd1ae7890d16a329/37523/textfield-variants.png" srcset="/static/bd74b51592dbc98efd1ae7890d16a329/e9ff0/textfield-variants.png 180w, /static/bd74b51592dbc98efd1ae7890d16a329/f21e7/textfield-variants.png 360w, /static/bd74b51592dbc98efd1ae7890d16a329/37523/textfield-variants.png 720w, /static/bd74b51592dbc98efd1ae7890d16a329/302a4/textfield-variants.png 1080w, /static/bd74b51592dbc98efd1ae7890d16a329/7a4b2/textfield-variants.png 1240w" sizes="(max-width: 720px) 100vw, 720px" style="width:100%;height:100%;margin:0;vertical-align:middle;position:absolute;top:0;left:0;" loading="lazy" decoding="async" /> </a> </span></p> <p>In this article, we’ll learn how to create a custom variant and override an existing one. We’ll use the Button component as an example, but a <code>variant</code> prop is also available in the Text Field and other components.</p> <p>If you’d like to skip all the details, below is the complete code example:</p> <div data-codesandbox="mui-custom-variant-ynugep"> <button>Run Code</button> </div> <p><em>If this is your first time working with MUI, please follow the <a href="https://mui.com/material-ui/getting-started/installation/">installation instructions</a> from the official documentation to get started.</em></p> <h2 id="override-a-variant" style="position:relative;"><a href="#override-a-variant" aria-label="override a variant permalink" class="anchor before"><svg aria-hidden="true" focusable="false" height="16" version="1.1" viewBox="0 0 16 16" width="16"><path fill-rule="evenodd" d="M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z"></path></svg></a>Override a variant</h2> <p><code>creatTheme</code> provides specific component customization using the <code>styleOverrides</code> key. Then we can add the component and variant we’re trying to customize, in our case, <code>MuiButton</code> and <code>container</code>.</p> <pre class="grvsc-container grvsc-has-line-highlighting default-dark" data-language="jsx" data-index="0"><code class="grvsc-code"><span class="grvsc-line"><span class="grvsc-source"><span class="mtk15">import</span><span class="mtk1"> { </span><span class="mtk12">ThemeProvider</span><span class="mtk1">, </span><span class="mtk12">createTheme</span><span class="mtk1"> } </span><span class="mtk15">from</span><span class="mtk1"> </span><span class="mtk8">&quot;@mui/material/styles&quot;</span><span class="mtk1">;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk15">import</span><span class="mtk1"> { </span><span class="mtk12">Button</span><span class="mtk1"> } </span><span class="mtk15">from</span><span class="mtk1"> </span><span class="mtk8">&quot;@mui/material&quot;</span><span class="mtk1">;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk4">const</span><span class="mtk1"> </span><span class="mtk12">theme</span><span class="mtk1"> = </span><span class="mtk11">createTheme</span><span class="mtk1">({</span></span></span> <span class="grvsc-line grvsc-line-highlighted"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">components:</span><span class="mtk1"> {</span></span></span> <span class="grvsc-line grvsc-line-highlighted"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">MuiButton:</span><span class="mtk1"> {</span></span></span> <span class="grvsc-line grvsc-line-highlighted"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">styleOverrides:</span><span class="mtk1"> {</span></span></span> <span class="grvsc-line grvsc-line-highlighted"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">contained:</span><span class="mtk1"> {</span></span></span> <span class="grvsc-line grvsc-line-highlighted"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">padding:</span><span class="mtk1"> </span><span class="mtk8">&quot;10px 20px&quot;</span><span class="mtk1">,</span></span></span> <span class="grvsc-line grvsc-line-highlighted"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">fontSize:</span><span class="mtk1"> </span><span class="mtk8">&quot;16px&quot;</span><span class="mtk1">,</span></span></span> <span class="grvsc-line grvsc-line-highlighted"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">fontWeight:</span><span class="mtk1"> </span><span class="mtk8">&quot;500&quot;</span></span></span> <span class="grvsc-line grvsc-line-highlighted"><span class="grvsc-source"><span class="mtk1"> }</span></span></span> <span class="grvsc-line grvsc-line-highlighted"><span class="grvsc-source"><span class="mtk1"> }</span></span></span> <span class="grvsc-line grvsc-line-highlighted"><span class="grvsc-source"><span class="mtk1"> }</span></span></span> <span class="grvsc-line grvsc-line-highlighted"><span class="grvsc-source"><span class="mtk1"> }</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1">});</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk15">export</span><span class="mtk1"> </span><span class="mtk15">default</span><span class="mtk1"> </span><span class="mtk4">function</span><span class="mtk1"> </span><span class="mtk11">App</span><span class="mtk1">() {</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk15">return</span><span class="mtk1"> (</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk17">&lt;</span><span class="mtk10">ThemeProvider</span><span class="mtk1"> </span><span class="mtk12">theme</span><span class="mtk1">=</span><span class="mtk4">{</span><span class="mtk12">theme</span><span class="mtk4">}</span><span class="mtk17">&gt;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk17">&lt;</span><span class="mtk10">Button</span><span class="mtk1"> </span><span class="mtk12">variant</span><span class="mtk1">=</span><span class="mtk8">&quot;contained&quot;</span><span class="mtk17">&gt;</span><span class="mtk1">contained</span><span class="mtk17">&lt;/</span><span class="mtk10">Button</span><span class="mtk17">&gt;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk17">&lt;/</span><span class="mtk10">ThemeProvider</span><span class="mtk17">&gt;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> );</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1">}</span></span></span></code></pre> <p>We can even be more selective and customize the variant with a specific color (e.g., primary or secondary).</p> <pre class="grvsc-container grvsc-has-line-highlighting default-dark" data-language="jsx" data-index="1"><code class="grvsc-code"><span class="grvsc-line"><span class="grvsc-source"><span class="mtk15">import</span><span class="mtk1"> { </span><span class="mtk12">ThemeProvider</span><span class="mtk1">, </span><span class="mtk12">createTheme</span><span class="mtk1"> } </span><span class="mtk15">from</span><span class="mtk1"> </span><span class="mtk8">&quot;@mui/material/styles&quot;</span><span class="mtk1">;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk15">import</span><span class="mtk1"> { </span><span class="mtk12">Button</span><span class="mtk1"> } </span><span class="mtk15">from</span><span class="mtk1"> </span><span class="mtk8">&quot;@mui/material&quot;</span><span class="mtk1">;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk15">import</span><span class="mtk1"> { </span><span class="mtk12">purple</span><span class="mtk1"> } </span><span class="mtk15">from</span><span class="mtk1"> </span><span class="mtk8">&quot;@mui/material/colors&quot;</span><span class="mtk1">;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk4">const</span><span class="mtk1"> </span><span class="mtk12">theme</span><span class="mtk1"> = </span><span class="mtk11">createTheme</span><span class="mtk1">({</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">components:</span><span class="mtk1"> {</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">MuiButton:</span><span class="mtk1"> {</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">styleOverrides:</span><span class="mtk1"> {</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">contained:</span><span class="mtk1"> {</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">padding:</span><span class="mtk1"> </span><span class="mtk8">&quot;10px 20px&quot;</span><span class="mtk1">,</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">fontSize:</span><span class="mtk1"> </span><span class="mtk8">&quot;16px&quot;</span><span class="mtk1">,</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">fontWeight:</span><span class="mtk1"> </span><span class="mtk8">&quot;500&quot;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> },</span></span></span> <span class="grvsc-line grvsc-line-highlighted"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">containedSecondary:</span><span class="mtk1"> {</span></span></span> <span class="grvsc-line grvsc-line-highlighted"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">background:</span><span class="mtk1"> </span><span class="mtk12">purple</span><span class="mtk1">[</span><span class="mtk7">300</span><span class="mtk1">]</span></span></span> <span class="grvsc-line grvsc-line-highlighted"><span class="grvsc-source"><span class="mtk1"> }</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> }</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> }</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> }</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1">});</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk15">export</span><span class="mtk1"> </span><span class="mtk15">default</span><span class="mtk1"> </span><span class="mtk4">function</span><span class="mtk1"> </span><span class="mtk11">App</span><span class="mtk1">() {</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk15">return</span><span class="mtk1"> (</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk17">&lt;</span><span class="mtk10">ThemeProvider</span><span class="mtk1"> </span><span class="mtk12">theme</span><span class="mtk1">=</span><span class="mtk4">{</span><span class="mtk12">theme</span><span class="mtk4">}</span><span class="mtk17">&gt;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk17">&lt;</span><span class="mtk10">Button</span><span class="mtk1"> </span><span class="mtk12">variant</span><span class="mtk1">=</span><span class="mtk8">&quot;contained&quot;</span><span class="mtk17">&gt;</span><span class="mtk1">contained</span><span class="mtk17">&lt;/</span><span class="mtk10">Button</span><span class="mtk17">&gt;</span></span></span> <span class="grvsc-line grvsc-line-highlighted"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk17">&lt;</span><span class="mtk10">Button</span><span class="mtk1"> </span><span class="mtk12">variant</span><span class="mtk1">=</span><span class="mtk8">&quot;contained&quot;</span><span class="mtk1"> </span><span class="mtk12">color</span><span class="mtk1">=</span><span class="mtk8">&quot;secondary&quot;</span><span class="mtk17">&gt;</span></span></span> <span class="grvsc-line grvsc-line-highlighted"><span class="grvsc-source"><span class="mtk1"> contained secondary</span></span></span> <span class="grvsc-line grvsc-line-highlighted"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk17">&lt;/</span><span class="mtk10">Button</span><span class="mtk17">&gt;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk17">&lt;/</span><span class="mtk10">ThemeProvider</span><span class="mtk17">&gt;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> );</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1">}</span></span></span> <span class="grvsc-line"><span class="grvsc-source"></span></span></code></pre> <p>Here are the new updated styles:</p> <p><span class="gatsby-resp-image-wrapper" style="position: relative; display: block; margin-left: auto; margin-right: auto; max-width: 720px; " > <a class="gatsby-resp-image-link" href="/static/cf6fe2c1a97638679574e8c2dc893be6/b7936/styled-variants.png" style="display: block" target="_blank" rel="noopener" > <span class="gatsby-resp-image-background-image" style="padding-bottom: 21.666666666666668%; position: relative; bottom: 0; left: 0; background-image: url('data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABQAAAAECAYAAACOXx+WAAAACXBIWXMAACToAAAk6AGCYwUcAAAA8UlEQVR42n2My0oCYRiGvY3oHoRALyCkW+gKWkaLsBMuytRFUF1A+1bti4jKA3aimYGyGSMqqBxmF5rz6/zO9PQ5BIaLPni+E7xPAin3M+Ch5eO4KsYWHr0eSoV0PUX7w6czTuvP/u4TfOmhisSwze49M7lyx1TRIVlwSJWaTOQaHJ261BduOFsyqCybVNcszrO3lOUuZ+W3alLLWRzPXdI8eB0J5/dfSBXvyezYTG/bzOzapLcaVC48rtclmBfZhkGtYFHNG7+IbNOkXrI4Wbzi6fBtJOzrkI7StIV4+ppub0AUfaP7AwK5/0UyYRjFwh9ZTBOOA81NSwAAAABJRU5ErkJggg=='); background-size: cover; display: block;" ></span> <img class="gatsby-resp-image-image" alt="Button Variants" title="" src="/static/cf6fe2c1a97638679574e8c2dc893be6/37523/styled-variants.png" srcset="/static/cf6fe2c1a97638679574e8c2dc893be6/e9ff0/styled-variants.png 180w, /static/cf6fe2c1a97638679574e8c2dc893be6/f21e7/styled-variants.png 360w, /static/cf6fe2c1a97638679574e8c2dc893be6/37523/styled-variants.png 720w, /static/cf6fe2c1a97638679574e8c2dc893be6/302a4/styled-variants.png 1080w, /static/cf6fe2c1a97638679574e8c2dc893be6/b7936/styled-variants.png 1155w" sizes="(max-width: 720px) 100vw, 720px" style="width:100%;height:100%;margin:0;vertical-align:middle;position:absolute;top:0;left:0;" loading="lazy" decoding="async" /> </a> </span></p> <h2 id="create-a-new-variant" style="position:relative;"><a href="#create-a-new-variant" aria-label="create a new variant permalink" class="anchor before"><svg aria-hidden="true" focusable="false" height="16" version="1.1" viewBox="0 0 16 16" width="16"><path fill-rule="evenodd" d="M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z"></path></svg></a>Create a new variant</h2> <p>Similar to the first section, we’ll need to customize <code>MuiButton</code> but this time using the <code>variants</code> key to add and style a custom one.</p> <p>Let’s create a new variant that adds a gradient to the background color.</p> <pre class="grvsc-container grvsc-has-line-highlighting default-dark" data-language="jsx" data-index="2"><code class="grvsc-code"><span class="grvsc-line"><span class="grvsc-source"><span class="mtk15">import</span><span class="mtk1"> { </span><span class="mtk12">ThemeProvider</span><span class="mtk1">, </span><span class="mtk12">createTheme</span><span class="mtk1"> } </span><span class="mtk15">from</span><span class="mtk1"> </span><span class="mtk8">&quot;@mui/material/styles&quot;</span><span class="mtk1">;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk15">import</span><span class="mtk1"> { </span><span class="mtk12">Button</span><span class="mtk1"> } </span><span class="mtk15">from</span><span class="mtk1"> </span><span class="mtk8">&quot;@mui/material&quot;</span><span class="mtk1">;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk15">import</span><span class="mtk1"> { </span><span class="mtk12">blue</span><span class="mtk1"> } </span><span class="mtk15">from</span><span class="mtk1"> </span><span class="mtk8">&quot;@mui/material/colors&quot;</span><span class="mtk1">;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk4">const</span><span class="mtk1"> </span><span class="mtk12">theme</span><span class="mtk1"> = </span><span class="mtk11">createTheme</span><span class="mtk1">({</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">components:</span><span class="mtk1"> {</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">MuiButton:</span><span class="mtk1"> {</span></span></span> <span class="grvsc-line grvsc-line-highlighted"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">variants:</span><span class="mtk1"> [</span></span></span> <span class="grvsc-line grvsc-line-highlighted"><span class="grvsc-source"><span class="mtk1"> {</span></span></span> <span class="grvsc-line grvsc-line-highlighted"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">props:</span><span class="mtk1"> { </span><span class="mtk12">variant:</span><span class="mtk1"> </span><span class="mtk8">&quot;gradient&quot;</span><span class="mtk1"> },</span></span></span> <span class="grvsc-line grvsc-line-highlighted"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">style:</span><span class="mtk1"> {</span></span></span> <span class="grvsc-line grvsc-line-highlighted"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">background:</span><span class="mtk1"> </span><span class="mtk8">`linear-gradient(45deg, </span><span class="mtk4">${</span><span class="mtk12">blue</span><span class="mtk1">[</span><span class="mtk7">700</span><span class="mtk1">]</span><span class="mtk4">}</span><span class="mtk8"> 35%, </span><span class="mtk4">${</span><span class="mtk12">blue</span><span class="mtk1">[</span><span class="mtk7">300</span><span class="mtk1">]</span><span class="mtk4">}</span><span class="mtk8"> 90%)`</span><span class="mtk1">,</span></span></span> <span class="grvsc-line grvsc-line-highlighted"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">color:</span><span class="mtk1"> </span><span class="mtk8">&quot;#fff&quot;</span></span></span> <span class="grvsc-line grvsc-line-highlighted"><span class="grvsc-source"><span class="mtk1"> }</span></span></span> <span class="grvsc-line grvsc-line-highlighted"><span class="grvsc-source"><span class="mtk1"> }</span></span></span> <span class="grvsc-line grvsc-line-highlighted"><span class="grvsc-source"><span class="mtk1"> ]</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> }</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> }</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1">});</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk15">export</span><span class="mtk1"> </span><span class="mtk15">default</span><span class="mtk1"> </span><span class="mtk4">function</span><span class="mtk1"> </span><span class="mtk11">App</span><span class="mtk1">() {</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk15">return</span><span class="mtk1"> (</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk17">&lt;</span><span class="mtk10">ThemeProvider</span><span class="mtk1"> </span><span class="mtk12">theme</span><span class="mtk1">=</span><span class="mtk4">{</span><span class="mtk12">theme</span><span class="mtk4">}</span><span class="mtk17">&gt;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk17">&lt;</span><span class="mtk10">Button</span><span class="mtk1"> </span><span class="mtk12">variant</span><span class="mtk1">=</span><span class="mtk8">&quot;gradient&quot;</span><span class="mtk17">&gt;</span><span class="mtk1">primary gradient</span><span class="mtk17">&lt;/</span><span class="mtk10">Button</span><span class="mtk17">&gt;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk17">&lt;/</span><span class="mtk10">ThemeProvider</span><span class="mtk17">&gt;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> );</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1">}</span></span></span></code></pre> <p>As seen above, when adding a custom variant, we can name and style the variant however we see fit. Additionally, <code>props</code> has a <code>color</code> option that we can use to style the variant with a specific color palette. Let’s try it for both <code>primary</code> and <code>secondary</code> colors.</p> <pre class="grvsc-container grvsc-has-line-highlighting default-dark" data-language="jsx" data-index="3"><code class="grvsc-code"><span class="grvsc-line"><span class="grvsc-source"><span class="mtk15">import</span><span class="mtk1"> { </span><span class="mtk12">ThemeProvider</span><span class="mtk1">, </span><span class="mtk12">createTheme</span><span class="mtk1"> } </span><span class="mtk15">from</span><span class="mtk1"> </span><span class="mtk8">&quot;@mui/material/styles&quot;</span><span class="mtk1">;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk15">import</span><span class="mtk1"> { </span><span class="mtk12">Button</span><span class="mtk1"> } </span><span class="mtk15">from</span><span class="mtk1"> </span><span class="mtk8">&quot;@mui/material&quot;</span><span class="mtk1">;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk15">import</span><span class="mtk1"> { </span><span class="mtk12">blue</span><span class="mtk1">, </span><span class="mtk12">purple</span><span class="mtk1"> } </span><span class="mtk15">from</span><span class="mtk1"> </span><span class="mtk8">&quot;@mui/material/colors&quot;</span><span class="mtk1">;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk4">const</span><span class="mtk1"> </span><span class="mtk12">theme</span><span class="mtk1"> = </span><span class="mtk11">createTheme</span><span class="mtk1">({</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">components:</span><span class="mtk1"> {</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">MuiButton:</span><span class="mtk1"> {</span></span></span> <span class="grvsc-line grvsc-line-highlighted"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">variants:</span><span class="mtk1"> [</span></span></span> <span class="grvsc-line grvsc-line-highlighted"><span class="grvsc-source"><span class="mtk1"> {</span></span></span> <span class="grvsc-line grvsc-line-highlighted"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">props:</span><span class="mtk1"> { </span><span class="mtk12">variant:</span><span class="mtk1"> </span><span class="mtk8">&quot;gradient&quot;</span><span class="mtk1">, </span><span class="mtk12">color:</span><span class="mtk1"> </span><span class="mtk8">&quot;primary&quot;</span><span class="mtk1"> },</span></span></span> <span class="grvsc-line grvsc-line-highlighted"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">style:</span><span class="mtk1"> {</span></span></span> <span class="grvsc-line grvsc-line-highlighted"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">background:</span><span class="mtk1"> </span><span class="mtk8">`linear-gradient(45deg, </span><span class="mtk4">${</span><span class="mtk12">blue</span><span class="mtk1">[</span><span class="mtk7">700</span><span class="mtk1">]</span><span class="mtk4">}</span><span class="mtk8"> 35%, </span><span class="mtk4">${</span><span class="mtk12">blue</span><span class="mtk1">[</span><span class="mtk7">300</span><span class="mtk1">]</span><span class="mtk4">}</span><span class="mtk8"> 90%)`</span><span class="mtk1">,</span></span></span> <span class="grvsc-line grvsc-line-highlighted"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">color:</span><span class="mtk1"> </span><span class="mtk8">&quot;#fff&quot;</span></span></span> <span class="grvsc-line grvsc-line-highlighted"><span class="grvsc-source"><span class="mtk1"> }</span></span></span> <span class="grvsc-line grvsc-line-highlighted"><span class="grvsc-source"><span class="mtk1"> },</span></span></span> <span class="grvsc-line grvsc-line-highlighted"><span class="grvsc-source"><span class="mtk1"> {</span></span></span> <span class="grvsc-line grvsc-line-highlighted"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">props:</span><span class="mtk1"> { </span><span class="mtk12">variant:</span><span class="mtk1"> </span><span class="mtk8">&quot;gradient&quot;</span><span class="mtk1">, </span><span class="mtk12">color:</span><span class="mtk1"> </span><span class="mtk8">&quot;secondary&quot;</span><span class="mtk1"> },</span></span></span> <span class="grvsc-line grvsc-line-highlighted"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">style:</span><span class="mtk1"> {</span></span></span> <span class="grvsc-line grvsc-line-highlighted"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">background:</span><span class="mtk1"> </span><span class="mtk8">`linear-gradient(45deg, </span><span class="mtk4">${</span><span class="mtk12">purple</span><span class="mtk1">[</span><span class="mtk7">700</span><span class="mtk1">]</span><span class="mtk4">}</span><span class="mtk8"> 35%, </span><span class="mtk4">${</span><span class="mtk12">purple</span><span class="mtk1">[</span><span class="mtk7">300</span><span class="mtk1">]</span><span class="mtk4">}</span><span class="mtk8"> 90%)`</span><span class="mtk1">,</span></span></span> <span class="grvsc-line grvsc-line-highlighted"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">color:</span><span class="mtk1"> </span><span class="mtk8">&quot;#fff&quot;</span></span></span> <span class="grvsc-line grvsc-line-highlighted"><span class="grvsc-source"><span class="mtk1"> }</span></span></span> <span class="grvsc-line grvsc-line-highlighted"><span class="grvsc-source"><span class="mtk1"> }</span></span></span> <span class="grvsc-line grvsc-line-highlighted"><span class="grvsc-source"><span class="mtk1"> ]</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> }</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> }</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1">});</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk15">export</span><span class="mtk1"> </span><span class="mtk15">default</span><span class="mtk1"> </span><span class="mtk4">function</span><span class="mtk1"> </span><span class="mtk11">App</span><span class="mtk1">() {</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk15">return</span><span class="mtk1"> (</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk17">&lt;</span><span class="mtk10">ThemeProvider</span><span class="mtk1"> </span><span class="mtk12">theme</span><span class="mtk1">=</span><span class="mtk4">{</span><span class="mtk12">theme</span><span class="mtk4">}</span><span class="mtk17">&gt;</span></span></span> <span class="grvsc-line grvsc-line-highlighted"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk17">&lt;</span><span class="mtk10">Button</span><span class="mtk1"> </span><span class="mtk12">variant</span><span class="mtk1">=</span><span class="mtk8">&quot;gradient&quot;</span><span class="mtk17">&gt;</span><span class="mtk1">primary gradient</span><span class="mtk17">&lt;/</span><span class="mtk10">Button</span><span class="mtk17">&gt;</span></span></span> <span class="grvsc-line grvsc-line-highlighted"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk17">&lt;</span><span class="mtk10">Button</span><span class="mtk1"> </span><span class="mtk12">variant</span><span class="mtk1">=</span><span class="mtk8">&quot;gradient&quot;</span><span class="mtk1"> </span><span class="mtk12">color</span><span class="mtk1">=</span><span class="mtk8">&quot;secondary&quot;</span><span class="mtk17">&gt;</span></span></span> <span class="grvsc-line grvsc-line-highlighted"><span class="grvsc-source"><span class="mtk1"> secondary gradient</span></span></span> <span class="grvsc-line grvsc-line-highlighted"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk17">&lt;/</span><span class="mtk10">Button</span><span class="mtk17">&gt;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk17">&lt;/</span><span class="mtk10">ThemeProvider</span><span class="mtk17">&gt;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> );</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1">}</span></span></span></code></pre> <p><span class="gatsby-resp-image-wrapper" style="position: relative; display: block; margin-left: auto; margin-right: auto; max-width: 720px; " > <a class="gatsby-resp-image-link" href="/static/ed3719019b8056abe8b6a51c5281f4a4/d7ba6/new-variant.png" style="display: block" target="_blank" rel="noopener" > <span class="gatsby-resp-image-background-image" style="padding-bottom: 19.444444444444443%; position: relative; bottom: 0; left: 0; background-image: url('data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABQAAAAECAYAAACOXx+WAAAACXBIWXMAACToAAAk6AGCYwUcAAAA7klEQVR42q3MvUrDUACG4d6UeAEuXQQHwUkQEfwZokUcXRRphw5CHRzEFmzBagWVGFAiERIQOnQoDoJBigGFOpTWtEnOSc9rTG/BDx6+7c2EUtEP4pQfjRlGKnnFSCgCCbECGcYEfUH4kxgIIl8ghjIlR3FqnHT+llmqdJjKv5ItvZE9emfuxGO53mVT77Fx56O7ksaqRWG6weHMDcezBuX5B6oLJtfrDvfbTcxck5eKOwkeGF8snnbQzj3Wah9ol5/sGt/kH3vsWQNsT/JUbHG2YlHXbC62bK5yDrc7z5j7LexiG6fQxtW9SZB/3i9S0xZTThQyCgAAAABJRU5ErkJggg=='); background-size: cover; display: block;" ></span> <img class="gatsby-resp-image-image" alt="Button Variants" title="" src="/static/ed3719019b8056abe8b6a51c5281f4a4/37523/new-variant.png" srcset="/static/ed3719019b8056abe8b6a51c5281f4a4/e9ff0/new-variant.png 180w, /static/ed3719019b8056abe8b6a51c5281f4a4/f21e7/new-variant.png 360w, /static/ed3719019b8056abe8b6a51c5281f4a4/37523/new-variant.png 720w, /static/ed3719019b8056abe8b6a51c5281f4a4/302a4/new-variant.png 1080w, /static/ed3719019b8056abe8b6a51c5281f4a4/d7ba6/new-variant.png 1107w" sizes="(max-width: 720px) 100vw, 720px" style="width:100%;height:100%;margin:0;vertical-align:middle;position:absolute;top:0;left:0;" loading="lazy" decoding="async" /> </a> </span></p> <h2 id="summary" style="position:relative;"><a href="#summary" aria-label="summary permalink" class="anchor before"><svg aria-hidden="true" focusable="false" height="16" version="1.1" viewBox="0 0 16 16" width="16"><path fill-rule="evenodd" d="M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z"></path></svg></a>Summary</h2> <p><code>variant</code> is a very useful option that MUI provides out of the box, and with the latest MUI 5 version, the team has done a fantastic job of making the theme more extensible and easier to customize.</p> <p>Bye for now 👋</p> <style class="grvsc-styles"> .grvsc-container { overflow: auto; position: relative; -webkit-overflow-scrolling: touch; padding-top: 1rem; padding-top: var(--grvsc-padding-top, var(--grvsc-padding-v, 1rem)); padding-bottom: 1rem; padding-bottom: var(--grvsc-padding-bottom, var(--grvsc-padding-v, 1rem)); border-radius: 8px; border-radius: var(--grvsc-border-radius, 8px); font-feature-settings: normal; line-height: 1.4; } .grvsc-code { display: table; } .grvsc-line { display: table-row; box-sizing: border-box; width: 100%; position: relative; } .grvsc-line > * { position: relative; } .grvsc-gutter-pad { display: table-cell; padding-left: 0.75rem; padding-left: calc(var(--grvsc-padding-left, var(--grvsc-padding-h, 1.5rem)) / 2); } .grvsc-gutter { display: table-cell; -webkit-user-select: none; -moz-user-select: none; user-select: none; } .grvsc-gutter::before { content: attr(data-content); } .grvsc-source { display: table-cell; padding-left: 1.5rem; padding-left: var(--grvsc-padding-left, var(--grvsc-padding-h, 1.5rem)); padding-right: 1.5rem; padding-right: var(--grvsc-padding-right, var(--grvsc-padding-h, 1.5rem)); } .grvsc-source:empty::after { content: ' '; -webkit-user-select: none; -moz-user-select: none; user-select: none; } .grvsc-gutter + .grvsc-source { padding-left: 0.75rem; padding-left: calc(var(--grvsc-padding-left, var(--grvsc-padding-h, 1.5rem)) / 2); } /* Line transformer styles */ .grvsc-has-line-highlighting > .grvsc-code > .grvsc-line::before { content: ' '; position: absolute; width: 100%; } .grvsc-line-diff-add::before { background-color: var(--grvsc-line-diff-add-background-color, rgba(0, 255, 60, 0.2)); } .grvsc-line-diff-del::before { background-color: var(--grvsc-line-diff-del-background-color, rgba(255, 0, 20, 0.2)); } .grvsc-line-number { padding: 0 2px; text-align: right; opacity: 0.7; } .default-dark { background-color: #1E1E1E; color: #D4D4D4; } .default-dark .mtk15 { color: #C586C0; } .default-dark .mtk1 { color: #D4D4D4; } .default-dark .mtk12 { color: #9CDCFE; } .default-dark .mtk8 { color: #CE9178; } .default-dark .mtk4 { color: #569CD6; } .default-dark .mtk11 { color: #DCDCAA; } .default-dark .mtk17 { color: #808080; } .default-dark .mtk10 { color: #4EC9B0; } .default-dark .mtk7 { color: #B5CEA8; } .default-dark .grvsc-line-highlighted::before { background-color: var(--grvsc-line-highlighted-background-color, rgba(255, 255, 255, 0.1)); box-shadow: inset var(--grvsc-line-highlighted-border-width, 4px) 0 0 0 var(--grvsc-line-highlighted-border-color, rgba(255, 255, 255, 0.5)); } </style><![CDATA[Customizing Theme, Palette, and Colors with Material UI (MUI)]]>https://muhimasri.comhow-to-customize-theme-and-colors-in-material-uihttps://muhimasri.comhow-to-customize-theme-and-colors-in-material-ui<p>Palettes and themes are essential parts of the overall UI look and feel. They convey meaning and consistency throughout the application.</p> <p>This article will focus on creating and customizing colors and palettes using MUI theme. There are three important parts that we need to understand:</p> <ul> <li>Customizing MUI theme</li> <li>Adding a custom palette</li> <li>Using custom colors</li> </ul> <p>Before we start, below is the complete working code example:</p> <div data-codesandbox="mui-custom-colors-x5cget"> <button>Run Code</button> </div> <p><em>If this is your first time working with MUI, please follow the <a href="https://mui.com/material-ui/getting-started/installation/">installation instructions</a> from the official documentation to get started.</em></p> <h2 id="custom-mui-theme" style="position:relative;"><a href="#custom-mui-theme" aria-label="custom mui theme permalink" class="anchor before"><svg aria-hidden="true" focusable="false" height="16" version="1.1" viewBox="0 0 16 16" width="16"><path fill-rule="evenodd" d="M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z"></path></svg></a>Custom MUI theme</h2> <p>Creating a custom theme is typically done at the root or main app section to be accessible to all components. We can use <code>ThemeProvider</code> as a root app component and pass in the customized theme.</p> <pre class="grvsc-container default-dark" data-language="jsx" data-index="0"><code class="grvsc-code"><span class="grvsc-line"><span class="grvsc-source"><span class="mtk15">import</span><span class="mtk1"> { </span><span class="mtk12">ThemeProvider</span><span class="mtk1">, </span><span class="mtk12">createTheme</span><span class="mtk1"> } </span><span class="mtk15">from</span><span class="mtk1"> </span><span class="mtk8">&quot;@mui/material/styles&quot;</span><span class="mtk1">;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk4">const</span><span class="mtk1"> </span><span class="mtk12">theme</span><span class="mtk1"> = </span><span class="mtk11">createTheme</span><span class="mtk1">({</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk3">// Override or create new styles, colors, palettes...</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1">});</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk15">export</span><span class="mtk1"> </span><span class="mtk15">default</span><span class="mtk1"> </span><span class="mtk4">function</span><span class="mtk1"> </span><span class="mtk11">App</span><span class="mtk1">() {</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk15">return</span><span class="mtk1"> (</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk17">&lt;</span><span class="mtk10">ThemeProvider</span><span class="mtk1"> </span><span class="mtk12">theme</span><span class="mtk1">=</span><span class="mtk4">{</span><span class="mtk12">theme</span><span class="mtk4">}</span><span class="mtk17">&gt;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> // MUI components</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk17">&lt;/</span><span class="mtk10">ThemeProvider</span><span class="mtk17">&gt;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> );</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1">}</span></span></span></code></pre> <p>Let’s look deeper at why and how to use custom themes.</p> <h3 id="why-is-it-important" style="position:relative;"><a href="#why-is-it-important" aria-label="why is it important permalink" class="anchor before"><svg aria-hidden="true" focusable="false" height="16" version="1.1" viewBox="0 0 16 16" width="16"><path fill-rule="evenodd" d="M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z"></path></svg></a>Why is it important?</h3> <p>Let’s assume we have a header with some input elements on the screen and want to change the button’s primary color.</p> <p><span class="gatsby-resp-image-wrapper" style="position: relative; display: block; margin-left: auto; margin-right: auto; max-width: 720px; " > <a class="gatsby-resp-image-link" href="/static/736286f5976b4af2d171b639ce36efe9/55681/custom-theme-1.png" style="display: block" target="_blank" rel="noopener" > <span class="gatsby-resp-image-background-image" style="padding-bottom: 39.44444444444444%; position: relative; bottom: 0; left: 0; background-image: url('data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABQAAAAICAYAAAD5nd/tAAAACXBIWXMAACToAAAk6AGCYwUcAAAAm0lEQVR42q2OTQ7BQACF50TEghNISIifrZ2rICxFsRFxGWfQTiuWEkVUpzEl0n40TqCZL3l5q/flibrlUZ16VCYOhYFNcfh/SiOb8lhSm3mI3sqls5A0LYfWXOZK+7vvLiX9zR6x3vo0LJesM9KUnPyG4nCO2R0fhPqNCcRdJ+hXJktITQhP4RP/ckUpZeZhHGuC4EYURWaEGOYDUrhDbz45KNgAAAAASUVORK5CYII='); background-size: cover; display: block;" ></span> <img class="gatsby-resp-image-image" alt="Default Theme" title="" src="/static/736286f5976b4af2d171b639ce36efe9/37523/custom-theme-1.png" srcset="/static/736286f5976b4af2d171b639ce36efe9/e9ff0/custom-theme-1.png 180w, /static/736286f5976b4af2d171b639ce36efe9/f21e7/custom-theme-1.png 360w, /static/736286f5976b4af2d171b639ce36efe9/37523/custom-theme-1.png 720w, /static/736286f5976b4af2d171b639ce36efe9/302a4/custom-theme-1.png 1080w, /static/736286f5976b4af2d171b639ce36efe9/07a9c/custom-theme-1.png 1440w, /static/736286f5976b4af2d171b639ce36efe9/55681/custom-theme-1.png 2062w" sizes="(max-width: 720px) 100vw, 720px" style="width:100%;height:100%;margin:0;vertical-align:middle;position:absolute;top:0;left:0;" loading="lazy" decoding="async" /> </a> </span></p> <pre class="grvsc-container default-dark" data-language="jsx" data-index="1"><code class="grvsc-code"><span class="grvsc-line"><span class="grvsc-source"><span class="mtk15">import</span><span class="mtk1"> {</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">Button</span><span class="mtk1">,</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">Box</span><span class="mtk1">,</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">AppBar</span><span class="mtk1">,</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">Toolbar</span><span class="mtk1">,</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">Typography</span><span class="mtk1">,</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">Checkbox</span><span class="mtk1">,</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">FormControl</span><span class="mtk1">,</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">FormControlLabel</span><span class="mtk1">,</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">RadioGroup</span><span class="mtk1">,</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">Radio</span><span class="mtk1">,</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">Stack</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1">} </span><span class="mtk15">from</span><span class="mtk1"> </span><span class="mtk8">&quot;@mui/material&quot;</span><span class="mtk1">;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk15">export</span><span class="mtk1"> </span><span class="mtk15">default</span><span class="mtk1"> </span><span class="mtk4">function</span><span class="mtk1"> </span><span class="mtk11">App</span><span class="mtk1">() {</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk15">return</span><span class="mtk1"> (</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk17">&lt;</span><span class="mtk10">Box</span><span class="mtk17">&gt;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk17">&lt;</span><span class="mtk10">Box</span><span class="mtk1"> </span><span class="mtk12">sx</span><span class="mtk1">=</span><span class="mtk4">{</span><span class="mtk1">{ </span><span class="mtk12">flexGrow:</span><span class="mtk1"> </span><span class="mtk7">1</span><span class="mtk1"> }</span><span class="mtk4">}</span><span class="mtk17">&gt;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk17">&lt;</span><span class="mtk10">AppBar</span><span class="mtk1"> </span><span class="mtk12">position</span><span class="mtk1">=</span><span class="mtk8">&quot;static&quot;</span><span class="mtk17">&gt;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk17">&lt;</span><span class="mtk10">Toolbar</span><span class="mtk17">&gt;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk17">&lt;</span><span class="mtk10">Typography</span><span class="mtk1"> </span><span class="mtk12">variant</span><span class="mtk1">=</span><span class="mtk8">&quot;h6&quot;</span><span class="mtk1"> </span><span class="mtk12">component</span><span class="mtk1">=</span><span class="mtk8">&quot;div&quot;</span><span class="mtk1"> </span><span class="mtk12">sx</span><span class="mtk1">=</span><span class="mtk4">{</span><span class="mtk1">{ </span><span class="mtk12">flexGrow:</span><span class="mtk1"> </span><span class="mtk7">1</span><span class="mtk1"> }</span><span class="mtk4">}</span><span class="mtk17">&gt;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> Header</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk17">&lt;/</span><span class="mtk10">Typography</span><span class="mtk17">&gt;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk17">&lt;</span><span class="mtk10">Button</span><span class="mtk1"> </span><span class="mtk12">color</span><span class="mtk1">=</span><span class="mtk8">&quot;inherit&quot;</span><span class="mtk17">&gt;</span><span class="mtk1">Login</span><span class="mtk17">&lt;/</span><span class="mtk10">Button</span><span class="mtk17">&gt;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk17">&lt;/</span><span class="mtk10">Toolbar</span><span class="mtk17">&gt;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk17">&lt;/</span><span class="mtk10">AppBar</span><span class="mtk17">&gt;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk17">&lt;/</span><span class="mtk10">Box</span><span class="mtk17">&gt;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk17">&lt;</span><span class="mtk10">Stack</span><span class="mtk1"> </span><span class="mtk12">gap</span><span class="mtk1">=</span><span class="mtk4">{</span><span class="mtk7">2</span><span class="mtk4">}</span><span class="mtk1"> </span><span class="mtk12">sx</span><span class="mtk1">=</span><span class="mtk4">{</span><span class="mtk1">{ </span><span class="mtk12">p:</span><span class="mtk1"> </span><span class="mtk7">2</span><span class="mtk1"> }</span><span class="mtk4">}</span><span class="mtk1"> </span><span class="mtk12">alignItems</span><span class="mtk1">=</span><span class="mtk8">&quot;flex-start&quot;</span><span class="mtk17">&gt;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk17">&lt;</span><span class="mtk10">Button</span><span class="mtk1"> </span><span class="mtk12">variant</span><span class="mtk1">=</span><span class="mtk8">&quot;contained&quot;</span><span class="mtk17">&gt;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> Button</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk17">&lt;/</span><span class="mtk10">Button</span><span class="mtk17">&gt;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk17">&lt;</span><span class="mtk10">Box</span><span class="mtk17">&gt;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk17">&lt;</span><span class="mtk10">Checkbox</span><span class="mtk1"> </span><span class="mtk12">defaultChecked</span><span class="mtk1"> </span><span class="mtk17">/&gt;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk17">&lt;/</span><span class="mtk10">Box</span><span class="mtk17">&gt;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk17">&lt;</span><span class="mtk10">Stack</span><span class="mtk1"> </span><span class="mtk12">direction</span><span class="mtk1">=</span><span class="mtk8">&quot;row&quot;</span><span class="mtk17">&gt;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk17">&lt;</span><span class="mtk10">FormControl</span><span class="mtk17">&gt;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk17">&lt;</span><span class="mtk10">RadioGroup</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">aria-labelledby</span><span class="mtk1">=</span><span class="mtk8">&quot;demo-radio-buttons-group-label&quot;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">defaultValue</span><span class="mtk1">=</span><span class="mtk8">&quot;optionA&quot;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">name</span><span class="mtk1">=</span><span class="mtk8">&quot;radio-buttons-group&quot;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk17">&gt;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk17">&lt;</span><span class="mtk10">FormControlLabel</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">value</span><span class="mtk1">=</span><span class="mtk8">&quot;optionA&quot;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">control</span><span class="mtk1">=</span><span class="mtk4">{</span><span class="mtk17">&lt;</span><span class="mtk10">Radio</span><span class="mtk1"> </span><span class="mtk17">/&gt;</span><span class="mtk4">}</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">label</span><span class="mtk1">=</span><span class="mtk8">&quot;Option A&quot;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk17">/&gt;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk17">&lt;</span><span class="mtk10">FormControlLabel</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">value</span><span class="mtk1">=</span><span class="mtk8">&quot;optionB&quot;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">control</span><span class="mtk1">=</span><span class="mtk4">{</span><span class="mtk17">&lt;</span><span class="mtk10">Radio</span><span class="mtk1"> </span><span class="mtk17">/&gt;</span><span class="mtk4">}</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">label</span><span class="mtk1">=</span><span class="mtk8">&quot;Option B&quot;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk17">/&gt;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk17">&lt;/</span><span class="mtk10">RadioGroup</span><span class="mtk17">&gt;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk17">&lt;/</span><span class="mtk10">FormControl</span><span class="mtk17">&gt;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk17">&lt;/</span><span class="mtk10">Stack</span><span class="mtk17">&gt;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk17">&lt;/</span><span class="mtk10">Stack</span><span class="mtk17">&gt;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk17">&lt;/</span><span class="mtk10">Box</span><span class="mtk17">&gt;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> );</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1">}</span></span></span></code></pre> <p>Adding a new background color using <code>sx</code> can be persuasively an easy and quick solution:</p> <div class="circle error"></div> <pre class="grvsc-container default-dark" data-language="jsx" data-index="2"><code class="grvsc-code"><span class="grvsc-line"><span class="grvsc-source"><span class="mtk17">&lt;</span><span class="mtk10">Button</span><span class="mtk1"> </span><span class="mtk12">sx</span><span class="mtk1">=</span><span class="mtk4">{</span><span class="mtk1">{ </span><span class="mtk12">bgcolor:</span><span class="mtk1"> </span><span class="mtk8">&quot;#2a9461&quot;</span><span class="mtk1"> }</span><span class="mtk4">}</span><span class="mtk17">&gt;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> Button</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk17">&lt;/</span><span class="mtk10">Button</span><span class="mtk17">&gt;</span></span></span></code></pre> <p>But the problem arises when the primary color is used in other elements. Remember that we aren’t just changing the background color, we are also changing the primary palette color. So with the above solution, we need to apply the exact change to all other elements, such as the checkbox, radio buttons, and headers.</p> <p>Below, we can see how the change only affected the button but not the rest.</p> <div class="circle error"></div> <p><span class="gatsby-resp-image-wrapper" style="position: relative; display: block; margin-left: auto; margin-right: auto; max-width: 720px; " > <a class="gatsby-resp-image-link" href="/static/cc5410515c277c4b64e4c3b9f638c350/50517/custom-theme-2.png" style="display: block" target="_blank" rel="noopener" > <span class="gatsby-resp-image-background-image" style="padding-bottom: 38.33333333333333%; position: relative; bottom: 0; left: 0; background-image: url('data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABQAAAAICAYAAAD5nd/tAAAACXBIWXMAACToAAAk6AGCYwUcAAAAlklEQVR42mNwnXD7v133zf8mrdf/m7aRhy07boBx3Ly7/xkCp1797z3x6n/X3mv/3frIw14Trv/3mHDtf/aSO/8ZYla3/G/at/D/z98//4PAv39/QQTJ+N9fiD6GQ/du/r//7sn/vyCDqAAY3n39C3XZf+oY+PLth/8fP36gnoGvXr/+/+rVK6CB1DGR4c+fP/9BmFoAAKQHQv5AKehXAAAAAElFTkSuQmCC'); background-size: cover; display: block;" ></span> <img class="gatsby-resp-image-image" alt="Default Theme" title="" src="/static/cc5410515c277c4b64e4c3b9f638c350/37523/custom-theme-2.png" srcset="/static/cc5410515c277c4b64e4c3b9f638c350/e9ff0/custom-theme-2.png 180w, /static/cc5410515c277c4b64e4c3b9f638c350/f21e7/custom-theme-2.png 360w, /static/cc5410515c277c4b64e4c3b9f638c350/37523/custom-theme-2.png 720w, /static/cc5410515c277c4b64e4c3b9f638c350/302a4/custom-theme-2.png 1080w, /static/cc5410515c277c4b64e4c3b9f638c350/07a9c/custom-theme-2.png 1440w, /static/cc5410515c277c4b64e4c3b9f638c350/50517/custom-theme-2.png 2060w" sizes="(max-width: 720px) 100vw, 720px" style="width:100%;height:100%;margin:0;vertical-align:middle;position:absolute;top:0;left:0;" loading="lazy" decoding="async" /> </a> </span></p> <p>This approach is redundant and hard to scale as the application grows bigger and bigger. For that reason, MUI provides a <code>ThemeProvider</code> component to inject a theme into our application.</p> <h3 id="how-to-use-it" style="position:relative;"><a href="#how-to-use-it" aria-label="how to use it permalink" class="anchor before"><svg aria-hidden="true" focusable="false" height="16" version="1.1" viewBox="0 0 16 16" width="16"><path fill-rule="evenodd" d="M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z"></path></svg></a>How to use it</h3> <p>Let’s create a new custom theme in the main app component to override the primary color and then pass it into <code>ThemeProvider</code>.</p> <div class="circle success"></div> <pre class="grvsc-container default-dark" data-language="jsx" data-index="3"><code class="grvsc-code"><span class="grvsc-line"><span class="grvsc-source"><span class="mtk15">import</span><span class="mtk1"> { </span><span class="mtk12">ThemeProvider</span><span class="mtk1">, </span><span class="mtk12">createTheme</span><span class="mtk1"> } </span><span class="mtk15">from</span><span class="mtk1"> </span><span class="mtk8">&quot;@mui/material/styles&quot;</span><span class="mtk1">;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk4">const</span><span class="mtk1"> </span><span class="mtk12">theme</span><span class="mtk1"> = </span><span class="mtk11">createTheme</span><span class="mtk1">({</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">palette:</span><span class="mtk1"> {</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">primary:</span><span class="mtk1"> {</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">main:</span><span class="mtk1"> </span><span class="mtk8">&quot;#2a9461&quot;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> }</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> }</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1">});</span></span></span> <span class="grvsc-line"><span class="grvsc-source"></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk15">export</span><span class="mtk1"> </span><span class="mtk15">default</span><span class="mtk1"> </span><span class="mtk4">function</span><span class="mtk1"> </span><span class="mtk11">App</span><span class="mtk1">() {</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk15">return</span><span class="mtk1"> (</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk17">&lt;</span><span class="mtk10">ThemeProvider</span><span class="mtk1"> </span><span class="mtk12">theme</span><span class="mtk1">=</span><span class="mtk4">{</span><span class="mtk12">theme</span><span class="mtk4">}</span><span class="mtk17">&gt;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> // MUI components</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk17">&lt;/</span><span class="mtk10">ThemeProvider</span><span class="mtk17">&gt;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> );</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1">}</span></span></span></code></pre> <p>Here is how it looks after creating a custom theme:</p> <div class="circle success"></div> <p><span class="gatsby-resp-image-wrapper" style="position: relative; display: block; margin-left: auto; margin-right: auto; max-width: 720px; " > <a class="gatsby-resp-image-link" href="/static/56375d90d9c445bdddb2f06756d547cf/6c2f8/custom-theme-3.png" style="display: block" target="_blank" rel="noopener" > <span class="gatsby-resp-image-background-image" style="padding-bottom: 43.333333333333336%; position: relative; bottom: 0; left: 0; background-image: url('data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABQAAAAJCAYAAAAywQxIAAAACXBIWXMAACToAAAk6AGCYwUcAAAAqElEQVR42mMIWln/3395zX/XhaX/3RaVkYW9llT891hc/j9784T/DFErm/9HrGj6H7Ck5n/g0lqycMjy+v/By+r+F2+d9p8haV3n/4qds/5//fntPwj8+/sXSPwjCf8D4r9QfQxHHlz+f/ft0/9//v75Tw3A8O7bJ4jL/lMHMLx89+b/h/fvwc6mioGvXr/6//LlS0gYUMPAv3/+/P/z589/agGG/1QGAErmijuK37oQAAAAAElFTkSuQmCC'); background-size: cover; display: block;" ></span> <img class="gatsby-resp-image-image" alt="Style Tokens" title="" src="/static/56375d90d9c445bdddb2f06756d547cf/37523/custom-theme-3.png" srcset="/static/56375d90d9c445bdddb2f06756d547cf/e9ff0/custom-theme-3.png 180w, /static/56375d90d9c445bdddb2f06756d547cf/f21e7/custom-theme-3.png 360w, /static/56375d90d9c445bdddb2f06756d547cf/37523/custom-theme-3.png 720w, /static/56375d90d9c445bdddb2f06756d547cf/302a4/custom-theme-3.png 1080w, /static/56375d90d9c445bdddb2f06756d547cf/07a9c/custom-theme-3.png 1440w, /static/56375d90d9c445bdddb2f06756d547cf/6c2f8/custom-theme-3.png 2065w" sizes="(max-width: 720px) 100vw, 720px" style="width:100%;height:100%;margin:0;vertical-align:middle;position:absolute;top:0;left:0;" loading="lazy" decoding="async" /> </a> </span></p> <p>Similarly, we can customize other palettes like the secondary color.</p> <pre class="grvsc-container grvsc-has-line-highlighting default-dark" data-language="jsx" data-index="4"><code class="grvsc-code"><span class="grvsc-line"><span class="grvsc-source"><span class="mtk15">import</span><span class="mtk1"> { </span><span class="mtk12">ThemeProvider</span><span class="mtk1">, </span><span class="mtk12">createTheme</span><span class="mtk1"> } </span><span class="mtk15">from</span><span class="mtk1"> </span><span class="mtk8">&quot;@mui/material/styles&quot;</span><span class="mtk1">;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk4">const</span><span class="mtk1"> </span><span class="mtk12">theme</span><span class="mtk1"> = </span><span class="mtk11">createTheme</span><span class="mtk1">({</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">palette:</span><span class="mtk1"> {</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">primary:</span><span class="mtk1"> {</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">main:</span><span class="mtk1"> </span><span class="mtk8">&quot;#2a9461&quot;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> },</span></span></span> <span class="grvsc-line grvsc-line-highlighted"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">secondary:</span><span class="mtk1"> {</span></span></span> <span class="grvsc-line grvsc-line-highlighted"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">main:</span><span class="mtk1"> </span><span class="mtk8">&quot;#494c7d&quot;</span></span></span> <span class="grvsc-line grvsc-line-highlighted"><span class="grvsc-source"><span class="mtk1"> }</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> }</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1">});</span></span></span> <span class="grvsc-line"><span class="grvsc-source"></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk15">export</span><span class="mtk1"> </span><span class="mtk15">default</span><span class="mtk1"> </span><span class="mtk4">function</span><span class="mtk1"> </span><span class="mtk11">App</span><span class="mtk1">() {</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk15">return</span><span class="mtk1"> (</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk17">&lt;</span><span class="mtk10">ThemeProvider</span><span class="mtk1"> </span><span class="mtk12">theme</span><span class="mtk1">=</span><span class="mtk4">{</span><span class="mtk12">theme</span><span class="mtk4">}</span><span class="mtk17">&gt;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> // MUI components</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk17">&lt;/</span><span class="mtk10">ThemeProvider</span><span class="mtk17">&gt;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> );</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1">}</span></span></span></code></pre> <p>We have to set the <code>color</code> value to use a secondary color. If not specified, the default is primary.</p> <p>Let’s change the header and button to a secondary color.</p> <pre class="grvsc-container grvsc-has-line-highlighting default-dark" data-language="jsx" data-index="5"><code class="grvsc-code"><span class="grvsc-line"><span class="grvsc-source"><span class="mtk15">export</span><span class="mtk1"> </span><span class="mtk15">default</span><span class="mtk1"> </span><span class="mtk4">function</span><span class="mtk1"> </span><span class="mtk11">App</span><span class="mtk1">() {</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk15">return</span><span class="mtk1"> (</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk17">&lt;</span><span class="mtk10">Box</span><span class="mtk17">&gt;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk17">&lt;</span><span class="mtk10">Box</span><span class="mtk1"> </span><span class="mtk12">sx</span><span class="mtk1">=</span><span class="mtk4">{</span><span class="mtk1">{ </span><span class="mtk12">flexGrow:</span><span class="mtk1"> </span><span class="mtk7">1</span><span class="mtk1"> }</span><span class="mtk4">}</span><span class="mtk17">&gt;</span></span></span> <span class="grvsc-line grvsc-line-highlighted"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk17">&lt;</span><span class="mtk10">AppBar</span><span class="mtk1"> </span><span class="mtk12">position</span><span class="mtk1">=</span><span class="mtk8">&quot;static&quot;</span><span class="mtk1"> </span><span class="mtk12">color</span><span class="mtk1">=</span><span class="mtk8">&quot;secondary&quot;</span><span class="mtk17">&gt;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk17">&lt;</span><span class="mtk10">Toolbar</span><span class="mtk17">&gt;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk17">&lt;</span><span class="mtk10">Typography</span><span class="mtk1"> </span><span class="mtk12">variant</span><span class="mtk1">=</span><span class="mtk8">&quot;h6&quot;</span><span class="mtk1"> </span><span class="mtk12">component</span><span class="mtk1">=</span><span class="mtk8">&quot;div&quot;</span><span class="mtk1"> </span><span class="mtk12">sx</span><span class="mtk1">=</span><span class="mtk4">{</span><span class="mtk1">{ </span><span class="mtk12">flexGrow:</span><span class="mtk1"> </span><span class="mtk7">1</span><span class="mtk1"> }</span><span class="mtk4">}</span><span class="mtk17">&gt;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> Header</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk17">&lt;/</span><span class="mtk10">Typography</span><span class="mtk17">&gt;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk17">&lt;</span><span class="mtk10">Button</span><span class="mtk1"> </span><span class="mtk12">color</span><span class="mtk1">=</span><span class="mtk8">&quot;inherit&quot;</span><span class="mtk17">&gt;</span><span class="mtk1">Login</span><span class="mtk17">&lt;/</span><span class="mtk10">Button</span><span class="mtk17">&gt;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk17">&lt;/</span><span class="mtk10">Toolbar</span><span class="mtk17">&gt;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk17">&lt;/</span><span class="mtk10">AppBar</span><span class="mtk17">&gt;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk17">&lt;/</span><span class="mtk10">Box</span><span class="mtk17">&gt;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk17">&lt;</span><span class="mtk10">Stack</span><span class="mtk1"> </span><span class="mtk12">gap</span><span class="mtk1">=</span><span class="mtk4">{</span><span class="mtk7">2</span><span class="mtk4">}</span><span class="mtk1"> </span><span class="mtk12">sx</span><span class="mtk1">=</span><span class="mtk4">{</span><span class="mtk1">{ </span><span class="mtk12">p:</span><span class="mtk1"> </span><span class="mtk7">2</span><span class="mtk1"> }</span><span class="mtk4">}</span><span class="mtk1"> </span><span class="mtk12">alignItems</span><span class="mtk1">=</span><span class="mtk8">&quot;flex-start&quot;</span><span class="mtk17">&gt;</span></span></span> <span class="grvsc-line grvsc-line-highlighted"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk17">&lt;</span><span class="mtk10">Button</span><span class="mtk1"> </span><span class="mtk12">variant</span><span class="mtk1">=</span><span class="mtk8">&quot;contained&quot;</span><span class="mtk1"> </span><span class="mtk12">color</span><span class="mtk1">=</span><span class="mtk8">&quot;secondary&quot;</span><span class="mtk17">&gt;</span></span></span> <span class="grvsc-line grvsc-line-highlighted"><span class="grvsc-source"><span class="mtk1"> Button</span></span></span> <span class="grvsc-line grvsc-line-highlighted"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk17">&lt;/</span><span class="mtk10">Button</span><span class="mtk17">&gt;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk17">&lt;</span><span class="mtk10">Box</span><span class="mtk17">&gt;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk17">&lt;</span><span class="mtk10">Checkbox</span><span class="mtk1"> </span><span class="mtk12">defaultChecked</span><span class="mtk1"> </span><span class="mtk17">/&gt;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk17">&lt;/</span><span class="mtk10">Box</span><span class="mtk17">&gt;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk17">&lt;</span><span class="mtk10">Stack</span><span class="mtk1"> </span><span class="mtk12">direction</span><span class="mtk1">=</span><span class="mtk8">&quot;row&quot;</span><span class="mtk17">&gt;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk17">&lt;</span><span class="mtk10">FormControl</span><span class="mtk17">&gt;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk17">&lt;</span><span class="mtk10">RadioGroup</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">aria-labelledby</span><span class="mtk1">=</span><span class="mtk8">&quot;demo-radio-buttons-group-label&quot;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">defaultValue</span><span class="mtk1">=</span><span class="mtk8">&quot;optionA&quot;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">name</span><span class="mtk1">=</span><span class="mtk8">&quot;radio-buttons-group&quot;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk17">&gt;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk17">&lt;</span><span class="mtk10">FormControlLabel</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">value</span><span class="mtk1">=</span><span class="mtk8">&quot;optionA&quot;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">control</span><span class="mtk1">=</span><span class="mtk4">{</span><span class="mtk17">&lt;</span><span class="mtk10">Radio</span><span class="mtk1"> </span><span class="mtk17">/&gt;</span><span class="mtk4">}</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">label</span><span class="mtk1">=</span><span class="mtk8">&quot;Option A&quot;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk17">/&gt;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk17">&lt;</span><span class="mtk10">FormControlLabel</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">value</span><span class="mtk1">=</span><span class="mtk8">&quot;optionB&quot;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">control</span><span class="mtk1">=</span><span class="mtk4">{</span><span class="mtk17">&lt;</span><span class="mtk10">Radioo</span><span class="mtk1"> </span><span class="mtk17">/&gt;</span><span class="mtk4">}</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">label</span><span class="mtk1">=</span><span class="mtk8">&quot;Option B&quot;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk17">/&gt;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk17">&lt;/</span><span class="mtk10">RadioGroup</span><span class="mtk17">&gt;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk17">&lt;/</span><span class="mtk10">FormControl</span><span class="mtk17">&gt;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk17">&lt;/</span><span class="mtk10">Stack</span><span class="mtk17">&gt;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk17">&lt;/</span><span class="mtk10">Stack</span><span class="mtk17">&gt;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk17">&lt;/</span><span class="mtk10">Box</span><span class="mtk17">&gt;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> );</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1">}</span></span></span></code></pre> <p><span class="gatsby-resp-image-wrapper" style="position: relative; display: block; margin-left: auto; margin-right: auto; max-width: 720px; " > <a class="gatsby-resp-image-link" href="/static/1353a5003ffae4a2d41a31aa3e5a61bc/55681/custom-theme-4.png" style="display: block" target="_blank" rel="noopener" > <span class="gatsby-resp-image-background-image" style="padding-bottom: 39.44444444444444%; position: relative; bottom: 0; left: 0; background-image: url('data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABQAAAAICAYAAAD5nd/tAAAACXBIWXMAACToAAAk6AGCYwUcAAAAnklEQVR42mPIK5j2PyN78v+4xJ7/kdEd/6NiOknG0bGd/xOSev9nZk/5z1DXsPB/afns/0UlM8E0ObisYvb/iqq5/xubF/9nWLP68P/8gun/N2w69h8E/v37958SwPDo1av/9588///t64//1AAMH35++f/tF3UMAxv48vO7/y+Brvz06RN1DPz27dv/d+/e/f/y5Qt1DARFAgxTAwAAuhY5LP9MbikAAAAASUVORK5CYII='); background-size: cover; display: block;" ></span> <img class="gatsby-resp-image-image" alt="Custom Theme" title="" src="/static/1353a5003ffae4a2d41a31aa3e5a61bc/37523/custom-theme-4.png" srcset="/static/1353a5003ffae4a2d41a31aa3e5a61bc/e9ff0/custom-theme-4.png 180w, /static/1353a5003ffae4a2d41a31aa3e5a61bc/f21e7/custom-theme-4.png 360w, /static/1353a5003ffae4a2d41a31aa3e5a61bc/37523/custom-theme-4.png 720w, /static/1353a5003ffae4a2d41a31aa3e5a61bc/302a4/custom-theme-4.png 1080w, /static/1353a5003ffae4a2d41a31aa3e5a61bc/07a9c/custom-theme-4.png 1440w, /static/1353a5003ffae4a2d41a31aa3e5a61bc/55681/custom-theme-4.png 2062w" sizes="(max-width: 720px) 100vw, 720px" style="width:100%;height:100%;margin:0;vertical-align:middle;position:absolute;top:0;left:0;" loading="lazy" decoding="async" /> </a> </span></p> <p>We can see how “primary” and “secondary” now reflects the new colors (green and purple).</p> <h2 id="custom-palette" style="position:relative;"><a href="#custom-palette" aria-label="custom palette permalink" class="anchor before"><svg aria-hidden="true" focusable="false" height="16" version="1.1" viewBox="0 0 16 16" width="16"><path fill-rule="evenodd" d="M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z"></path></svg></a>Custom palette</h2> <h3 id="how-it-works" style="position:relative;"><a href="#how-it-works" aria-label="how it works permalink" class="anchor before"><svg aria-hidden="true" focusable="false" height="16" version="1.1" viewBox="0 0 16 16" width="16"><path fill-rule="evenodd" d="M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z"></path></svg></a>How it works</h3> <p>The default theme has several built-in palettes, such as primary, secondary, success, and warning.</p> <p><span class="gatsby-resp-image-wrapper" style="position: relative; display: block; margin-left: auto; margin-right: auto; max-width: 720px; " > <a class="gatsby-resp-image-link" href="/static/cc6ca6db04c004a08d7474c625a635b1/5e4a4/style-tokens.png" style="display: block" target="_blank" rel="noopener" > <span class="gatsby-resp-image-background-image" style="padding-bottom: 102.22222222222221%; position: relative; bottom: 0; left: 0; background-image: url('data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABQAAAAUCAYAAACNiR0NAAAACXBIWXMAABnWAAAZ1gEY0crtAAABaklEQVR42qWUWY6DMBBEOVLwBoQlEJYEMGaAkAlKIj7m/meosX0E/NH+sKynald3eVEUYVQj7l2NJDtDCAFCCCilh8qL4xiv1wvjqHC9FgjD0A0YhgHmacG8ShRVpC/ZYZgFMhGgunVopULZtBBRAp8HIDw8VJ5PKKqqwvC7I1cZssYHoQKU8UPlnU4nlEWOn+0P/TOHXCIw7vCH5rhcLpCyR98NaO4VKPePA82YSCkxTZN2+WovCaFuQKWUBZZlCc4dXeaco65rNE2DNE2tOieF5jAK13XF47Gg7+9WJTkKNFth2t33XUOfuDWpBroMNmO25a7rkMQpfJ+AMQrmAjQtf79fyDlH0QSIcwoR6Afk0C6HmOdZt7toYyoEQejmcpIkGIZBr1+uk0bYlp2AJr7e77d2eIXsWzuLJiOPRphnZm/bNh2yCkWewfypk8Lz+WxNadvWpo6LOgvMsgyfzwfLYkypYTbHReE/cUqSKUv9XccAAAAASUVORK5CYII='); background-size: cover; display: block;" ></span> <img class="gatsby-resp-image-image" alt="Style Tokens" title="" src="/static/cc6ca6db04c004a08d7474c625a635b1/37523/style-tokens.png" srcset="/static/cc6ca6db04c004a08d7474c625a635b1/e9ff0/style-tokens.png 180w, /static/cc6ca6db04c004a08d7474c625a635b1/f21e7/style-tokens.png 360w, /static/cc6ca6db04c004a08d7474c625a635b1/37523/style-tokens.png 720w, /static/cc6ca6db04c004a08d7474c625a635b1/302a4/style-tokens.png 1080w, /static/cc6ca6db04c004a08d7474c625a635b1/5e4a4/style-tokens.png 1403w" sizes="(max-width: 720px) 100vw, 720px" style="width:100%;height:100%;margin:0;vertical-align:middle;position:absolute;top:0;left:0;" loading="lazy" decoding="async" /> </a> </span></p> <p>And as shown above, each palette has four values (main, dark, light and contrastText).</p> <p>When styling components using <code>sx</code>, we can directly access values as follows:</p> <pre class="grvsc-container default-dark" data-language="jsx" data-index="6"><code class="grvsc-code"><span class="grvsc-line"><span class="grvsc-source"><span class="mtk17">&lt;</span><span class="mtk10">Button</span><span class="mtk1"> </span><span class="mtk12">sx</span><span class="mtk1">=</span><span class="mtk4">{</span><span class="mtk1">{ </span><span class="mtk12">color:</span><span class="mtk1"> </span><span class="mtk8">&quot;primary.main&quot;</span><span class="mtk1"> }</span><span class="mtk4">}</span><span class="mtk17">&gt;</span><span class="mtk1">Button</span><span class="mtk17">&lt;/</span><span class="mtk10">Button</span><span class="mtk17">&gt;</span></span></span></code></pre> <p>Which is a shortcut to doing this:</p> <pre class="grvsc-container default-dark" data-language="jsx" data-index="7"><code class="grvsc-code"><span class="grvsc-line"><span class="grvsc-source"><span class="mtk17">&lt;</span><span class="mtk10">Button</span><span class="mtk1"> </span><span class="mtk12">sx</span><span class="mtk1">=</span><span class="mtk4">{</span><span class="mtk1">{ </span><span class="mtk11">color</span><span class="mtk12">:</span><span class="mtk1"> (</span><span class="mtk12">theme</span><span class="mtk1">) </span><span class="mtk4">=&gt;</span><span class="mtk1"> </span><span class="mtk12">theme</span><span class="mtk1">.</span><span class="mtk12">palette</span><span class="mtk1">.</span><span class="mtk12">primary</span><span class="mtk1">.</span><span class="mtk12">main</span><span class="mtk1"> }</span><span class="mtk4">}</span><span class="mtk17">&gt;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> Button</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk17">&lt;/</span><span class="mtk10">Button</span><span class="mtk17">&gt;</span></span></span></code></pre> <p>Cool right! Now, when using the <code>color</code> prop to set a palette, MUI will automatically pick “main” as the main color and “contrastText” as the text color.</p> <pre class="grvsc-container default-dark" data-language="jsx" data-index="8"><code class="grvsc-code"><span class="grvsc-line"><span class="grvsc-source"><span class="mtk17">&lt;</span><span class="mtk10">Button</span><span class="mtk1"> </span><span class="mtk12">variant</span><span class="mtk1">=</span><span class="mtk8">&quot;contained&quot;</span><span class="mtk1"> </span><span class="mtk12">color</span><span class="mtk1">=</span><span class="mtk8">&quot;secondary&quot;</span><span class="mtk17">&gt;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> Button</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk17">&lt;/</span><span class="mtk10">Button</span><span class="mtk17">&gt;</span></span></span></code></pre> <p><span class="gatsby-resp-image-wrapper" style="position: relative; display: block; margin-left: auto; margin-right: auto; max-width: 354px; " > <a class="gatsby-resp-image-link" href="/static/140baea6b759e5f6483dd55e16eeade9/8f50f/secondary-button.png" style="display: block" target="_blank" rel="noopener" > <span class="gatsby-resp-image-background-image" style="padding-bottom: 68.88888888888889%; position: relative; bottom: 0; left: 0; background-image: url('data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABQAAAAOCAYAAAAvxDzwAAAACXBIWXMAAAsTAAALEwEAmpwYAAAB1UlEQVR42rWT30tUQRTHL/vgv1D0ID330B8QveRTf8HWspG4bd1MMFziWiYV0e+N0HYrycgSekv7gYUERb+xoKAXXXHXCiUienCT9Y7uzP147r0bkewNkjrw5ZyZOfOd75w5Y/GPzVrtRm/+KZTvwY+REOX7Mvf47wk9L/TldxspDFuMD8co3IkxMWQx92b9ahUaqrPHWfyYwZ12qBQd1HQG/eV0fUJfhTGeeIF4Y0yAYCxrnp6RhJmf2dE19Df5du36KDt2nmW33UPLrguk9/RI3EsqfZ5k8yVyJxIU3/eFdFrJIVUJQtQlPHLsJk1bu3EOXqW9Pc/+jj5a23J0Hh7ggNPPliaH3OWRIFdrs1KhF9TEhzbVYLKza5DtcZtHt+KirpdtyTPEE6ew9+UFOTZtznAxfzeKMKT0oWsKr/Q/odU+xNGubppTWbl2Vq6blfgcLeITyZPcHnoeQWgqsDguKxNQ9VFAL3zALU8yX9Eo5aJcF1cQxCqMVxL9Ilx4y9dna5h82MjUaCOFB+v49nqDEH+uvZ/5Yz/WIXwlzWnx8kYDLwYaGBuMMTe2FpY+haXwdK1dfkf011NTLJVSuCUbVdyLKqXxZjtE4fe6ffbf/nKULQMxv/qh49y7HgAAAABJRU5ErkJggg=='); background-size: cover; display: block;" ></span> <img class="gatsby-resp-image-image" alt="Secondary Button" title="" src="/static/140baea6b759e5f6483dd55e16eeade9/8f50f/secondary-button.png" srcset="/static/140baea6b759e5f6483dd55e16eeade9/e9ff0/secondary-button.png 180w, /static/140baea6b759e5f6483dd55e16eeade9/8f50f/secondary-button.png 354w" sizes="(max-width: 354px) 100vw, 354px" style="width:100%;height:100%;margin:0;vertical-align:middle;position:absolute;top:0;left:0;" loading="lazy" decoding="async" /> </a> </span></p> <h3 id="create-a-new-palette" style="position:relative;"><a href="#create-a-new-palette" aria-label="create a new palette permalink" class="anchor before"><svg aria-hidden="true" focusable="false" height="16" version="1.1" viewBox="0 0 16 16" width="16"><path fill-rule="evenodd" d="M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z"></path></svg></a>Create a new palette</h3> <p>We can append a new color to the palette object with a main and text color to create a new custom palette.</p> <pre class="grvsc-container grvsc-has-line-highlighting default-dark" data-language="jsx" data-index="9"><code class="grvsc-code"><span class="grvsc-line"><span class="grvsc-source"><span class="mtk4">const</span><span class="mtk1"> </span><span class="mtk12">theme</span><span class="mtk1"> = </span><span class="mtk11">createTheme</span><span class="mtk1">({</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">palette:</span><span class="mtk1"> {</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">primary:</span><span class="mtk1"> {</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">main:</span><span class="mtk1"> </span><span class="mtk8">&quot;#2a9461&quot;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> },</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">secondary:</span><span class="mtk1"> {</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">main:</span><span class="mtk1"> </span><span class="mtk8">&quot;#494c7d&quot;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> },</span></span></span> <span class="grvsc-line grvsc-line-highlighted"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">primaryLight:</span><span class="mtk1"> {</span></span></span> <span class="grvsc-line grvsc-line-highlighted"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">main:</span><span class="mtk1"> </span><span class="mtk8">&quot;#dbece2&quot;</span><span class="mtk1">,</span></span></span> <span class="grvsc-line grvsc-line-highlighted"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">contrastText:</span><span class="mtk1"> </span><span class="mtk8">&quot;#616161&quot;</span></span></span> <span class="grvsc-line grvsc-line-highlighted"><span class="grvsc-source"><span class="mtk1"> }</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> }</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1">});</span></span></span></code></pre> <p>“contrastText”, “dark” and “light” are optional, and if omitted, their values will be calculated automatically according to the “tonalOffset” and “contrastThreshold” of the “main” value. More details on this are available on <a href="https://mui.com/material-ui/customization/palette/#using-a-color-object">MUI Palette Documentation</a></p> <p>Let’s replace the header color with the new custom palette we just created.</p> <pre class="grvsc-container grvsc-has-line-highlighting default-dark" data-language="jsx" data-index="10"><code class="grvsc-code"><span class="grvsc-line"><span class="grvsc-source"><span class="mtk15">export</span><span class="mtk1"> </span><span class="mtk15">default</span><span class="mtk1"> </span><span class="mtk4">function</span><span class="mtk1"> </span><span class="mtk11">App</span><span class="mtk1">() {</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk15">return</span><span class="mtk1"> (</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk17">&lt;</span><span class="mtk10">Box</span><span class="mtk17">&gt;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk17">&lt;</span><span class="mtk10">Box</span><span class="mtk1"> </span><span class="mtk12">sx</span><span class="mtk1">=</span><span class="mtk4">{</span><span class="mtk1">{ </span><span class="mtk12">flexGrow:</span><span class="mtk1"> </span><span class="mtk7">1</span><span class="mtk1"> }</span><span class="mtk4">}</span><span class="mtk17">&gt;</span></span></span> <span class="grvsc-line grvsc-line-highlighted"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk17">&lt;</span><span class="mtk10">AppBar</span><span class="mtk1"> </span><span class="mtk12">position</span><span class="mtk1">=</span><span class="mtk8">&quot;static&quot;</span><span class="mtk1"> </span><span class="mtk12">color</span><span class="mtk1">=</span><span class="mtk8">&quot;primaryLight&quot;</span><span class="mtk17">&gt;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk17">&lt;</span><span class="mtk10">Toolbar</span><span class="mtk17">&gt;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk17">&lt;</span><span class="mtk10">Typography</span><span class="mtk1"> </span><span class="mtk12">variant</span><span class="mtk1">=</span><span class="mtk8">&quot;h6&quot;</span><span class="mtk1"> </span><span class="mtk12">component</span><span class="mtk1">=</span><span class="mtk8">&quot;div&quot;</span><span class="mtk1"> </span><span class="mtk12">sx</span><span class="mtk1">=</span><span class="mtk4">{</span><span class="mtk1">{ </span><span class="mtk12">flexGrow:</span><span class="mtk1"> </span><span class="mtk7">1</span><span class="mtk1"> }</span><span class="mtk4">}</span><span class="mtk17">&gt;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> Header</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk17">&lt;/</span><span class="mtk10">Typography</span><span class="mtk17">&gt;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk17">&lt;</span><span class="mtk10">Button</span><span class="mtk1"> </span><span class="mtk12">color</span><span class="mtk1">=</span><span class="mtk8">&quot;inherit&quot;</span><span class="mtk17">&gt;</span><span class="mtk1">Login</span><span class="mtk17">&lt;/</span><span class="mtk10">Button</span><span class="mtk17">&gt;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk17">&lt;/</span><span class="mtk10">Toolbar</span><span class="mtk17">&gt;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk17">&lt;/</span><span class="mtk10">AppBar</span><span class="mtk17">&gt;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk17">&lt;/</span><span class="mtk10">Box</span><span class="mtk17">&gt;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk17">&lt;</span><span class="mtk10">Stack</span><span class="mtk1"> </span><span class="mtk12">gap</span><span class="mtk1">=</span><span class="mtk4">{</span><span class="mtk7">2</span><span class="mtk4">}</span><span class="mtk1"> </span><span class="mtk12">sx</span><span class="mtk1">=</span><span class="mtk4">{</span><span class="mtk1">{ </span><span class="mtk12">p:</span><span class="mtk1"> </span><span class="mtk7">2</span><span class="mtk1"> }</span><span class="mtk4">}</span><span class="mtk1"> </span><span class="mtk12">alignItems</span><span class="mtk1">=</span><span class="mtk8">&quot;flex-start&quot;</span><span class="mtk17">&gt;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk17">&lt;</span><span class="mtk10">Button</span><span class="mtk1"> </span><span class="mtk12">variant</span><span class="mtk1">=</span><span class="mtk8">&quot;contained&quot;</span><span class="mtk1"> </span><span class="mtk12">color</span><span class="mtk1">=</span><span class="mtk8">&quot;secondary&quot;</span><span class="mtk17">&gt;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> Button</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk17">&lt;/</span><span class="mtk10">Button</span><span class="mtk17">&gt;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk17">&lt;</span><span class="mtk10">Box</span><span class="mtk17">&gt;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk17">&lt;</span><span class="mtk10">Checkbox</span><span class="mtk1"> </span><span class="mtk12">defaultChecked</span><span class="mtk1"> </span><span class="mtk17">/&gt;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk17">&lt;/</span><span class="mtk10">Box</span><span class="mtk17">&gt;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk17">&lt;</span><span class="mtk10">Stack</span><span class="mtk1"> </span><span class="mtk12">direction</span><span class="mtk1">=</span><span class="mtk8">&quot;row&quot;</span><span class="mtk17">&gt;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk17">&lt;</span><span class="mtk10">FormControl</span><span class="mtk17">&gt;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk17">&lt;</span><span class="mtk10">RadioGroup</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">aria-labelledby</span><span class="mtk1">=</span><span class="mtk8">&quot;demo-radio-buttons-group-label&quot;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">defaultValue</span><span class="mtk1">=</span><span class="mtk8">&quot;optionA&quot;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">name</span><span class="mtk1">=</span><span class="mtk8">&quot;radio-buttons-group&quot;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk17">&gt;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk17">&lt;</span><span class="mtk10">FormControlLabel</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">value</span><span class="mtk1">=</span><span class="mtk8">&quot;optionA&quot;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">control</span><span class="mtk1">=</span><span class="mtk4">{</span><span class="mtk17">&lt;</span><span class="mtk10">Radio</span><span class="mtk1"> </span><span class="mtk17">/&gt;</span><span class="mtk4">}</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">label</span><span class="mtk1">=</span><span class="mtk8">&quot;Option A&quot;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk17">/&gt;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk17">&lt;</span><span class="mtk10">FormControlLabel</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">value</span><span class="mtk1">=</span><span class="mtk8">&quot;optionB&quot;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">control</span><span class="mtk1">=</span><span class="mtk4">{</span><span class="mtk17">&lt;</span><span class="mtk10">Radioo</span><span class="mtk1"> </span><span class="mtk17">/&gt;</span><span class="mtk4">}</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">label</span><span class="mtk1">=</span><span class="mtk8">&quot;Option B&quot;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk17">/&gt;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk17">&lt;/</span><span class="mtk10">RadioGroup</span><span class="mtk17">&gt;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk17">&lt;/</span><span class="mtk10">FormControl</span><span class="mtk17">&gt;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk17">&lt;/</span><span class="mtk10">Stack</span><span class="mtk17">&gt;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk17">&lt;/</span><span class="mtk10">Stack</span><span class="mtk17">&gt;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk17">&lt;/</span><span class="mtk10">Box</span><span class="mtk17">&gt;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> );</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1">}</span></span></span></code></pre> <p><span class="gatsby-resp-image-wrapper" style="position: relative; display: block; margin-left: auto; margin-right: auto; max-width: 720px; " > <a class="gatsby-resp-image-link" href="/static/062814a9b84ea20ea0a8761590b69d4d/a6d66/custom-theme-5.png" style="display: block" target="_blank" rel="noopener" > <span class="gatsby-resp-image-background-image" style="padding-bottom: 37.77777777777778%; position: relative; bottom: 0; left: 0; background-image: url('data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABQAAAAICAYAAAD5nd/tAAAACXBIWXMAACToAAAk6AGCYwUcAAAAgUlEQVR42q2QOw6DMBBE9+CcIuIAHCFXSJeSFIjIYCDhI2zAllJR2B4iS7kA2Sc9zWiLKZbKSUKuPVoz/qWYW3TbCMplgefUoF7eqPTrtMVQof4mJUmGS3qFcw7e+9OGEGLS7f6AEEM8cEBm/8TCNriYFdZacEFKKWit+QZ/T+XiABoCa2z0RJbLAAAAAElFTkSuQmCC'); background-size: cover; display: block;" ></span> <img class="gatsby-resp-image-image" alt="Custom Theme" title="" src="/static/062814a9b84ea20ea0a8761590b69d4d/37523/custom-theme-5.png" srcset="/static/062814a9b84ea20ea0a8761590b69d4d/e9ff0/custom-theme-5.png 180w, /static/062814a9b84ea20ea0a8761590b69d4d/f21e7/custom-theme-5.png 360w, /static/062814a9b84ea20ea0a8761590b69d4d/37523/custom-theme-5.png 720w, /static/062814a9b84ea20ea0a8761590b69d4d/302a4/custom-theme-5.png 1080w, /static/062814a9b84ea20ea0a8761590b69d4d/07a9c/custom-theme-5.png 1440w, /static/062814a9b84ea20ea0a8761590b69d4d/a6d66/custom-theme-5.png 2070w" sizes="(max-width: 720px) 100vw, 720px" style="width:100%;height:100%;margin:0;vertical-align:middle;position:absolute;top:0;left:0;" loading="lazy" decoding="async" /> </a> </span></p> <p>We can see above how the header reflects the new text and background color.</p> <p>One last detail, if we’re using typescript, we also need to use module augmentation for the theme to accept the new values.</p> <pre class="grvsc-container default-dark" data-language="jsx" data-index="11"><code class="grvsc-code"><span class="grvsc-line"><span class="grvsc-source"><span class="mtk4">declare</span><span class="mtk1"> </span><span class="mtk4">module</span><span class="mtk1"> </span><span class="mtk8">&#39;@mui/material/styles&#39;</span><span class="mtk1"> {</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk4">interface</span><span class="mtk1"> </span><span class="mtk10">Palette</span><span class="mtk1"> {</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">primaryLight</span><span class="mtk1">: </span><span class="mtk10">Palette</span><span class="mtk1">[</span><span class="mtk8">&#39;primary&#39;</span><span class="mtk1">];</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> }</span></span></span> <span class="grvsc-line"><span class="grvsc-source"></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk4">interface</span><span class="mtk1"> </span><span class="mtk10">PaletteOptions</span><span class="mtk1"> {</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">primaryLight</span><span class="mtk1">: </span><span class="mtk10">PaletteOptions</span><span class="mtk1">[</span><span class="mtk8">&#39;primary&#39;</span><span class="mtk1">];</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> }</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1">}</span></span></span></code></pre> <h2 id="custom-colors" style="position:relative;"><a href="#custom-colors" aria-label="custom colors permalink" class="anchor before"><svg aria-hidden="true" focusable="false" height="16" version="1.1" viewBox="0 0 16 16" width="16"><path fill-rule="evenodd" d="M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z"></path></svg></a>Custom colors</h2> <p>MUI theme provides a set of built-in colors that we can import and use anywhere in the application. Each set of colors comes with all shades from 0 to 100.</p> <p>Let’s import the theme colors and replace the values we had earlier.</p> <pre class="grvsc-container default-dark" data-language="jsx" data-index="12"><code class="grvsc-code"><span class="grvsc-line"><span class="grvsc-source"><span class="mtk15">import</span><span class="mtk1"> { </span><span class="mtk12">createTheme</span><span class="mtk1"> } </span><span class="mtk15">from</span><span class="mtk1"> </span><span class="mtk8">&#39;@mui/material/styles&#39;</span><span class="mtk1">;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk15">import</span><span class="mtk1"> { </span><span class="mtk12">green</span><span class="mtk1">, </span><span class="mtk12">purple</span><span class="mtk1"> } </span><span class="mtk15">from</span><span class="mtk1"> </span><span class="mtk8">&#39;@mui/material/colors&#39;</span><span class="mtk1">;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk4">const</span><span class="mtk1"> </span><span class="mtk12">theme</span><span class="mtk1"> = </span><span class="mtk11">createTheme</span><span class="mtk1">({</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">palette:</span><span class="mtk1"> {</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">primary:</span><span class="mtk1"> {</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">main:</span><span class="mtk1"> </span><span class="mtk12">green</span><span class="mtk1">[</span><span class="mtk7">500</span><span class="mtk1">],</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> },</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">secondary:</span><span class="mtk1"> {</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">main:</span><span class="mtk1"> </span><span class="mtk12">purple</span><span class="mtk1">[</span><span class="mtk7">500</span><span class="mtk1">],</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> },</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> },</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1">});</span></span></span></code></pre> <p>If we look into the source code, we can see all the provided shades.</p> <p><span class="gatsby-resp-image-wrapper" style="position: relative; display: block; margin-left: auto; margin-right: auto; max-width: 720px; " > <a class="gatsby-resp-image-link" href="/static/d39e19ec49d749f1f79dab8ee8138d21/a20ae/image-2-906x1024.jpg" style="display: block" target="_blank" rel="noopener" > <span class="gatsby-resp-image-background-image" style="padding-bottom: 112.77777777777777%; position: relative; bottom: 0; left: 0; background-image: url('data:image/jpeg;base64,/9j/2wBDABALDA4MChAODQ4SERATGCgaGBYWGDEjJR0oOjM9PDkzODdASFxOQERXRTc4UG1RV19iZ2hnPk1xeXBkeFxlZ2P/2wBDARESEhgVGC8aGi9jQjhCY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2P/wgARCAAXABQDASIAAhEBAxEB/8QAFgABAQEAAAAAAAAAAAAAAAAAAAEF/8QAFAEBAAAAAAAAAAAAAAAAAAAAAP/aAAwDAQACEAMQAAABxoAAAH//xAAUEAEAAAAAAAAAAAAAAAAAAAAw/9oACAEBAAEFAh//xAAUEQEAAAAAAAAAAAAAAAAAAAAg/9oACAEDAQE/AR//xAAUEQEAAAAAAAAAAAAAAAAAAAAg/9oACAECAQE/AR//xAAUEAEAAAAAAAAAAAAAAAAAAAAw/9oACAEBAAY/Ah//xAAXEAADAQAAAAAAAAAAAAAAAAAAAREg/9oACAEBAAE/IaUr3//aAAwDAQACAAMAAAAQUwAA/8QAFBEBAAAAAAAAAAAAAAAAAAAAIP/aAAgBAwEBPxAf/8QAFBEBAAAAAAAAAAAAAAAAAAAAIP/aAAgBAgEBPxAf/8QAGhAAAwEAAwAAAAAAAAAAAAAAAAERMRBBUf/aAAgBAQABPxCppXpLGdc4ioqP/9k='); background-size: cover; display: block;" ></span> <img class="gatsby-resp-image-image" alt="Green palette" title="" src="/static/d39e19ec49d749f1f79dab8ee8138d21/80e3c/image-2-906x1024.jpg" srcset="/static/d39e19ec49d749f1f79dab8ee8138d21/4ec73/image-2-906x1024.jpg 180w, /static/d39e19ec49d749f1f79dab8ee8138d21/158ba/image-2-906x1024.jpg 360w, /static/d39e19ec49d749f1f79dab8ee8138d21/80e3c/image-2-906x1024.jpg 720w, /static/d39e19ec49d749f1f79dab8ee8138d21/a20ae/image-2-906x1024.jpg 906w" sizes="(max-width: 720px) 100vw, 720px" style="width:100%;height:100%;margin:0;vertical-align:middle;position:absolute;top:0;left:0;" loading="lazy" decoding="async" /> </a> </span></p> <p>Great, but there is a caveat, not every green palette is the same. The one MUI provides won’t work with the new primary and secondary colors we created, so we need to add our own custom colors and shades.</p> <p>Usually, the designer provides us with all the necessary shades. But for now, we can use <a href="https://m2.material.io/inline-tools/color/">this helpful tool</a> to autogenerate it from the primary and secondary hex values we added in the first section (<code>#2a9461</code> and <code>#494c7d</code>).</p> <p>Let’s create a new <code>color.js</code> file that exports all the new shades we just generated:</p> <pre class="grvsc-container default-dark" data-language="jsx" data-index="13"><code class="grvsc-code"><span class="grvsc-line"><span class="grvsc-source"><span class="mtk15">export</span><span class="mtk1"> </span><span class="mtk4">const</span><span class="mtk1"> </span><span class="mtk12">green</span><span class="mtk1"> = {</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk7">50</span><span class="mtk12">:</span><span class="mtk1"> </span><span class="mtk8">&quot;#dbece2&quot;</span><span class="mtk1">,</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk7">100</span><span class="mtk12">:</span><span class="mtk1"> </span><span class="mtk8">&quot;#a7d0b8&quot;</span><span class="mtk1">,</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk7">200</span><span class="mtk12">:</span><span class="mtk1"> </span><span class="mtk8">&quot;#6eb18b&quot;</span><span class="mtk1">,</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk7">300</span><span class="mtk12">:</span><span class="mtk1"> </span><span class="mtk8">&quot;#2a9461&quot;</span><span class="mtk1">,</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk7">400</span><span class="mtk12">:</span><span class="mtk1"> </span><span class="mtk8">&quot;#008044&quot;</span><span class="mtk1">,</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk7">500</span><span class="mtk12">:</span><span class="mtk1"> </span><span class="mtk8">&quot;#006c27&quot;</span><span class="mtk1">,</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk7">600</span><span class="mtk12">:</span><span class="mtk1"> </span><span class="mtk8">&quot;#006020&quot;</span><span class="mtk1">,</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk7">700</span><span class="mtk12">:</span><span class="mtk1"> </span><span class="mtk8">&quot;#005116&quot;</span><span class="mtk1">,</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk7">800</span><span class="mtk12">:</span><span class="mtk1"> </span><span class="mtk8">&quot;#00410b&quot;</span><span class="mtk1">,</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk7">900</span><span class="mtk12">:</span><span class="mtk1"> </span><span class="mtk8">&quot;#002700&quot;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1">};</span></span></span> <span class="grvsc-line"><span class="grvsc-source"></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk15">export</span><span class="mtk1"> </span><span class="mtk4">const</span><span class="mtk1"> </span><span class="mtk12">purple</span><span class="mtk1"> = {</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk7">50</span><span class="mtk12">:</span><span class="mtk1"> </span><span class="mtk8">&quot;#e9eaf0&quot;</span><span class="mtk1">,</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk7">100</span><span class="mtk12">:</span><span class="mtk1"> </span><span class="mtk8">&quot;#c7cada&quot;</span><span class="mtk1">,</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk7">200</span><span class="mtk12">:</span><span class="mtk1"> </span><span class="mtk8">&quot;#a3a8c1&quot;</span><span class="mtk1">,</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk7">300</span><span class="mtk12">:</span><span class="mtk1"> </span><span class="mtk8">&quot;#8186a7&quot;</span><span class="mtk1">,</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk7">400</span><span class="mtk12">:</span><span class="mtk1"> </span><span class="mtk8">&quot;#686c95&quot;</span><span class="mtk1">,</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk7">500</span><span class="mtk12">:</span><span class="mtk1"> </span><span class="mtk8">&quot;#505485&quot;</span><span class="mtk1">,</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk7">600</span><span class="mtk12">:</span><span class="mtk1"> </span><span class="mtk8">&quot;#494c7d&quot;</span><span class="mtk1">,</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk7">700</span><span class="mtk12">:</span><span class="mtk1"> </span><span class="mtk8">&quot;#414371&quot;</span><span class="mtk1">,</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk7">800</span><span class="mtk12">:</span><span class="mtk1"> </span><span class="mtk8">&quot;#393964&quot;</span><span class="mtk1">,</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk7">900</span><span class="mtk12">:</span><span class="mtk1"> </span><span class="mtk8">&quot;#2d2a4c&quot;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1">};</span></span></span></code></pre> <p>Now, we can import the new colors and use them in the custom theme:</p> <pre class="grvsc-container default-dark" data-language="jsx" data-index="14"><code class="grvsc-code"><span class="grvsc-line"><span class="grvsc-source"><span class="mtk15">import</span><span class="mtk1"> { </span><span class="mtk12">green</span><span class="mtk1">, </span><span class="mtk12">purple</span><span class="mtk1"> } </span><span class="mtk15">from</span><span class="mtk1"> </span><span class="mtk8">&quot;./colors&quot;</span><span class="mtk1">;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk15">import</span><span class="mtk1"> { </span><span class="mtk12">ThemeProvider</span><span class="mtk1">, </span><span class="mtk12">createTheme</span><span class="mtk1"> } </span><span class="mtk15">from</span><span class="mtk1"> </span><span class="mtk8">&quot;@mui/material/styles&quot;</span><span class="mtk1">;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk4">const</span><span class="mtk1"> </span><span class="mtk12">theme</span><span class="mtk1"> = </span><span class="mtk11">createTheme</span><span class="mtk1">({</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">palette:</span><span class="mtk1"> {</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">primary:</span><span class="mtk1"> {</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">main:</span><span class="mtk1"> </span><span class="mtk12">green</span><span class="mtk1">[</span><span class="mtk7">300</span><span class="mtk1">]</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> },</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">secondary:</span><span class="mtk1"> {</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">main:</span><span class="mtk1"> </span><span class="mtk12">purple</span><span class="mtk1">[</span><span class="mtk7">600</span><span class="mtk1">]</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> },</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">primaryLight:</span><span class="mtk1"> {</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">main:</span><span class="mtk1"> </span><span class="mtk12">green</span><span class="mtk1">[</span><span class="mtk7">50</span><span class="mtk1">]</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> }</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> }</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1">});</span></span></span></code></pre> <h2 id="summary" style="position:relative;"><a href="#summary" aria-label="summary permalink" class="anchor before"><svg aria-hidden="true" focusable="false" height="16" version="1.1" viewBox="0 0 16 16" width="16"><path fill-rule="evenodd" d="M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z"></path></svg></a>Summary</h2> <p>Having a theme brings consistency and minimizes redundancies when styling components. In this article, we learned how to override MUI theme, add a new custom palette, and use custom colors and shades.</p> <p>Lastly, understanding MUI’s system is essential for maximizing usability and enhancing the developer’s experience.</p> <p>Bye for now 👋</p> <style class="grvsc-styles"> .grvsc-container { overflow: auto; position: relative; -webkit-overflow-scrolling: touch; padding-top: 1rem; padding-top: var(--grvsc-padding-top, var(--grvsc-padding-v, 1rem)); padding-bottom: 1rem; padding-bottom: var(--grvsc-padding-bottom, var(--grvsc-padding-v, 1rem)); border-radius: 8px; border-radius: var(--grvsc-border-radius, 8px); font-feature-settings: normal; line-height: 1.4; } .grvsc-code { display: table; } .grvsc-line { display: table-row; box-sizing: border-box; width: 100%; position: relative; } .grvsc-line > * { position: relative; } .grvsc-gutter-pad { display: table-cell; padding-left: 0.75rem; padding-left: calc(var(--grvsc-padding-left, var(--grvsc-padding-h, 1.5rem)) / 2); } .grvsc-gutter { display: table-cell; -webkit-user-select: none; -moz-user-select: none; user-select: none; } .grvsc-gutter::before { content: attr(data-content); } .grvsc-source { display: table-cell; padding-left: 1.5rem; padding-left: var(--grvsc-padding-left, var(--grvsc-padding-h, 1.5rem)); padding-right: 1.5rem; padding-right: var(--grvsc-padding-right, var(--grvsc-padding-h, 1.5rem)); } .grvsc-source:empty::after { content: ' '; -webkit-user-select: none; -moz-user-select: none; user-select: none; } .grvsc-gutter + .grvsc-source { padding-left: 0.75rem; padding-left: calc(var(--grvsc-padding-left, var(--grvsc-padding-h, 1.5rem)) / 2); } /* Line transformer styles */ .grvsc-has-line-highlighting > .grvsc-code > .grvsc-line::before { content: ' '; position: absolute; width: 100%; } .grvsc-line-diff-add::before { background-color: var(--grvsc-line-diff-add-background-color, rgba(0, 255, 60, 0.2)); } .grvsc-line-diff-del::before { background-color: var(--grvsc-line-diff-del-background-color, rgba(255, 0, 20, 0.2)); } .grvsc-line-number { padding: 0 2px; text-align: right; opacity: 0.7; } .default-dark { background-color: #1E1E1E; color: #D4D4D4; } .default-dark .mtk15 { color: #C586C0; } .default-dark .mtk1 { color: #D4D4D4; } .default-dark .mtk12 { color: #9CDCFE; } .default-dark .mtk8 { color: #CE9178; } .default-dark .mtk4 { color: #569CD6; } .default-dark .mtk11 { color: #DCDCAA; } .default-dark .mtk3 { color: #6A9955; } .default-dark .mtk17 { color: #808080; } .default-dark .mtk10 { color: #4EC9B0; } .default-dark .mtk7 { color: #B5CEA8; } .default-dark .grvsc-line-highlighted::before { background-color: var(--grvsc-line-highlighted-background-color, rgba(255, 255, 255, 0.1)); box-shadow: inset var(--grvsc-line-highlighted-border-width, 4px) 0 0 0 var(--grvsc-line-highlighted-border-color, rgba(255, 255, 255, 0.5)); } </style><![CDATA[Customizing disabled button color with Material UI (MUI)]]>https://muhimasri.comcustomizing-disabled-button-colors-with-muihttps://muhimasri.comcustomizing-disabled-button-colors-with-mui<p>Disabling buttons is essential in the UI world as it stops the user from committing an action until specific criteria are met.</p> <p>A disabled button typically has default greyed-out/faded color, but it’s typical to customize it to match our overall design system. So let’s look at different approaches available for us using MUI.</p> <p>If you’d like to skip all the details, below is the complete code example:</p> <div data-codesandbox="mui-disabled-button-colors-h7w5vl?file"> <button>Run Code</button> </div> <p><em>If this is your first time working with MUI, please follow the <a href="https://mui.com/material-ui/getting-started/installation/">installation instructions</a> from the official documentation to get started.</em></p> <h2 id="solution-1-modifying-the-button-class-directly" style="position:relative;"><a href="#solution-1-modifying-the-button-class-directly" aria-label="solution 1 modifying the button class directly permalink" class="anchor before"><svg aria-hidden="true" focusable="false" height="16" version="1.1" viewBox="0 0 16 16" width="16"><path fill-rule="evenodd" d="M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z"></path></svg></a>Solution 1: Modifying the button class directly</h2> <p>Using MUI’s <code>sx</code> prop, we can easily customize the colors of the disabled button:</p> <pre class="grvsc-container grvsc-has-line-highlighting default-dark" data-language="jsx" data-index="0"><code class="grvsc-code"><span class="grvsc-line"><span class="grvsc-source"><span class="mtk15">import</span><span class="mtk1"> </span><span class="mtk12">React</span><span class="mtk1"> </span><span class="mtk15">from</span><span class="mtk1"> </span><span class="mtk8">&quot;react&quot;</span><span class="mtk1">;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk15">import</span><span class="mtk1"> { </span><span class="mtk12">Button</span><span class="mtk1"> } </span><span class="mtk15">from</span><span class="mtk1"> </span><span class="mtk8">&quot;@mui/material&quot;</span><span class="mtk1">;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk15">export</span><span class="mtk1"> </span><span class="mtk15">default</span><span class="mtk1"> </span><span class="mtk4">function</span><span class="mtk1"> </span><span class="mtk11">App</span><span class="mtk1">() {</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk15">return</span><span class="mtk1"> (</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk17">&lt;</span><span class="mtk10">Button</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">disabled</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">variant</span><span class="mtk1">=</span><span class="mtk8">&quot;contained&quot;</span></span></span> <span class="grvsc-line grvsc-line-highlighted"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">sx</span><span class="mtk1">=</span><span class="mtk4">{</span><span class="mtk1">{</span></span></span> <span class="grvsc-line grvsc-line-highlighted"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk8">&quot;&amp;.Mui-disabled&quot;</span><span class="mtk12">:</span><span class="mtk1"> {</span></span></span> <span class="grvsc-line grvsc-line-highlighted"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">background:</span><span class="mtk1"> </span><span class="mtk8">&quot;#eaeaea&quot;</span><span class="mtk1">,</span></span></span> <span class="grvsc-line grvsc-line-highlighted"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">color:</span><span class="mtk1"> </span><span class="mtk8">&quot;#c0c0c0&quot;</span></span></span> <span class="grvsc-line grvsc-line-highlighted"><span class="grvsc-source"><span class="mtk1"> }</span></span></span> <span class="grvsc-line grvsc-line-highlighted"><span class="grvsc-source"><span class="mtk1"> }</span><span class="mtk4">}</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk17">&gt;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> Disabled Button</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk17">&lt;/</span><span class="mtk10">Button</span><span class="mtk17">&gt;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> );</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1">}</span></span></span></code></pre> <p>MUI’s <a href="https://mui.com/material-ui/api/button/">button API</a> can provide us with all the required classes and props to customize a button. In our case, <code>.Mui-disabled</code> is sufficient.</p> <p>Although the solution above looks simple, it can become redundant. As the application grows, we must do this every time we need the disabled button.</p> <h2 id="solution-2-using-mui-theme" style="position:relative;"><a href="#solution-2-using-mui-theme" aria-label="solution 2 using mui theme permalink" class="anchor before"><svg aria-hidden="true" focusable="false" height="16" version="1.1" viewBox="0 0 16 16" width="16"><path fill-rule="evenodd" d="M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z"></path></svg></a>Solution 2: Using MUI Theme</h2> <p>Customizing the global theme will enable the new disabled colors to persist everywhere in the application:</p> <pre class="grvsc-container grvsc-has-line-highlighting default-dark" data-language="jsx" data-index="1"><code class="grvsc-code"><span class="grvsc-line"><span class="grvsc-source"><span class="mtk15">import</span><span class="mtk1"> </span><span class="mtk12">React</span><span class="mtk1"> </span><span class="mtk15">from</span><span class="mtk1"> </span><span class="mtk8">&quot;react&quot;</span><span class="mtk1">;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk15">import</span><span class="mtk1"> { </span><span class="mtk12">Button</span><span class="mtk1"> } </span><span class="mtk15">from</span><span class="mtk1"> </span><span class="mtk8">&quot;@mui/material&quot;</span><span class="mtk1">;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk15">import</span><span class="mtk1"> { </span><span class="mtk12">ThemeProvider</span><span class="mtk1">, </span><span class="mtk12">createTheme</span><span class="mtk1"> } </span><span class="mtk15">from</span><span class="mtk1"> </span><span class="mtk8">&quot;@mui/material/styles&quot;</span><span class="mtk1">;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"></span></span> <span class="grvsc-line grvsc-line-highlighted"><span class="grvsc-source"><span class="mtk4">const</span><span class="mtk1"> </span><span class="mtk12">theme</span><span class="mtk1"> = </span><span class="mtk11">createTheme</span><span class="mtk1">({</span></span></span> <span class="grvsc-line grvsc-line-highlighted"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">components:</span><span class="mtk1"> {</span></span></span> <span class="grvsc-line grvsc-line-highlighted"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">MuiButton:</span><span class="mtk1"> {</span></span></span> <span class="grvsc-line grvsc-line-highlighted"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">styleOverrides:</span><span class="mtk1"> {</span></span></span> <span class="grvsc-line grvsc-line-highlighted"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">root:</span><span class="mtk1"> {</span></span></span> <span class="grvsc-line grvsc-line-highlighted"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk8">&quot;&amp;.Mui-disabled&quot;</span><span class="mtk12">:</span><span class="mtk1"> {</span></span></span> <span class="grvsc-line grvsc-line-highlighted"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">background:</span><span class="mtk1"> </span><span class="mtk8">&quot;#f3f3f3&quot;</span><span class="mtk1">,</span></span></span> <span class="grvsc-line grvsc-line-highlighted"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">color:</span><span class="mtk1"> </span><span class="mtk8">&quot;#dadada&quot;</span></span></span> <span class="grvsc-line grvsc-line-highlighted"><span class="grvsc-source"><span class="mtk1"> }</span></span></span> <span class="grvsc-line grvsc-line-highlighted"><span class="grvsc-source"><span class="mtk1"> }</span></span></span> <span class="grvsc-line grvsc-line-highlighted"><span class="grvsc-source"><span class="mtk1"> }</span></span></span> <span class="grvsc-line grvsc-line-highlighted"><span class="grvsc-source"><span class="mtk1"> }</span></span></span> <span class="grvsc-line grvsc-line-highlighted"><span class="grvsc-source"><span class="mtk1"> }</span></span></span> <span class="grvsc-line grvsc-line-highlighted"><span class="grvsc-source"><span class="mtk1">});</span></span></span> <span class="grvsc-line"><span class="grvsc-source"></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk15">export</span><span class="mtk1"> </span><span class="mtk15">default</span><span class="mtk1"> </span><span class="mtk4">function</span><span class="mtk1"> </span><span class="mtk11">App</span><span class="mtk1">() {</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk15">return</span><span class="mtk1"> (</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk17">&lt;</span><span class="mtk10">ThemeProvider</span><span class="mtk1"> </span><span class="mtk12">theme</span><span class="mtk1">=</span><span class="mtk4">{</span><span class="mtk12">theme</span><span class="mtk4">}</span><span class="mtk17">&gt;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk17">&lt;</span><span class="mtk10">Button</span><span class="mtk1"> </span><span class="mtk12">disabled</span><span class="mtk1"> </span><span class="mtk12">variant</span><span class="mtk1">=</span><span class="mtk8">&quot;contained&quot;</span><span class="mtk17">&gt;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> Disabled Button</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk17">&lt;/</span><span class="mtk10">Button</span><span class="mtk17">&gt;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk17">&lt;/</span><span class="mtk10">ThemeProvider</span><span class="mtk17">&gt;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> );</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1">}</span></span></span> <span class="grvsc-line"><span class="grvsc-source"></span></span></code></pre> <p>We can even take it further and customize the disabled button color based on the selected variant!</p> <pre class="grvsc-container grvsc-has-line-highlighting default-dark" data-language="jsx" data-index="2"><code class="grvsc-code"><span class="grvsc-line"><span class="grvsc-source"><span class="mtk15">import</span><span class="mtk1"> </span><span class="mtk12">React</span><span class="mtk1"> </span><span class="mtk15">from</span><span class="mtk1"> </span><span class="mtk8">&quot;react&quot;</span><span class="mtk1">;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk15">import</span><span class="mtk1"> { </span><span class="mtk12">Button</span><span class="mtk1"> } </span><span class="mtk15">from</span><span class="mtk1"> </span><span class="mtk8">&quot;@mui/material&quot;</span><span class="mtk1">;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk15">import</span><span class="mtk1"> { </span><span class="mtk12">ThemeProvider</span><span class="mtk1">, </span><span class="mtk12">createTheme</span><span class="mtk1"> } </span><span class="mtk15">from</span><span class="mtk1"> </span><span class="mtk8">&quot;@mui/material/styles&quot;</span><span class="mtk1">;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk4">const</span><span class="mtk1"> </span><span class="mtk12">theme</span><span class="mtk1"> = </span><span class="mtk11">createTheme</span><span class="mtk1">({</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">components:</span><span class="mtk1"> {</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">MuiButton:</span><span class="mtk1"> {</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">styleOverrides:</span><span class="mtk1"> {</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk11">root</span><span class="mtk12">:</span><span class="mtk1"> ({ </span><span class="mtk12">ownerState</span><span class="mtk1"> }) </span><span class="mtk4">=&gt;</span><span class="mtk1"> {</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk15">switch</span><span class="mtk1"> (</span><span class="mtk12">ownerState</span><span class="mtk1">.</span><span class="mtk12">variant</span><span class="mtk1">) {</span></span></span> <span class="grvsc-line grvsc-line-highlighted"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk15">case</span><span class="mtk1"> </span><span class="mtk8">&quot;contained&quot;</span><span class="mtk1">:</span></span></span> <span class="grvsc-line grvsc-line-highlighted"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk15">return</span><span class="mtk1"> {</span></span></span> <span class="grvsc-line grvsc-line-highlighted"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk8">&quot;&amp;.Mui-disabled&quot;</span><span class="mtk12">:</span><span class="mtk1"> {</span></span></span> <span class="grvsc-line grvsc-line-highlighted"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">background:</span><span class="mtk1"> </span><span class="mtk8">&quot;#f3f3f3&quot;</span><span class="mtk1">,</span></span></span> <span class="grvsc-line grvsc-line-highlighted"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">color:</span><span class="mtk1"> </span><span class="mtk8">&quot;#dadada&quot;</span></span></span> <span class="grvsc-line grvsc-line-highlighted"><span class="grvsc-source"><span class="mtk1"> }</span></span></span> <span class="grvsc-line grvsc-line-highlighted"><span class="grvsc-source"><span class="mtk1"> };</span></span></span> <span class="grvsc-line grvsc-line-highlighted"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk15">case</span><span class="mtk1"> </span><span class="mtk8">&quot;outlined&quot;</span><span class="mtk1">:</span></span></span> <span class="grvsc-line grvsc-line-highlighted"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk15">return</span><span class="mtk1"> {</span></span></span> <span class="grvsc-line grvsc-line-highlighted"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk8">&quot;&amp;.Mui-disabled&quot;</span><span class="mtk12">:</span><span class="mtk1"> {</span></span></span> <span class="grvsc-line grvsc-line-highlighted"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">background:</span><span class="mtk1"> </span><span class="mtk8">&quot;#e9e9e9&quot;</span><span class="mtk1">,</span></span></span> <span class="grvsc-line grvsc-line-highlighted"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">color:</span><span class="mtk1"> </span><span class="mtk8">&quot;#c7c7c7&quot;</span><span class="mtk1">,</span></span></span> <span class="grvsc-line grvsc-line-highlighted"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">borderColor:</span><span class="mtk1"> </span><span class="mtk8">&quot;#e4e4e4&quot;</span></span></span> <span class="grvsc-line grvsc-line-highlighted"><span class="grvsc-source"><span class="mtk1"> }</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> };</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk15">default</span><span class="mtk1">:</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk15">return</span><span class="mtk1">;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> }</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> }</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> }</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> }</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> }</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1">});</span></span></span> <span class="grvsc-line"><span class="grvsc-source"></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk15">export</span><span class="mtk1"> </span><span class="mtk15">default</span><span class="mtk1"> </span><span class="mtk4">function</span><span class="mtk1"> </span><span class="mtk11">App</span><span class="mtk1">() {</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk15">return</span><span class="mtk1"> (</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk17">&lt;</span><span class="mtk10">ThemeProvider</span><span class="mtk1"> </span><span class="mtk12">theme</span><span class="mtk1">=</span><span class="mtk4">{</span><span class="mtk12">theme</span><span class="mtk4">}</span><span class="mtk17">&gt;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk17">&lt;</span><span class="mtk10">Button</span><span class="mtk1"> </span><span class="mtk12">disabled</span><span class="mtk1"> </span><span class="mtk12">variant</span><span class="mtk1">=</span><span class="mtk8">&quot;contained&quot;</span><span class="mtk17">&gt;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> Disabled Contained Button</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk17">&lt;/</span><span class="mtk10">Button</span><span class="mtk17">&gt;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk17">&lt;</span><span class="mtk10">Button</span><span class="mtk1"> </span><span class="mtk12">disabled</span><span class="mtk1"> </span><span class="mtk12">variant</span><span class="mtk1">=</span><span class="mtk8">&quot;outlined&quot;</span><span class="mtk17">&gt;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> Disabled Outlined Button</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk17">&lt;/</span><span class="mtk10">Button</span><span class="mtk17">&gt;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk17">&lt;/</span><span class="mtk10">ThemeProvider</span><span class="mtk17">&gt;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> );</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1">}</span></span></span> <span class="grvsc-line"><span class="grvsc-source"></span></span></code></pre> <h2 id="solution-3-creating-a-styled-component" style="position:relative;"><a href="#solution-3-creating-a-styled-component" aria-label="solution 3 creating a styled component permalink" class="anchor before"><svg aria-hidden="true" focusable="false" height="16" version="1.1" viewBox="0 0 16 16" width="16"><path fill-rule="evenodd" d="M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z"></path></svg></a>Solution 3: Creating a Styled Component</h2> <p>Styled Components is an excellent option for isolating styles in a custom component while still inheriting all the button’s features.</p> <p>Below, we can change the disabled button color for three different variants (default, outlined, and contained):</p> <pre class="grvsc-container default-dark" data-language="jsx" data-index="3"><code class="grvsc-code"><span class="grvsc-line"><span class="grvsc-source"><span class="mtk15">import</span><span class="mtk1"> </span><span class="mtk12">React</span><span class="mtk1"> </span><span class="mtk15">from</span><span class="mtk1"> </span><span class="mtk8">&quot;react&quot;</span><span class="mtk1">;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk15">import</span><span class="mtk1"> { </span><span class="mtk12">Button</span><span class="mtk1"> </span><span class="mtk15">as</span><span class="mtk1"> </span><span class="mtk12">MuiButton</span><span class="mtk1"> } </span><span class="mtk15">from</span><span class="mtk1"> </span><span class="mtk8">&quot;@mui/material&quot;</span><span class="mtk1">;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk15">import</span><span class="mtk1"> { </span><span class="mtk12">styled</span><span class="mtk1"> } </span><span class="mtk15">from</span><span class="mtk1"> </span><span class="mtk8">&quot;@mui/system&quot;</span><span class="mtk1">;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk4">const</span><span class="mtk1"> </span><span class="mtk12">Button</span><span class="mtk1"> = </span><span class="mtk11">styled</span><span class="mtk1">(</span><span class="mtk12">MuiButton</span><span class="mtk1">)({</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk8">&quot;&amp;.Mui-disabled&quot;</span><span class="mtk12">:</span><span class="mtk1"> {</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">color:</span><span class="mtk1"> </span><span class="mtk8">&quot;#c0c0c0&quot;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> },</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk8">&quot;&amp;.MuiButton-outlined.Mui-disabled&quot;</span><span class="mtk12">:</span><span class="mtk1"> {</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">background:</span><span class="mtk1"> </span><span class="mtk8">&quot;#e4e4e4&quot;</span><span class="mtk1">,</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">color:</span><span class="mtk1"> </span><span class="mtk8">&quot;#b7babf&quot;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> },</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk8">&quot;&amp;.MuiButton-contained.Mui-disabled&quot;</span><span class="mtk12">:</span><span class="mtk1"> {</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">background:</span><span class="mtk1"> </span><span class="mtk8">&quot;#eaeaea&quot;</span><span class="mtk1">,</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">color:</span><span class="mtk1"> </span><span class="mtk8">&quot;#c0c0c0&quot;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> }</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1">});</span></span></span> <span class="grvsc-line"><span class="grvsc-source"></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk15">export</span><span class="mtk1"> </span><span class="mtk15">default</span><span class="mtk1"> </span><span class="mtk4">function</span><span class="mtk1"> </span><span class="mtk11">App</span><span class="mtk1">() {</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk15">return</span><span class="mtk1"> (</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk17">&lt;</span><span class="mtk10">Button</span><span class="mtk1"> </span><span class="mtk12">disabled</span><span class="mtk1"> </span><span class="mtk12">variant</span><span class="mtk1">=</span><span class="mtk8">&quot;outlined&quot;</span><span class="mtk17">&gt;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> Disabled Outlined Button</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk17">&lt;/</span><span class="mtk10">Button</span><span class="mtk17">&gt;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> );</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1">}</span></span></span></code></pre> <p>And, of course, we can reuse the component anywhere in the project without re-writing the styles again.</p> <h2 id="summary" style="position:relative;"><a href="#summary" aria-label="summary permalink" class="anchor before"><svg aria-hidden="true" focusable="false" height="16" version="1.1" viewBox="0 0 16 16" width="16"><path fill-rule="evenodd" d="M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z"></path></svg></a>Summary</h2> <p>Using <code>sx</code> is very useful for one-time styling but if we’d like to apply it globally, then using MUI theme is a more scalable solution. Styled Components is a better option for more custom and advanced use-case.</p> <p>Bye for now 👋</p> <style class="grvsc-styles"> .grvsc-container { overflow: auto; position: relative; -webkit-overflow-scrolling: touch; padding-top: 1rem; padding-top: var(--grvsc-padding-top, var(--grvsc-padding-v, 1rem)); padding-bottom: 1rem; padding-bottom: var(--grvsc-padding-bottom, var(--grvsc-padding-v, 1rem)); border-radius: 8px; border-radius: var(--grvsc-border-radius, 8px); font-feature-settings: normal; line-height: 1.4; } .grvsc-code { display: table; } .grvsc-line { display: table-row; box-sizing: border-box; width: 100%; position: relative; } .grvsc-line > * { position: relative; } .grvsc-gutter-pad { display: table-cell; padding-left: 0.75rem; padding-left: calc(var(--grvsc-padding-left, var(--grvsc-padding-h, 1.5rem)) / 2); } .grvsc-gutter { display: table-cell; -webkit-user-select: none; -moz-user-select: none; user-select: none; } .grvsc-gutter::before { content: attr(data-content); } .grvsc-source { display: table-cell; padding-left: 1.5rem; padding-left: var(--grvsc-padding-left, var(--grvsc-padding-h, 1.5rem)); padding-right: 1.5rem; padding-right: var(--grvsc-padding-right, var(--grvsc-padding-h, 1.5rem)); } .grvsc-source:empty::after { content: ' '; -webkit-user-select: none; -moz-user-select: none; user-select: none; } .grvsc-gutter + .grvsc-source { padding-left: 0.75rem; padding-left: calc(var(--grvsc-padding-left, var(--grvsc-padding-h, 1.5rem)) / 2); } /* Line transformer styles */ .grvsc-has-line-highlighting > .grvsc-code > .grvsc-line::before { content: ' '; position: absolute; width: 100%; } .grvsc-line-diff-add::before { background-color: var(--grvsc-line-diff-add-background-color, rgba(0, 255, 60, 0.2)); } .grvsc-line-diff-del::before { background-color: var(--grvsc-line-diff-del-background-color, rgba(255, 0, 20, 0.2)); } .grvsc-line-number { padding: 0 2px; text-align: right; opacity: 0.7; } .default-dark { background-color: #1E1E1E; color: #D4D4D4; } .default-dark .mtk15 { color: #C586C0; } .default-dark .mtk1 { color: #D4D4D4; } .default-dark .mtk12 { color: #9CDCFE; } .default-dark .mtk8 { color: #CE9178; } .default-dark .mtk4 { color: #569CD6; } .default-dark .mtk11 { color: #DCDCAA; } .default-dark .mtk17 { color: #808080; } .default-dark .mtk10 { color: #4EC9B0; } .default-dark .grvsc-line-highlighted::before { background-color: var(--grvsc-line-highlighted-background-color, rgba(255, 255, 255, 0.1)); box-shadow: inset var(--grvsc-line-highlighted-border-width, 4px) 0 0 0 var(--grvsc-line-highlighted-border-color, rgba(255, 255, 255, 0.5)); } </style><![CDATA[Creating a Button Link with Material UI (MUI)]]>https://muhimasri.comhow-to-create-button-link-with-muihttps://muhimasri.comhow-to-create-button-link-with-mui<p>In many scenarios, we often want a button to behave like a link but still look like a button, especially when we need to change the page or use other Anchor element properties.</p> <p>Luckily, we can easily do this with the MUI Button component while keeping all the existing styles and functionality intact!</p> <p>If you’d like to skip all the details, below is the complete code example:</p> <div data-stackblitz="mui-button-link"> <button>Run Code</button> </div> <p><em>If this is your first time working with MUI, please follow the <a href="https://mui.com/material-ui/getting-started/installation/">installation instructions</a> from the official documentation to get started.</em></p> <h2 id="button-link-with-an-href-tag" style="position:relative;"><a href="#button-link-with-an-href-tag" aria-label="button link with an href tag permalink" class="anchor before"><svg aria-hidden="true" focusable="false" height="16" version="1.1" viewBox="0 0 16 16" width="16"><path fill-rule="evenodd" d="M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z"></path></svg></a>Button Link with an href tag</h2> <p>Adding the <code>href</code> prop to the Button component will automatically change it to a Link component, an Anchor tag element.</p> <pre class="grvsc-container default-dark" data-language="jsx" data-index="0"><code class="grvsc-code"><span class="grvsc-line"><span class="grvsc-source"><span class="mtk15">import</span><span class="mtk1"> </span><span class="mtk4">*</span><span class="mtk1"> </span><span class="mtk15">as</span><span class="mtk1"> </span><span class="mtk12">React</span><span class="mtk1"> </span><span class="mtk15">from</span><span class="mtk1"> </span><span class="mtk8">&#39;react&#39;</span><span class="mtk1">;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk15">import</span><span class="mtk1"> { </span><span class="mtk12">Button</span><span class="mtk1"> } </span><span class="mtk15">from</span><span class="mtk1"> </span><span class="mtk8">&#39;@mui/material&#39;</span><span class="mtk1">;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk15">export</span><span class="mtk1"> </span><span class="mtk15">default</span><span class="mtk1"> </span><span class="mtk4">function</span><span class="mtk1"> </span><span class="mtk11">App</span><span class="mtk1">() {</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk15">return</span><span class="mtk1"> </span><span class="mtk17">&lt;</span><span class="mtk10">Button</span><span class="mtk1"> </span><span class="mtk12">href</span><span class="mtk1">=</span><span class="mtk8">&quot;/new-page&quot;</span><span class="mtk17">&gt;</span><span class="mtk1">MUI Link Button</span><span class="mtk17">&lt;/</span><span class="mtk10">Button</span><span class="mtk17">&gt;</span><span class="mtk1">;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1">}</span></span></span></code></pre> <p>The cool part is that MUI will allow us to use both the Button’s and Link’s API. So we can add a <code>target</code> prop that belongs to the Link component and still use the Button’s <code>variant</code> prop, like “outlined” or “contained”.</p> <pre class="grvsc-container default-dark" data-language="jsx" data-index="1"><code class="grvsc-code"><span class="grvsc-line"><span class="grvsc-source"><span class="mtk15">import</span><span class="mtk1"> </span><span class="mtk4">*</span><span class="mtk1"> </span><span class="mtk15">as</span><span class="mtk1"> </span><span class="mtk12">React</span><span class="mtk1"> </span><span class="mtk15">from</span><span class="mtk1"> </span><span class="mtk8">&#39;react&#39;</span><span class="mtk1">;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk15">import</span><span class="mtk1"> { </span><span class="mtk12">Button</span><span class="mtk1"> } </span><span class="mtk15">from</span><span class="mtk1"> </span><span class="mtk8">&#39;@mui/material&#39;</span><span class="mtk1">;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk15">export</span><span class="mtk1"> </span><span class="mtk15">default</span><span class="mtk1"> </span><span class="mtk4">function</span><span class="mtk1"> </span><span class="mtk11">App</span><span class="mtk1">() {</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk15">return</span><span class="mtk1"> </span><span class="mtk17">&lt;</span><span class="mtk10">Button</span><span class="mtk1"> </span><span class="mtk12">href</span><span class="mtk1">=</span><span class="mtk8">&quot;/new-page&quot;</span><span class="mtk1"> </span><span class="mtk12">target</span><span class="mtk1">=</span><span class="mtk8">&quot;_blank&quot;</span><span class="mtk1"> </span><span class="mtk12">variant</span><span class="mtk1">=</span><span class="mtk8">&quot;outlined&quot;</span><span class="mtk17">&gt;</span><span class="mtk1">MUI Link Button</span><span class="mtk17">&lt;/</span><span class="mtk10">Button</span><span class="mtk17">&gt;</span><span class="mtk1">;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1">}</span></span></span></code></pre> <h2 id="button-link-with-a-custom-component" style="position:relative;"><a href="#button-link-with-a-custom-component" aria-label="button link with a custom component permalink" class="anchor before"><svg aria-hidden="true" focusable="false" height="16" version="1.1" viewBox="0 0 16 16" width="16"><path fill-rule="evenodd" d="M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z"></path></svg></a>Button Link with a custom component</h2> <p>If we’d like to use a third-party Link component or use our custom one, we can pass it in the <code>component</code> prop as follows:</p> <pre class="grvsc-container default-dark" data-language="jsx" data-index="2"><code class="grvsc-code"><span class="grvsc-line"><span class="grvsc-source"><span class="mtk15">import</span><span class="mtk1"> </span><span class="mtk4">*</span><span class="mtk1"> </span><span class="mtk15">as</span><span class="mtk1"> </span><span class="mtk12">React</span><span class="mtk1"> </span><span class="mtk15">from</span><span class="mtk1"> </span><span class="mtk8">&#39;react&#39;</span><span class="mtk1">;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk15">import</span><span class="mtk1"> { </span><span class="mtk12">Button</span><span class="mtk1">, </span><span class="mtk12">Stack</span><span class="mtk1"> } </span><span class="mtk15">from</span><span class="mtk1"> </span><span class="mtk8">&#39;@mui/material&#39;</span><span class="mtk1">;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk15">export</span><span class="mtk1"> </span><span class="mtk15">default</span><span class="mtk1"> </span><span class="mtk4">function</span><span class="mtk1"> </span><span class="mtk11">App</span><span class="mtk1">() {</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk15">return</span><span class="mtk1"> (</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk17">&lt;</span><span class="mtk10">Button</span><span class="mtk1"> </span><span class="mtk12">href</span><span class="mtk1">=</span><span class="mtk8">&quot;/new-page&quot;</span><span class="mtk1"> </span><span class="mtk12">component</span><span class="mtk1">=</span><span class="mtk4">{</span><span class="mtk12">CustomLink</span><span class="mtk4">}</span><span class="mtk1"> </span><span class="mtk12">variant</span><span class="mtk1">=</span><span class="mtk8">&quot;outlined&quot;</span><span class="mtk17">&gt;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> Custom Link Button</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk17">&lt;/</span><span class="mtk10">Button</span><span class="mtk17">&gt;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> );</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1">}</span></span></span> <span class="grvsc-line"><span class="grvsc-source"></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk4">const</span><span class="mtk1"> </span><span class="mtk11">CustomLink</span><span class="mtk1"> = (</span><span class="mtk12">props</span><span class="mtk1">) </span><span class="mtk4">=&gt;</span><span class="mtk1"> </span><span class="mtk17">&lt;</span><span class="mtk4">a</span><span class="mtk1"> </span><span class="mtk4">{</span><span class="mtk1">...</span><span class="mtk12">props</span><span class="mtk4">}</span><span class="mtk17">&gt;</span><span class="mtk4">{</span><span class="mtk12">props</span><span class="mtk1">.</span><span class="mtk12">children</span><span class="mtk4">}</span><span class="mtk17">&lt;/</span><span class="mtk4">a</span><span class="mtk17">&gt;</span><span class="mtk1">;</span></span></span></code></pre> <h2 id="button-link-with-react-router" style="position:relative;"><a href="#button-link-with-react-router" aria-label="button link with react router permalink" class="anchor before"><svg aria-hidden="true" focusable="false" height="16" version="1.1" viewBox="0 0 16 16" width="16"><path fill-rule="evenodd" d="M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z"></path></svg></a>Button Link with React Router</h2> <p>In most React applications, we will likely use React Router to navigate between different pages. But because React Router provides a custom Link component, we can’t simply add an <code>href</code> tag if it’s not an MUI component.</p> <p>To make it work with the router, we will follow the previous approach and add it as a custom component in MUI Button:</p> <pre class="grvsc-container default-dark" data-language="jsx" data-index="3"><code class="grvsc-code"><span class="grvsc-line"><span class="grvsc-source"><span class="mtk15">import</span><span class="mtk1"> </span><span class="mtk4">*</span><span class="mtk1"> </span><span class="mtk15">as</span><span class="mtk1"> </span><span class="mtk12">React</span><span class="mtk1"> </span><span class="mtk15">from</span><span class="mtk1"> </span><span class="mtk8">&#39;react&#39;</span><span class="mtk1">;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk15">import</span><span class="mtk1"> { </span><span class="mtk12">Link</span><span class="mtk1"> } </span><span class="mtk15">from</span><span class="mtk1"> </span><span class="mtk8">&#39;react-router-dom&#39;</span><span class="mtk1">;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk15">export</span><span class="mtk1"> </span><span class="mtk15">default</span><span class="mtk1"> </span><span class="mtk4">function</span><span class="mtk1"> </span><span class="mtk11">App</span><span class="mtk1">() {</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk15">return</span><span class="mtk1"> (</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk17">&lt;</span><span class="mtk10">Button</span><span class="mtk1"> </span><span class="mtk12">component</span><span class="mtk1">=</span><span class="mtk4">{</span><span class="mtk12">Link</span><span class="mtk4">}</span><span class="mtk1"> </span><span class="mtk12">to</span><span class="mtk1">=</span><span class="mtk8">&quot;/new-page&quot;</span><span class="mtk17">&gt;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> Router Link</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk17">&lt;/</span><span class="mtk10">Button</span><span class="mtk17">&gt;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> );</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1">}</span></span></span></code></pre> <h2 id="button-link-with-an-icon" style="position:relative;"><a href="#button-link-with-an-icon" aria-label="button link with an icon permalink" class="anchor before"><svg aria-hidden="true" focusable="false" height="16" version="1.1" viewBox="0 0 16 16" width="16"><path fill-rule="evenodd" d="M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z"></path></svg></a>Button Link with an Icon</h2> <p>Creating an icon button as a Link is very useful as well. For example, we can have social links as buttons that need to redirect to a new page or use the <code>mailto</code> prop to open the default email.</p> <p>Similar to the first approach, all we need is to add the <code>href</code> tag to the <code>IconButton</code> component:</p> <pre class="grvsc-container default-dark" data-language="jsx" data-index="4"><code class="grvsc-code"><span class="grvsc-line"><span class="grvsc-source"><span class="mtk15">import</span><span class="mtk1"> </span><span class="mtk4">*</span><span class="mtk1"> </span><span class="mtk15">as</span><span class="mtk1"> </span><span class="mtk12">React</span><span class="mtk1"> </span><span class="mtk15">from</span><span class="mtk1"> </span><span class="mtk8">&#39;react&#39;</span><span class="mtk1">;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk15">import</span><span class="mtk1"> { </span><span class="mtk12">IconButton</span><span class="mtk1"> } </span><span class="mtk15">from</span><span class="mtk1"> </span><span class="mtk8">&#39;@mui/material&#39;</span><span class="mtk1">;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk15">import</span><span class="mtk1"> </span><span class="mtk12">GitHubIcon</span><span class="mtk1"> </span><span class="mtk15">from</span><span class="mtk1"> </span><span class="mtk8">&#39;@mui/icons-material/GitHub&#39;</span><span class="mtk1">;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk15">import</span><span class="mtk1"> </span><span class="mtk12">EmailIcon</span><span class="mtk1"> </span><span class="mtk15">from</span><span class="mtk1"> </span><span class="mtk8">&#39;@mui/icons-material/Email&#39;</span><span class="mtk1">;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk15">export</span><span class="mtk1"> </span><span class="mtk15">default</span><span class="mtk1"> </span><span class="mtk4">function</span><span class="mtk1"> </span><span class="mtk11">App</span><span class="mtk1">() {</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk15">return</span><span class="mtk1"> (</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk17">&lt;</span><span class="mtk4">div</span><span class="mtk17">&gt;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk17">&lt;</span><span class="mtk10">IconButton</span><span class="mtk1"> </span><span class="mtk12">href</span><span class="mtk1">=</span><span class="mtk8">&quot;https://github.com/muhimasri&quot;</span><span class="mtk1"> </span><span class="mtk12">target</span><span class="mtk1">=</span><span class="mtk8">&quot;_blank&quot;</span><span class="mtk17">&gt;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk17">&lt;</span><span class="mtk10">GitHubIcon</span><span class="mtk1"> </span><span class="mtk17">/&gt;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk17">&lt;/</span><span class="mtk10">IconButton</span><span class="mtk17">&gt;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk17">&lt;</span><span class="mtk10">IconButton</span><span class="mtk1"> </span><span class="mtk12">href</span><span class="mtk1">=</span><span class="mtk8">&quot;mailto:[email protected]&quot;</span><span class="mtk17">&gt;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk17">&lt;</span><span class="mtk10">EmailIcon</span><span class="mtk1"> </span><span class="mtk17">/&gt;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk17">&lt;/</span><span class="mtk10">IconButton</span><span class="mtk17">&gt;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk17">&lt;/</span><span class="mtk4">div</span><span class="mtk17">&gt;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> );</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1">}</span></span></span></code></pre> <p>Alternatively, we can use a normal button with an icon:</p> <pre class="grvsc-container default-dark" data-language="jsx" data-index="5"><code class="grvsc-code"><span class="grvsc-line"><span class="grvsc-source"><span class="mtk17">&lt;</span><span class="mtk10">Button</span><span class="mtk1"> </span><span class="mtk12">href</span><span class="mtk1">=</span><span class="mtk8">&quot;/new-page&quot;</span><span class="mtk1"> </span><span class="mtk12">variant</span><span class="mtk1">=</span><span class="mtk8">&quot;outlined&quot;</span><span class="mtk1"> </span><span class="mtk12">startIcon</span><span class="mtk1">=</span><span class="mtk4">{</span><span class="mtk17">&lt;</span><span class="mtk10">LaunchIcon</span><span class="mtk1"> </span><span class="mtk17">/&gt;</span><span class="mtk4">}</span><span class="mtk17">&gt;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> Icon Button</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk17">&lt;/</span><span class="mtk10">Button</span><span class="mtk17">&gt;</span></span></span></code></pre> <h2 id="summary" style="position:relative;"><a href="#summary" aria-label="summary permalink" class="anchor before"><svg aria-hidden="true" focusable="false" height="16" version="1.1" viewBox="0 0 16 16" width="16"><path fill-rule="evenodd" d="M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z"></path></svg></a>Summary</h2> <p>Most MUI components support the <code>component</code> prop, which replaces the HTML element with a more suitable one. Still, we have a simplified approach with a Button component by only adding the <code>href</code> tag. It will transform into a Button Link automatically.</p> <p>Bye for now 👋</p> <style class="grvsc-styles"> .grvsc-container { overflow: auto; position: relative; -webkit-overflow-scrolling: touch; padding-top: 1rem; padding-top: var(--grvsc-padding-top, var(--grvsc-padding-v, 1rem)); padding-bottom: 1rem; padding-bottom: var(--grvsc-padding-bottom, var(--grvsc-padding-v, 1rem)); border-radius: 8px; border-radius: var(--grvsc-border-radius, 8px); font-feature-settings: normal; line-height: 1.4; } .grvsc-code { display: table; } .grvsc-line { display: table-row; box-sizing: border-box; width: 100%; position: relative; } .grvsc-line > * { position: relative; } .grvsc-gutter-pad { display: table-cell; padding-left: 0.75rem; padding-left: calc(var(--grvsc-padding-left, var(--grvsc-padding-h, 1.5rem)) / 2); } .grvsc-gutter { display: table-cell; -webkit-user-select: none; -moz-user-select: none; user-select: none; } .grvsc-gutter::before { content: attr(data-content); } .grvsc-source { display: table-cell; padding-left: 1.5rem; padding-left: var(--grvsc-padding-left, var(--grvsc-padding-h, 1.5rem)); padding-right: 1.5rem; padding-right: var(--grvsc-padding-right, var(--grvsc-padding-h, 1.5rem)); } .grvsc-source:empty::after { content: ' '; -webkit-user-select: none; -moz-user-select: none; user-select: none; } .grvsc-gutter + .grvsc-source { padding-left: 0.75rem; padding-left: calc(var(--grvsc-padding-left, var(--grvsc-padding-h, 1.5rem)) / 2); } /* Line transformer styles */ .grvsc-has-line-highlighting > .grvsc-code > .grvsc-line::before { content: ' '; position: absolute; width: 100%; } .grvsc-line-diff-add::before { background-color: var(--grvsc-line-diff-add-background-color, rgba(0, 255, 60, 0.2)); } .grvsc-line-diff-del::before { background-color: var(--grvsc-line-diff-del-background-color, rgba(255, 0, 20, 0.2)); } .grvsc-line-number { padding: 0 2px; text-align: right; opacity: 0.7; } .default-dark { background-color: #1E1E1E; color: #D4D4D4; } .default-dark .mtk15 { color: #C586C0; } .default-dark .mtk1 { color: #D4D4D4; } .default-dark .mtk4 { color: #569CD6; } .default-dark .mtk12 { color: #9CDCFE; } .default-dark .mtk8 { color: #CE9178; } .default-dark .mtk11 { color: #DCDCAA; } .default-dark .mtk17 { color: #808080; } .default-dark .mtk10 { color: #4EC9B0; } .default-dark .grvsc-line-highlighted::before { background-color: var(--grvsc-line-highlighted-background-color, rgba(255, 255, 255, 0.1)); box-shadow: inset var(--grvsc-line-highlighted-border-width, 4px) 0 0 0 var(--grvsc-line-highlighted-border-color, rgba(255, 255, 255, 0.5)); } </style><![CDATA[MUI Container: How to Customize and Override Width]]>https://muhimasri.comhow-to-override-material-ui-container-widthhttps://muhimasri.comhow-to-override-material-ui-container-width<p>The MUI Container is a fundamental layout component in Material UI. It is designed to manage the width of the content it encloses, ensuring it doesn’t span the entire viewport width but is centered horizontally. This functionality is crucial for creating visually appealing layouts by preventing content from stretching too wide on large screens, thus maintaining a consistent and aesthetically pleasing appearance.</p> <p>Throughout this tutorial, we will explore different methods of implementing MUI Containers, highlighting the importance of each approach and how they contribute to effective layout design. This will include examining the various properties available with the <code>Container</code> component, such as <code>maxWidth</code> and fixed, to tailor the Container’s behavior to specific design needs.</p> <h2 id="fluid-container" style="position:relative;"><a href="#fluid-container" aria-label="fluid container permalink" class="anchor before"><svg aria-hidden="true" focusable="false" height="16" version="1.1" viewBox="0 0 16 16" width="16"><path fill-rule="evenodd" d="M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z"></path></svg></a>Fluid Container</h2> <p>By default, the MUI <code>Container</code> component is fluid, automatically adjusting its width to match the viewport with a default <code>maxWidth</code> limit of <code>1200px</code>.</p> <pre class="grvsc-container default-dark" data-language="jsx" data-index="0"><code class="grvsc-code"><span class="grvsc-line"><span class="grvsc-source"><span class="mtk15">import</span><span class="mtk1"> </span><span class="mtk12">React</span><span class="mtk1"> </span><span class="mtk15">from</span><span class="mtk1"> </span><span class="mtk8">&quot;react&quot;</span><span class="mtk1">;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk15">import</span><span class="mtk1"> </span><span class="mtk12">Container</span><span class="mtk1"> </span><span class="mtk15">from</span><span class="mtk1"> </span><span class="mtk8">&quot;@mui/material/Container&quot;</span><span class="mtk1">;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk15">import</span><span class="mtk1"> </span><span class="mtk12">Box</span><span class="mtk1"> </span><span class="mtk15">from</span><span class="mtk1"> </span><span class="mtk8">&quot;@mui/material/Box&quot;</span><span class="mtk1">;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk15">export</span><span class="mtk1"> </span><span class="mtk15">default</span><span class="mtk1"> </span><span class="mtk4">function</span><span class="mtk1"> </span><span class="mtk11">FluidContainer</span><span class="mtk1">() {</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk15">return</span><span class="mtk1"> (</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk17">&lt;</span><span class="mtk10">Container</span><span class="mtk17">&gt;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk17">&lt;</span><span class="mtk10">Box</span><span class="mtk1"> </span><span class="mtk12">sx</span><span class="mtk1">=</span><span class="mtk4">{</span><span class="mtk1">{ </span><span class="mtk12">bgcolor:</span><span class="mtk1"> </span><span class="mtk8">&quot;#cfe8fc&quot;</span><span class="mtk1">, </span><span class="mtk12">height:</span><span class="mtk1"> </span><span class="mtk8">&quot;100vh&quot;</span><span class="mtk1"> }</span><span class="mtk4">}</span><span class="mtk1"> </span><span class="mtk17">/&gt;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk17">&lt;/</span><span class="mtk10">Container</span><span class="mtk17">&gt;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> );</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1">}</span></span></span></code></pre> <video width="720" height="400" autoplay loop muted playsinline preload="none"> <source src="/77bcee20f25df983b3dc370a2fa235cb/FluidContainer.mp4" type="video/mp4"> </video> <p>In this example, as the viewport size increases, the content will be centered and won’t stretch beyond the default max width of <code>1200px</code> (the <code>lg</code> breakpoint). And as it decreases below <code>1200px</code>, the content will take up the entire width of the viewport.</p> <p>MUI provides several <code>maxWidth</code> options, allowing for granular control over how the content scales with the screen size.</p> <ul> <li><code>xs</code> - Extra small devices (phones, less than 600px)</li> <li><code>sm</code> - Small devices (tablets, 600px and up)</li> <li><code>md</code> - Medium devices (desktops, 960px and up)</li> <li><code>lg</code> - Large devices (large desktops, 1200px and up)</li> <li><code>xl</code> - Extra large devices (extra large desktops, 1536px and up)</li> </ul> <p>So if the default <code>maxWidth</code> of <code>1200px</code> doesn’t suit our design, we can easily adjust it to match the specific requirements:</p> <pre class="grvsc-container default-dark" data-language="jsx" data-index="1"><code class="grvsc-code"><span class="grvsc-line"><span class="grvsc-source"><span class="mtk15">import</span><span class="mtk1"> </span><span class="mtk12">React</span><span class="mtk1"> </span><span class="mtk15">from</span><span class="mtk1"> </span><span class="mtk8">&quot;react&quot;</span><span class="mtk1">;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk15">import</span><span class="mtk1"> </span><span class="mtk12">Container</span><span class="mtk1"> </span><span class="mtk15">from</span><span class="mtk1"> </span><span class="mtk8">&quot;@mui/material/Container&quot;</span><span class="mtk1">;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk15">import</span><span class="mtk1"> </span><span class="mtk12">Box</span><span class="mtk1"> </span><span class="mtk15">from</span><span class="mtk1"> </span><span class="mtk8">&quot;@mui/material/Box&quot;</span><span class="mtk1">;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk15">export</span><span class="mtk1"> </span><span class="mtk15">default</span><span class="mtk1"> </span><span class="mtk4">function</span><span class="mtk1"> </span><span class="mtk11">CustomMaxWidthContainer</span><span class="mtk1">() {</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk15">return</span><span class="mtk1"> (</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk17">&lt;</span><span class="mtk10">Container</span><span class="mtk1"> </span><span class="mtk12">maxWidth</span><span class="mtk1">=</span><span class="mtk8">&quot;md&quot;</span><span class="mtk17">&gt;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk17">&lt;</span><span class="mtk10">Box</span><span class="mtk1"> </span><span class="mtk12">sx</span><span class="mtk1">=</span><span class="mtk4">{</span><span class="mtk1">{ </span><span class="mtk12">bgcolor:</span><span class="mtk1"> </span><span class="mtk8">&quot;#cfe8fc&quot;</span><span class="mtk1">, </span><span class="mtk12">height:</span><span class="mtk1"> </span><span class="mtk8">&quot;100vh&quot;</span><span class="mtk1"> }</span><span class="mtk4">}</span><span class="mtk1"> </span><span class="mtk17">/&gt;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk17">&lt;/</span><span class="mtk10">Container</span><span class="mtk17">&gt;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> );</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1">}</span></span></span></code></pre> <video width="720" height="400" autoplay loop muted playsinline preload="none"> <source src="/5e44669f3f59588834210318ea11d74c/CustomMaxWidthContainer.mp4" type="video/mp4"> </video> <p>Now, the <code>Container</code> component will stop growing beyond the <code>960px</code> width, which is the <code>md</code> breakpoint.</p> <h2 id="fixed-container" style="position:relative;"><a href="#fixed-container" aria-label="fixed container permalink" class="anchor before"><svg aria-hidden="true" focusable="false" height="16" version="1.1" viewBox="0 0 16 16" width="16"><path fill-rule="evenodd" d="M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z"></path></svg></a>Fixed Container</h2> <p>A fixed container in MUI maintains a constant width regardless of the viewport size, only adjusting its width when it crosses a predefined breakpoint (like <code>md</code>, <code>sm</code>, etc.). This behavior ensures that the Container’s width remains stable and does not shrink or expand with the window resizing, providing a consistent layout experience across different screen sizes.</p> <pre class="grvsc-container default-dark" data-language="jsx" data-index="2"><code class="grvsc-code"><span class="grvsc-line"><span class="grvsc-source"><span class="mtk15">import</span><span class="mtk1"> </span><span class="mtk12">React</span><span class="mtk1"> </span><span class="mtk15">from</span><span class="mtk1"> </span><span class="mtk8">&quot;react&quot;</span><span class="mtk1">;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk15">import</span><span class="mtk1"> </span><span class="mtk12">Container</span><span class="mtk1"> </span><span class="mtk15">from</span><span class="mtk1"> </span><span class="mtk8">&quot;@mui/material/Container&quot;</span><span class="mtk1">;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk15">import</span><span class="mtk1"> </span><span class="mtk12">Box</span><span class="mtk1"> </span><span class="mtk15">from</span><span class="mtk1"> </span><span class="mtk8">&quot;@mui/material/Box&quot;</span><span class="mtk1">;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk15">export</span><span class="mtk1"> </span><span class="mtk15">default</span><span class="mtk1"> </span><span class="mtk4">function</span><span class="mtk1"> </span><span class="mtk11">FixedContainer</span><span class="mtk1">() {</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk15">return</span><span class="mtk1"> (</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk17">&lt;</span><span class="mtk10">Container</span><span class="mtk1"> </span><span class="mtk12">fixed</span><span class="mtk17">&gt;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk17">&lt;</span><span class="mtk10">Box</span><span class="mtk1"> </span><span class="mtk12">sx</span><span class="mtk1">=</span><span class="mtk4">{</span><span class="mtk1">{ </span><span class="mtk12">bgcolor:</span><span class="mtk1"> </span><span class="mtk8">&quot;#cfe8fc&quot;</span><span class="mtk1">, </span><span class="mtk12">height:</span><span class="mtk1"> </span><span class="mtk8">&quot;100vh&quot;</span><span class="mtk1"> }</span><span class="mtk4">}</span><span class="mtk1"> </span><span class="mtk17">/&gt;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk17">&lt;/</span><span class="mtk10">Container</span><span class="mtk17">&gt;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> );</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1">}</span></span></span></code></pre> <video width="720" height="400" autoplay loop muted playsinline preload="none"> <source src="/2871ae4c2589fe3f7065179093af62e8/FixedContainer.mp4" type="video/mp4"> </video> <p>This example demonstrates how a container with a <code>fixed</code> property adheres to a set width until it reaches the specified media breakpoint, unlike fluid containers that continuously adjust their width based on the viewport size.</p> <p>The fixed Container’s behavior is due to the <code>maxWidth</code> property being set for all breakpoints, ensuring that the container’s width remains constant until the viewport size exceeds the specified breakpoint.</p> <p>We can use the theme to override the default MUI breakpoints:</p> <pre class="grvsc-container default-dark" data-language="jsx" data-index="3"><code class="grvsc-code"><span class="grvsc-line"><span class="grvsc-source"><span class="mtk15">import</span><span class="mtk1"> </span><span class="mtk12">React</span><span class="mtk1"> </span><span class="mtk15">from</span><span class="mtk1"> </span><span class="mtk8">&quot;react&quot;</span><span class="mtk1">;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk15">import</span><span class="mtk1"> { </span><span class="mtk12">createTheme</span><span class="mtk1">, </span><span class="mtk12">ThemeProvider</span><span class="mtk1">, </span><span class="mtk12">Container</span><span class="mtk1">, </span><span class="mtk12">Box</span><span class="mtk1"> } </span><span class="mtk15">from</span><span class="mtk1"> </span><span class="mtk8">&quot;@mui/material&quot;</span><span class="mtk1">;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk4">const</span><span class="mtk1"> </span><span class="mtk12">theme</span><span class="mtk1"> = </span><span class="mtk11">createTheme</span><span class="mtk1">({</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">breakpoints:</span><span class="mtk1"> {</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">values:</span><span class="mtk1"> {</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">xs:</span><span class="mtk1"> </span><span class="mtk7">0</span><span class="mtk1">,</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">sm:</span><span class="mtk1"> </span><span class="mtk7">300</span><span class="mtk1">,</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">md:</span><span class="mtk1"> </span><span class="mtk7">660</span><span class="mtk1">,</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">lg:</span><span class="mtk1"> </span><span class="mtk7">980</span><span class="mtk1">,</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">xl:</span><span class="mtk1"> </span><span class="mtk7">1620</span><span class="mtk1">,</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> },</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> },</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1">});</span></span></span> <span class="grvsc-line"><span class="grvsc-source"></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk15">export</span><span class="mtk1"> </span><span class="mtk15">default</span><span class="mtk1"> </span><span class="mtk4">function</span><span class="mtk1"> </span><span class="mtk11">CustomFixedContainer</span><span class="mtk1">() {</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk15">return</span><span class="mtk1"> (</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk17">&lt;</span><span class="mtk10">ThemeProvider</span><span class="mtk1"> </span><span class="mtk12">theme</span><span class="mtk1">=</span><span class="mtk4">{</span><span class="mtk12">theme</span><span class="mtk4">}</span><span class="mtk17">&gt;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk17">&lt;</span><span class="mtk10">Container</span><span class="mtk1"> </span><span class="mtk12">fixed</span><span class="mtk17">&gt;</span><span class="mtk4">{</span><span class="mtk3">/* More content here */</span><span class="mtk4">}</span><span class="mtk17">&lt;/</span><span class="mtk10">Container</span><span class="mtk17">&gt;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk17">&lt;/</span><span class="mtk10">ThemeProvider</span><span class="mtk17">&gt;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> );</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1">}</span></span></span></code></pre> <p>This will have a global effect on all containers within the application.</p> <h2 id="overriding-container-max-width" style="position:relative;"><a href="#overriding-container-max-width" aria-label="overriding container max width permalink" class="anchor before"><svg aria-hidden="true" focusable="false" height="16" version="1.1" viewBox="0 0 16 16" width="16"><path fill-rule="evenodd" d="M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z"></path></svg></a>Overriding Container Max Width</h2> <p>To customize the layout beyond the default Material Design screen sizes, you can override the MUI Container’s <code>maxWidth</code> directly from the theme or on a per-component basis. This flexibility allows for tailored layout designs that better suit the unique requirements of our application.</p> <h3 id="overriding-from-theme" style="position:relative;"><a href="#overriding-from-theme" aria-label="overriding from theme permalink" class="anchor before"><svg aria-hidden="true" focusable="false" height="16" version="1.1" viewBox="0 0 16 16" width="16"><path fill-rule="evenodd" d="M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z"></path></svg></a>Overriding from Theme</h3> <p>We can override default <code>maxWidth</code> values by customizing the theme. This approach ensures consistency across all containers within our application:</p> <pre class="grvsc-container default-dark" data-language="jsx" data-index="4"><code class="grvsc-code"><span class="grvsc-line"><span class="grvsc-source"><span class="mtk15">import</span><span class="mtk1"> { </span><span class="mtk12">createTheme</span><span class="mtk1">, </span><span class="mtk12">ThemeProvider</span><span class="mtk1">, </span><span class="mtk12">Container</span><span class="mtk1"> } </span><span class="mtk15">from</span><span class="mtk1"> </span><span class="mtk8">&quot;@mui/material&quot;</span><span class="mtk1">;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk4">const</span><span class="mtk1"> </span><span class="mtk12">theme</span><span class="mtk1"> = </span><span class="mtk11">createTheme</span><span class="mtk1">({</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">components:</span><span class="mtk1"> {</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">MuiContainer:</span><span class="mtk1"> {</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">styleOverrides:</span><span class="mtk1"> {</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">root:</span><span class="mtk1"> {</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk8">&quot;&amp;.MuiContainer-maxWidthSm&quot;</span><span class="mtk12">:</span><span class="mtk1"> {</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">maxWidth:</span><span class="mtk1"> </span><span class="mtk8">&quot;400px&quot;</span><span class="mtk1">,</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> },</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk8">&quot;&amp;.MuiContainer-maxWidthMd&quot;</span><span class="mtk12">:</span><span class="mtk1"> {</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">maxWidth:</span><span class="mtk1"> </span><span class="mtk8">&quot;600px&quot;</span><span class="mtk1">,</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> },</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk3">// Add other classes as needed</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> },</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> },</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> },</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> },</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1">});</span></span></span> <span class="grvsc-line"><span class="grvsc-source"></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk4">function</span><span class="mtk1"> </span><span class="mtk11">App</span><span class="mtk1">() {</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk15">return</span><span class="mtk1"> (</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk17">&lt;</span><span class="mtk10">ThemeProvider</span><span class="mtk1"> </span><span class="mtk12">theme</span><span class="mtk1">=</span><span class="mtk4">{</span><span class="mtk12">theme</span><span class="mtk4">}</span><span class="mtk17">&gt;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk17">&lt;</span><span class="mtk10">Container</span><span class="mtk1"> </span><span class="mtk12">maxWidth</span><span class="mtk1">=</span><span class="mtk8">&quot;sm&quot;</span><span class="mtk17">&gt;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk4">{</span><span class="mtk3">/* This Container will use the new sm maxWidth of 400px */</span><span class="mtk4">}</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk17">&lt;/</span><span class="mtk10">Container</span><span class="mtk17">&gt;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk17">&lt;/</span><span class="mtk10">ThemeProvider</span><span class="mtk17">&gt;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> );</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1">}</span></span></span></code></pre> <p>In this example, we used the <code>styleOverrides</code> property to customize the <code>maxWidth</code> values for the <code>sm</code> and <code>md</code> classes, ensuring that all containers within the application will use the overridden <code>maxWidth</code> values.</p> <h3 id="overriding-from-component" style="position:relative;"><a href="#overriding-from-component" aria-label="overriding from component permalink" class="anchor before"><svg aria-hidden="true" focusable="false" height="16" version="1.1" viewBox="0 0 16 16" width="16"><path fill-rule="evenodd" d="M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z"></path></svg></a>Overriding from Component</h3> <p>We can also directly override the <code>maxWidth</code> from the component, allowing for per-component customization.</p> <pre class="grvsc-container default-dark" data-language="jsx" data-index="5"><code class="grvsc-code"><span class="grvsc-line"><span class="grvsc-source"><span class="mtk15">import</span><span class="mtk1"> </span><span class="mtk12">Container</span><span class="mtk1"> </span><span class="mtk15">from</span><span class="mtk1"> </span><span class="mtk8">&quot;@mui/material/Container&quot;</span><span class="mtk1">;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk4">function</span><span class="mtk1"> </span><span class="mtk11">CustomMaxWidthContainer</span><span class="mtk1">() {</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk15">return</span><span class="mtk1"> (</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk17">&lt;</span><span class="mtk10">Container</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">maxWidth</span><span class="mtk1">=</span><span class="mtk8">&quot;md&quot;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">sx</span><span class="mtk1">=</span><span class="mtk4">{</span><span class="mtk1">{</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk8">&quot;&amp;.MuiContainer-maxWidthMd&quot;</span><span class="mtk12">:</span><span class="mtk1"> {</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">maxWidth:</span><span class="mtk1"> </span><span class="mtk8">&quot;600px&quot;</span><span class="mtk1">,</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> },</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> }</span><span class="mtk4">}</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk17">&gt;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk4">{</span><span class="mtk3">/* This Container will use the new md maxWidth of 600px */</span><span class="mtk4">}</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk17">&lt;/</span><span class="mtk10">Container</span><span class="mtk17">&gt;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> );</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1">}</span></span></span></code></pre> <p>In this example, we used the <code>sx</code> prop to override the <code>maxWidth</code> for the <code>md</code> breakpoint directly from the component, ensuring that only this specific container will use the overridden <code>maxWidth</code> value.</p> <h3 id="disabling-maxwidth" style="position:relative;"><a href="#disabling-maxwidth" aria-label="disabling maxwidth permalink" class="anchor before"><svg aria-hidden="true" focusable="false" height="16" version="1.1" viewBox="0 0 16 16" width="16"><path fill-rule="evenodd" d="M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z"></path></svg></a>Disabling <code>maxWidth</code></h3> <p>For complete customization, setting <code>maxWidth</code> to <code>false</code> and using the <code>sx</code> prop allows precise control over the Container’s width, effectively turning off the default behavior and enabling full customization.</p> <pre class="grvsc-container default-dark" data-language="jsx" data-index="6"><code class="grvsc-code"><span class="grvsc-line"><span class="grvsc-source"><span class="mtk15">import</span><span class="mtk1"> </span><span class="mtk12">Container</span><span class="mtk1"> </span><span class="mtk15">from</span><span class="mtk1"> </span><span class="mtk8">&quot;@mui/material/Container&quot;</span><span class="mtk1">;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk4">function</span><span class="mtk1"> </span><span class="mtk11">FullWidthContainer</span><span class="mtk1">() {</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk15">return</span><span class="mtk1"> (</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk17">&lt;</span><span class="mtk10">Container</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">maxWidth</span><span class="mtk1">=</span><span class="mtk4">{false}</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">sx</span><span class="mtk1">=</span><span class="mtk4">{</span><span class="mtk1">{</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">width:</span><span class="mtk1"> </span><span class="mtk8">&quot;100%&quot;</span><span class="mtk1">, </span><span class="mtk3">// Full width</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> }</span><span class="mtk4">}</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk17">&gt;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk4">{</span><span class="mtk3">/* This Container will use the full width */</span><span class="mtk4">}</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk17">&lt;/</span><span class="mtk10">Container</span><span class="mtk17">&gt;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> );</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1">}</span></span></span></code></pre> <h2 id="conclusion" style="position:relative;"><a href="#conclusion" aria-label="conclusion permalink" class="anchor before"><svg aria-hidden="true" focusable="false" height="16" version="1.1" viewBox="0 0 16 16" width="16"><path fill-rule="evenodd" d="M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z"></path></svg></a>Conclusion</h2> <p>MUI Container component offers versatile layout solutions, allowing for both fluid and fixed designs tailored to the application’s needs. Whether we’re adhering to Material Design standards or requiring custom dimensions, the Container’s <code>maxWidth</code> property and theme customization capabilities provide the flexibility needed to create consistent and responsive layouts.</p> <h2 id="complete-code" style="position:relative;"><a href="#complete-code" aria-label="complete code permalink" class="anchor before"><svg aria-hidden="true" focusable="false" height="16" version="1.1" viewBox="0 0 16 16" width="16"><path fill-rule="evenodd" d="M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z"></path></svg></a>Complete Code</h2> <div data-stackblitz="override-mui-container-width"> <button>Run Code</button> </div> <p>Bye for now 👋</p> <style class="grvsc-styles"> .grvsc-container { overflow: auto; position: relative; -webkit-overflow-scrolling: touch; padding-top: 1rem; padding-top: var(--grvsc-padding-top, var(--grvsc-padding-v, 1rem)); padding-bottom: 1rem; padding-bottom: var(--grvsc-padding-bottom, var(--grvsc-padding-v, 1rem)); border-radius: 8px; border-radius: var(--grvsc-border-radius, 8px); font-feature-settings: normal; line-height: 1.4; } .grvsc-code { display: table; } .grvsc-line { display: table-row; box-sizing: border-box; width: 100%; position: relative; } .grvsc-line > * { position: relative; } .grvsc-gutter-pad { display: table-cell; padding-left: 0.75rem; padding-left: calc(var(--grvsc-padding-left, var(--grvsc-padding-h, 1.5rem)) / 2); } .grvsc-gutter { display: table-cell; -webkit-user-select: none; -moz-user-select: none; user-select: none; } .grvsc-gutter::before { content: attr(data-content); } .grvsc-source { display: table-cell; padding-left: 1.5rem; padding-left: var(--grvsc-padding-left, var(--grvsc-padding-h, 1.5rem)); padding-right: 1.5rem; padding-right: var(--grvsc-padding-right, var(--grvsc-padding-h, 1.5rem)); } .grvsc-source:empty::after { content: ' '; -webkit-user-select: none; -moz-user-select: none; user-select: none; } .grvsc-gutter + .grvsc-source { padding-left: 0.75rem; padding-left: calc(var(--grvsc-padding-left, var(--grvsc-padding-h, 1.5rem)) / 2); } /* Line transformer styles */ .grvsc-has-line-highlighting > .grvsc-code > .grvsc-line::before { content: ' '; position: absolute; width: 100%; } .grvsc-line-diff-add::before { background-color: var(--grvsc-line-diff-add-background-color, rgba(0, 255, 60, 0.2)); } .grvsc-line-diff-del::before { background-color: var(--grvsc-line-diff-del-background-color, rgba(255, 0, 20, 0.2)); } .grvsc-line-number { padding: 0 2px; text-align: right; opacity: 0.7; } .default-dark { background-color: #1E1E1E; color: #D4D4D4; } .default-dark .mtk15 { color: #C586C0; } .default-dark .mtk1 { color: #D4D4D4; } .default-dark .mtk12 { color: #9CDCFE; } .default-dark .mtk8 { color: #CE9178; } .default-dark .mtk4 { color: #569CD6; } .default-dark .mtk11 { color: #DCDCAA; } .default-dark .mtk17 { color: #808080; } .default-dark .mtk10 { color: #4EC9B0; } .default-dark .mtk7 { color: #B5CEA8; } .default-dark .mtk3 { color: #6A9955; } .default-dark .grvsc-line-highlighted::before { background-color: var(--grvsc-line-highlighted-background-color, rgba(255, 255, 255, 0.1)); box-shadow: inset var(--grvsc-line-highlighted-border-width, 4px) 0 0 0 var(--grvsc-line-highlighted-border-color, rgba(255, 255, 255, 0.5)); } </style><![CDATA[How to Create an Icon Button with Material UI (MUI)]]>https://muhimasri.comhow-to-create-mui-icon-button-with-texthttps://muhimasri.comhow-to-create-mui-icon-button-with-text<p>In this tutorial, we will learn how to create a React icon button using Material UI. In particular, we will cover two different techniques for adding an icon to a Material UI button. Below is the complete working code:</p> <div data-codesandbox="mui-icon-button-82u123"> <button>Run Code</button> </div> <p>As you can see in the above example, we have four different buttons:</p> <ol> <li>The first two are very similar, a button with an icon and a text, except each button has the icon in a different position.</li> <li>The last two are just icons with no label or text but they are still made of a button element. If we inspect the element, we can see it as a button with an SVG icon as a child element. That’s why it still has the cool ripple effect (a built-in effect from the Material UI)</li> </ol> <p>Let’s get started with building icon button components:</p> <h2 id="install-mui" style="position:relative;"><a href="#install-mui" aria-label="install mui permalink" class="anchor before"><svg aria-hidden="true" focusable="false" height="16" version="1.1" viewBox="0 0 16 16" width="16"><path fill-rule="evenodd" d="M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z"></path></svg></a>Install MUI</h2> <pre class="grvsc-container default-dark" data-language="" data-index="0"><code class="grvsc-code"><span class="grvsc-line"><span class="grvsc-source">npm install @mui/material @mui/icons-material @emotion/react @emotion/styled</span></span></code></pre> <p><a href="https://emotion.sh/docs/introduction">Emotion</a> library is required to create React components that have styles attached to them.</p> <h2 id="create-an-mui-icon-button-without-text" style="position:relative;"><a href="#create-an-mui-icon-button-without-text" aria-label="create an mui icon button without text permalink" class="anchor before"><svg aria-hidden="true" focusable="false" height="16" version="1.1" viewBox="0 0 16 16" width="16"><path fill-rule="evenodd" d="M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z"></path></svg></a>Create an MUI Icon Button without text</h2> <p>We can import and use an already made Material UI icon button component called <code>IconButton</code> in the main App component. It’s made specifically to create an icon button with no text or label:</p> <pre class="grvsc-container default-dark" data-language="jsx" data-index="1"><code class="grvsc-code"><span class="grvsc-line"><span class="grvsc-source"><span class="mtk15">import</span><span class="mtk1"> </span><span class="mtk12">IconButton</span><span class="mtk1"> </span><span class="mtk15">from</span><span class="mtk1"> </span><span class="mtk8">&quot;@mui/material/IconButton&quot;</span><span class="mtk1">;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk15">export</span><span class="mtk1"> </span><span class="mtk15">default</span><span class="mtk1"> </span><span class="mtk4">function</span><span class="mtk1"> </span><span class="mtk11">App</span><span class="mtk1">() {</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk15">return</span><span class="mtk1"> (</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk17">&lt;</span><span class="mtk4">div</span><span class="mtk17">&gt;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk17">&lt;</span><span class="mtk10">IconButton</span><span class="mtk17">&gt;&lt;/</span><span class="mtk10">IconButton</span><span class="mtk17">&gt;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk17">&lt;/</span><span class="mtk4">div</span><span class="mtk17">&gt;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> );</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1">}</span></span></span></code></pre> <p>Initially, we won’t see anything because it requires us to specify the icon. MUI has a list of icons we can choose from; <a href="https://mui.com/material-ui/material-icons/">click here to see the complete list</a>. We can pick the delete icon for this example and include it within the <code>IconButton</code> component:</p> <pre class="grvsc-container grvsc-has-line-highlighting default-dark" data-language="jsx" data-index="2"><code class="grvsc-code"><span class="grvsc-line"><span class="grvsc-source"><span class="mtk15">import</span><span class="mtk1"> </span><span class="mtk12">IconButton</span><span class="mtk1"> </span><span class="mtk15">from</span><span class="mtk1"> </span><span class="mtk8">&quot;@mui/material/IconButton&quot;</span><span class="mtk1">;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk15">import</span><span class="mtk1"> </span><span class="mtk12">DeleteIcon</span><span class="mtk1"> </span><span class="mtk15">from</span><span class="mtk1"> </span><span class="mtk8">&#39;@mui/icons-material/Delete&#39;</span><span class="mtk1">;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk15">export</span><span class="mtk1"> </span><span class="mtk15">default</span><span class="mtk1"> </span><span class="mtk4">function</span><span class="mtk1"> </span><span class="mtk11">App</span><span class="mtk1">() {</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk15">return</span><span class="mtk1"> (</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk17">&lt;</span><span class="mtk4">div</span><span class="mtk17">&gt;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk17">&lt;</span><span class="mtk10">IconButton</span><span class="mtk17">&gt;</span></span></span> <span class="grvsc-line grvsc-line-highlighted"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk17">&lt;</span><span class="mtk10">DeleteIcon</span><span class="mtk1"> </span><span class="mtk17">/&gt;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk17">&lt;/</span><span class="mtk10">IconButton</span><span class="mtk17">&gt;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk17">&lt;/</span><span class="mtk4">div</span><span class="mtk17">&gt;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> );</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1">}</span></span></span></code></pre> <p>Now we should have the delete icon button showing correctly on the screen.</p> <p>To change the size or other styles, we can make use of the <a href="https://mui.com/material-ui/api/icon-button/">IconButton API</a> and <a href="https://mui.com/material-ui/api/icon/">Icon API</a>:</p> <pre class="grvsc-container default-dark" data-language="jsx" data-index="3"><code class="grvsc-code"><span class="grvsc-line"><span class="grvsc-source"><span class="mtk15">import</span><span class="mtk1"> </span><span class="mtk12">IconButton</span><span class="mtk1"> </span><span class="mtk15">from</span><span class="mtk1"> </span><span class="mtk8">&quot;@mui/material/IconButton&quot;</span><span class="mtk1">;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk15">import</span><span class="mtk1"> </span><span class="mtk12">DeleteIcon</span><span class="mtk1"> </span><span class="mtk15">from</span><span class="mtk1"> </span><span class="mtk8">&#39;@mui/icons-material/Delete&#39;</span><span class="mtk1">;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk15">export</span><span class="mtk1"> </span><span class="mtk15">default</span><span class="mtk1"> </span><span class="mtk4">function</span><span class="mtk1"> </span><span class="mtk11">App</span><span class="mtk1">() {</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk15">return</span><span class="mtk1"> (</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk17">&lt;</span><span class="mtk4">div</span><span class="mtk17">&gt;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk17">&lt;</span><span class="mtk10">IconButton</span><span class="mtk1"> </span><span class="mtk12">size</span><span class="mtk1">=</span><span class="mtk8">&quot;large&quot;</span><span class="mtk17">&gt;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk17">&lt;</span><span class="mtk10">DeleteIcon</span><span class="mtk1"> </span><span class="mtk12">fontSize</span><span class="mtk1">=</span><span class="mtk8">&quot;large&quot;</span><span class="mtk1"> </span><span class="mtk17">/&gt;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk17">&lt;/</span><span class="mtk10">IconButton</span><span class="mtk17">&gt;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk17">&lt;/</span><span class="mtk4">div</span><span class="mtk17">&gt;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> );</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1">}</span></span></span></code></pre> <p>We have to use both <code>size</code> and <code>fontSize</code> props because the <code>IconButton</code> will only change the size of the button but not the SVG font size.</p> <h2 id="create-an-mui-icon-button-with-text" style="position:relative;"><a href="#create-an-mui-icon-button-with-text" aria-label="create an mui icon button with text permalink" class="anchor before"><svg aria-hidden="true" focusable="false" height="16" version="1.1" viewBox="0 0 16 16" width="16"><path fill-rule="evenodd" d="M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z"></path></svg></a>Create an MUI icon button with text</h2> <p>To create an icon button with a text, we can use a standard button component along with a <code>startIcon</code> or <code>endIcon</code> prop, which is available as part of the <a href="https://mui.com/material-ui/api/button/">button API</a>. The prop value accepts any Material UI icon. Let’s add a save icon followed by a “Save” text:</p> <pre class="grvsc-container grvsc-has-line-highlighting default-dark" data-language="jsx" data-index="4"><code class="grvsc-code"><span class="grvsc-line"><span class="grvsc-source"><span class="mtk15">import</span><span class="mtk1"> </span><span class="mtk12">IconButton</span><span class="mtk1"> </span><span class="mtk15">from</span><span class="mtk1"> </span><span class="mtk8">&quot;@mui/material/IconButton&quot;</span><span class="mtk1">;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk15">import</span><span class="mtk1"> </span><span class="mtk12">DeleteIcon</span><span class="mtk1"> </span><span class="mtk15">from</span><span class="mtk1"> </span><span class="mtk8">&#39;@mui/icons-material/Delete&#39;</span><span class="mtk1">;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk15">import</span><span class="mtk1"> </span><span class="mtk12">SaveIcon</span><span class="mtk1"> </span><span class="mtk15">from</span><span class="mtk1"> </span><span class="mtk8">&#39;@mui/icons-material/Save&#39;</span><span class="mtk1">;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk15">import</span><span class="mtk1"> { </span><span class="mtk12">Button</span><span class="mtk1"> } </span><span class="mtk15">from</span><span class="mtk1"> </span><span class="mtk8">&quot;@mui/material&quot;</span><span class="mtk1">;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk15">export</span><span class="mtk1"> </span><span class="mtk15">default</span><span class="mtk1"> </span><span class="mtk4">function</span><span class="mtk1"> </span><span class="mtk11">App</span><span class="mtk1">() {</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk15">return</span><span class="mtk1"> (</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk17">&lt;</span><span class="mtk4">div</span><span class="mtk17">&gt;</span></span></span> <span class="grvsc-line grvsc-line-highlighted"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk17">&lt;</span><span class="mtk10">Button</span><span class="mtk1"> </span><span class="mtk12">startIcon</span><span class="mtk1">=</span><span class="mtk4">{</span><span class="mtk17">&lt;</span><span class="mtk10">SaveIcon</span><span class="mtk1"> </span><span class="mtk17">/&gt;</span><span class="mtk4">}</span><span class="mtk17">&gt;</span><span class="mtk1">Save</span><span class="mtk17">&lt;/</span><span class="mtk10">Button</span><span class="mtk17">&gt;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk17">&lt;</span><span class="mtk10">IconButton</span><span class="mtk1"> </span><span class="mtk12">size</span><span class="mtk1">=</span><span class="mtk8">&quot;large&quot;</span><span class="mtk17">&gt;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk17">&lt;</span><span class="mtk10">DeleteIcon</span><span class="mtk1"> </span><span class="mtk12">fontSize</span><span class="mtk1">=</span><span class="mtk8">&quot;large&quot;</span><span class="mtk1"> </span><span class="mtk17">/&gt;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk17">&lt;/</span><span class="mtk10">IconButton</span><span class="mtk17">&gt;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk17">&lt;/</span><span class="mtk4">div</span><span class="mtk17">&gt;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> );</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1">}</span></span></span></code></pre> <p>Customizing and styling is similar to the <code>IconButton</code> we did earlier. For this specific example, we can use the <code>sx</code> prop, which allows us to specify any valid CSS. Let’s change the radius to 10 pixels and make it “contained”.</p> <pre class="grvsc-container grvsc-has-line-highlighting default-dark" data-language="jsx" data-index="5"><code class="grvsc-code"><span class="grvsc-line"><span class="grvsc-source"><span class="mtk15">import</span><span class="mtk1"> </span><span class="mtk12">IconButton</span><span class="mtk1"> </span><span class="mtk15">from</span><span class="mtk1"> </span><span class="mtk8">&quot;@mui/material/IconButton&quot;</span><span class="mtk1">;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk15">import</span><span class="mtk1"> </span><span class="mtk12">DeleteIcon</span><span class="mtk1"> </span><span class="mtk15">from</span><span class="mtk1"> </span><span class="mtk8">&quot;@mui/icons-material/Delete&quot;</span><span class="mtk1">;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk15">import</span><span class="mtk1"> </span><span class="mtk12">SaveIcon</span><span class="mtk1"> </span><span class="mtk15">from</span><span class="mtk1"> </span><span class="mtk8">&quot;@mui/icons-material/Save&quot;</span><span class="mtk1">;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk15">import</span><span class="mtk1"> { </span><span class="mtk12">Button</span><span class="mtk1"> } </span><span class="mtk15">from</span><span class="mtk1"> </span><span class="mtk8">&quot;@mui/material&quot;</span><span class="mtk1">;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk15">export</span><span class="mtk1"> </span><span class="mtk15">default</span><span class="mtk1"> </span><span class="mtk4">function</span><span class="mtk1"> </span><span class="mtk11">App</span><span class="mtk1">() {</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk15">return</span><span class="mtk1"> (</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk17">&lt;</span><span class="mtk4">div</span><span class="mtk17">&gt;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk17">&lt;</span><span class="mtk10">Button</span></span></span> <span class="grvsc-line grvsc-line-highlighted"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">sx</span><span class="mtk1">=</span><span class="mtk4">{</span><span class="mtk1">{ </span><span class="mtk12">borderRadius:</span><span class="mtk1"> </span><span class="mtk7">10</span><span class="mtk1"> }</span><span class="mtk4">}</span></span></span> <span class="grvsc-line grvsc-line-highlighted"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">variant</span><span class="mtk1">=</span><span class="mtk8">&quot;contained&quot;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">startIcon</span><span class="mtk1">=</span><span class="mtk4">{</span><span class="mtk17">&lt;</span><span class="mtk10">SaveIcon</span><span class="mtk1"> </span><span class="mtk17">/&gt;</span><span class="mtk4">}</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk17">&gt;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> Save</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk17">&lt;/</span><span class="mtk10">Button</span><span class="mtk17">&gt;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk17">&lt;</span><span class="mtk10">IconButton</span><span class="mtk1"> </span><span class="mtk12">size</span><span class="mtk1">=</span><span class="mtk8">&quot;large&quot;</span><span class="mtk17">&gt;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk17">&lt;</span><span class="mtk10">DeleteIcon</span><span class="mtk1"> </span><span class="mtk12">fontSize</span><span class="mtk1">=</span><span class="mtk8">&quot;large&quot;</span><span class="mtk1"> </span><span class="mtk17">/&gt;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk17">&lt;/</span><span class="mtk10">IconButton</span><span class="mtk17">&gt;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk17">&lt;/</span><span class="mtk4">div</span><span class="mtk17">&gt;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> );</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1">}</span></span></span></code></pre> <p>Lastly, we can tidy things up by encapsulating the new button customization in one component to reuse it anywhere in our project. So let’s create a new one with all the changes we just did and then import it into the main app.</p> <pre class="grvsc-container default-dark" data-language="jsx" data-index="6"><code class="grvsc-code"><span class="grvsc-line"><span class="grvsc-source"><span class="mtk15">import</span><span class="mtk1"> </span><span class="mtk12">SaveIcon</span><span class="mtk1"> </span><span class="mtk15">from</span><span class="mtk1"> </span><span class="mtk8">&quot;@mui/icons-material/Save&quot;</span><span class="mtk1">;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk15">import</span><span class="mtk1"> { </span><span class="mtk12">Button</span><span class="mtk1"> } </span><span class="mtk15">from</span><span class="mtk1"> </span><span class="mtk8">&quot;@mui/material&quot;</span><span class="mtk1">;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk15">export</span><span class="mtk1"> </span><span class="mtk4">const</span><span class="mtk1"> </span><span class="mtk11">SaveButton</span><span class="mtk1"> = () </span><span class="mtk4">=&gt;</span><span class="mtk1"> (</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk17">&lt;</span><span class="mtk10">Button</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">sx</span><span class="mtk1">=</span><span class="mtk4">{</span><span class="mtk1">{ </span><span class="mtk12">borderRadius:</span><span class="mtk1"> </span><span class="mtk7">10</span><span class="mtk1"> }</span><span class="mtk4">}</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">variant</span><span class="mtk1">=</span><span class="mtk8">&quot;contained&quot;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">startIcon</span><span class="mtk1">=</span><span class="mtk4">{</span><span class="mtk17">&lt;</span><span class="mtk10">SaveIcon</span><span class="mtk1"> </span><span class="mtk17">/&gt;</span><span class="mtk4">}</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk17">&gt;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> Save</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk17">&lt;/</span><span class="mtk10">Button</span><span class="mtk17">&gt;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1">);</span></span></span></code></pre> <pre class="grvsc-container grvsc-has-line-highlighting default-dark" data-language="jsx" data-index="7"><code class="grvsc-code"><span class="grvsc-line"><span class="grvsc-source"><span class="mtk15">import</span><span class="mtk1"> </span><span class="mtk12">IconButton</span><span class="mtk1"> </span><span class="mtk15">from</span><span class="mtk1"> </span><span class="mtk8">&quot;@mui/material/IconButton&quot;</span><span class="mtk1">;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk15">import</span><span class="mtk1"> </span><span class="mtk12">DeleteIcon</span><span class="mtk1"> </span><span class="mtk15">from</span><span class="mtk1"> </span><span class="mtk8">&quot;@mui/icons-material/Delete&quot;</span><span class="mtk1">;</span></span></span> <span class="grvsc-line grvsc-line-highlighted"><span class="grvsc-source"><span class="mtk15">import</span><span class="mtk1"> { </span><span class="mtk12">SaveButton</span><span class="mtk1"> } </span><span class="mtk15">from</span><span class="mtk1"> </span><span class="mtk8">&quot;./buttons/SaveButton&quot;</span><span class="mtk1">;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk15">export</span><span class="mtk1"> </span><span class="mtk15">default</span><span class="mtk1"> </span><span class="mtk4">function</span><span class="mtk1"> </span><span class="mtk11">App</span><span class="mtk1">() {</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk15">return</span><span class="mtk1"> (</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk17">&lt;</span><span class="mtk4">div</span><span class="mtk17">&gt;</span></span></span> <span class="grvsc-line grvsc-line-highlighted"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk17">&lt;</span><span class="mtk10">SaveButton</span><span class="mtk1"> </span><span class="mtk17">/&gt;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk17">&lt;</span><span class="mtk10">IconButton</span><span class="mtk1"> </span><span class="mtk12">size</span><span class="mtk1">=</span><span class="mtk8">&quot;large&quot;</span><span class="mtk17">&gt;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk17">&lt;</span><span class="mtk10">DeleteIcon</span><span class="mtk1"> </span><span class="mtk12">fontSize</span><span class="mtk1">=</span><span class="mtk8">&quot;large&quot;</span><span class="mtk1"> </span><span class="mtk17">/&gt;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk17">&lt;/</span><span class="mtk10">IconButton</span><span class="mtk17">&gt;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk17">&lt;/</span><span class="mtk4">div</span><span class="mtk17">&gt;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> );</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1">}</span></span></span></code></pre> <p>Bye for now 👋</p> <style class="grvsc-styles"> .grvsc-container { overflow: auto; position: relative; -webkit-overflow-scrolling: touch; padding-top: 1rem; padding-top: var(--grvsc-padding-top, var(--grvsc-padding-v, 1rem)); padding-bottom: 1rem; padding-bottom: var(--grvsc-padding-bottom, var(--grvsc-padding-v, 1rem)); border-radius: 8px; border-radius: var(--grvsc-border-radius, 8px); font-feature-settings: normal; line-height: 1.4; } .grvsc-code { display: table; } .grvsc-line { display: table-row; box-sizing: border-box; width: 100%; position: relative; } .grvsc-line > * { position: relative; } .grvsc-gutter-pad { display: table-cell; padding-left: 0.75rem; padding-left: calc(var(--grvsc-padding-left, var(--grvsc-padding-h, 1.5rem)) / 2); } .grvsc-gutter { display: table-cell; -webkit-user-select: none; -moz-user-select: none; user-select: none; } .grvsc-gutter::before { content: attr(data-content); } .grvsc-source { display: table-cell; padding-left: 1.5rem; padding-left: var(--grvsc-padding-left, var(--grvsc-padding-h, 1.5rem)); padding-right: 1.5rem; padding-right: var(--grvsc-padding-right, var(--grvsc-padding-h, 1.5rem)); } .grvsc-source:empty::after { content: ' '; -webkit-user-select: none; -moz-user-select: none; user-select: none; } .grvsc-gutter + .grvsc-source { padding-left: 0.75rem; padding-left: calc(var(--grvsc-padding-left, var(--grvsc-padding-h, 1.5rem)) / 2); } /* Line transformer styles */ .grvsc-has-line-highlighting > .grvsc-code > .grvsc-line::before { content: ' '; position: absolute; width: 100%; } .grvsc-line-diff-add::before { background-color: var(--grvsc-line-diff-add-background-color, rgba(0, 255, 60, 0.2)); } .grvsc-line-diff-del::before { background-color: var(--grvsc-line-diff-del-background-color, rgba(255, 0, 20, 0.2)); } .grvsc-line-number { padding: 0 2px; text-align: right; opacity: 0.7; } .default-dark { background-color: #1E1E1E; color: #D4D4D4; } .default-dark .mtk15 { color: #C586C0; } .default-dark .mtk1 { color: #D4D4D4; } .default-dark .mtk12 { color: #9CDCFE; } .default-dark .mtk8 { color: #CE9178; } .default-dark .mtk4 { color: #569CD6; } .default-dark .mtk11 { color: #DCDCAA; } .default-dark .mtk17 { color: #808080; } .default-dark .mtk10 { color: #4EC9B0; } .default-dark .mtk7 { color: #B5CEA8; } .default-dark .grvsc-line-highlighted::before { background-color: var(--grvsc-line-highlighted-background-color, rgba(255, 255, 255, 0.1)); box-shadow: inset var(--grvsc-line-highlighted-border-width, 4px) 0 0 0 var(--grvsc-line-highlighted-border-color, rgba(255, 255, 255, 0.5)); } </style><![CDATA[[Part 4] Validate Table Rows and Fields with Angular Material]]>https://muhimasri.compart-4-validate-table-rows-and-fields-with-angular-materialhttps://muhimasri.compart-4-validate-table-rows-and-fields-with-angular-material<p>This part will focus on adding input field validations for table rows; we’ll leverage the built-in HTML form validation to identify input validity.</p> <p>Before we begin, the <a href="https://github.com/muhimasri/angular-editable-table">complete repository is accessible here</a>, and a working example is available below:</p> <div data-stackblitz="angular-editable-table-part-4"> <button>Run Code</button> </div> <p><em>As we continue building upon the same code from previous parts in this series, it’s recommended that you go through these tutorials from the beginning to understand how the code structure works as we will not be explaining it. You can navigate to any part using the table of contents.</em></p> <h2 id="required-validation" style="position:relative;"><a href="#required-validation" aria-label="required validation permalink" class="anchor before"><svg aria-hidden="true" focusable="false" height="16" version="1.1" viewBox="0 0 16 16" width="16"><path fill-rule="evenodd" d="M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z"></path></svg></a>Required validation</h2> <p>The <code>required</code> attribute is a built-in HTML input validation, and it specifies that an input field must be filled out before submitting the form. Given that <code>matInput</code> already has a style rule for a required input field, it should turn red if the user leaves it empty.</p> <p>Let’s add it to the input element in <code>app.component.html</code> and look at the results:</p> <pre class="grvsc-container grvsc-has-line-highlighting default-dark" data-language="html" data-index="0"><code class="grvsc-code"><span class="grvsc-line"><span class="grvsc-source"><span class="mtk17">&lt;</span><span class="mtk4">article</span><span class="mtk1"> </span><span class="mtk12">class</span><span class="mtk1">=</span><span class="mtk8">&quot;table-header&quot;</span><span class="mtk17">&gt;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk17">&lt;</span><span class="mtk4">button</span><span class="mtk1"> </span><span class="mtk12">class</span><span class="mtk1">=</span><span class="mtk8">&quot;button-remove-rows&quot;</span><span class="mtk1"> </span><span class="mtk12">mat-button</span><span class="mtk1"> </span><span class="mtk12">(click)</span><span class="mtk1">=</span><span class="mtk8">&quot;removeSelectedRows()&quot;</span><span class="mtk17">&gt;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> Remove Rows</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk17">&lt;/</span><span class="mtk4">button</span><span class="mtk17">&gt;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk17">&lt;</span><span class="mtk4">button</span><span class="mtk1"> </span><span class="mtk12">class</span><span class="mtk1">=</span><span class="mtk8">&quot;button-add-row&quot;</span><span class="mtk1"> </span><span class="mtk12">mat-button</span><span class="mtk1"> </span><span class="mtk12">(click)</span><span class="mtk1">=</span><span class="mtk8">&quot;addRow()&quot;</span><span class="mtk17">&gt;</span><span class="mtk1">Add Row</span><span class="mtk17">&lt;/</span><span class="mtk4">button</span><span class="mtk17">&gt;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk17">&lt;/</span><span class="mtk4">article</span><span class="mtk17">&gt;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk17">&lt;</span><span class="mtk4">table</span><span class="mtk1"> </span><span class="mtk12">mat-table</span><span class="mtk1"> </span><span class="mtk12">[dataSource]</span><span class="mtk1">=</span><span class="mtk8">&quot;dataSource&quot;</span><span class="mtk17">&gt;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk17">&lt;</span><span class="mtk4">ng-container</span><span class="mtk1"> </span><span class="mtk12">[matColumnDef]</span><span class="mtk1">=</span><span class="mtk8">&quot;col.key&quot;</span><span class="mtk1"> </span><span class="mtk12">*ngFor</span><span class="mtk1">=</span><span class="mtk8">&quot;let col of columnsSchema&quot;</span><span class="mtk17">&gt;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk17">&lt;</span><span class="mtk4">th</span><span class="mtk1"> </span><span class="mtk12">mat-header-cell</span><span class="mtk1"> </span><span class="mtk12">*matHeaderCellDef</span><span class="mtk17">&gt;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> {{ col.label }}</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk17">&lt;/</span><span class="mtk4">th</span><span class="mtk17">&gt;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk17">&lt;</span><span class="mtk4">td</span><span class="mtk1"> </span><span class="mtk12">mat-cell</span><span class="mtk1"> </span><span class="mtk12">*matCellDef</span><span class="mtk1">=</span><span class="mtk8">&quot;let element&quot;</span><span class="mtk17">&gt;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk17">&lt;</span><span class="mtk4">div</span><span class="mtk1"> </span><span class="mtk12">[ngSwitch]</span><span class="mtk1">=</span><span class="mtk8">&quot;col.type&quot;</span><span class="mtk1"> </span><span class="mtk12">*ngIf</span><span class="mtk1">=</span><span class="mtk8">&quot;!element.isEdit&quot;</span><span class="mtk17">&gt;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk17">&lt;</span><span class="mtk4">ng-container</span><span class="mtk1"> </span><span class="mtk12">*ngSwitchCase</span><span class="mtk1">=</span><span class="mtk8">&quot;&#39;isSelected&#39;&quot;</span><span class="mtk17">&gt;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk17">&lt;</span><span class="mtk4">mat-checkbox</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">(change)</span><span class="mtk1">=</span><span class="mtk8">&quot;element.isSelected = $event.checked&quot;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk17">&gt;&lt;/</span><span class="mtk4">mat-checkbox</span><span class="mtk17">&gt;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk17">&lt;/</span><span class="mtk4">ng-container</span><span class="mtk17">&gt;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk17">&lt;</span><span class="mtk4">div</span><span class="mtk1"> </span><span class="mtk12">class</span><span class="mtk1">=</span><span class="mtk8">&quot;btn-edit&quot;</span><span class="mtk1"> </span><span class="mtk12">*ngSwitchCase</span><span class="mtk1">=</span><span class="mtk8">&quot;&#39;isEdit&#39;&quot;</span><span class="mtk17">&gt;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk17">&lt;</span><span class="mtk4">button</span><span class="mtk1"> </span><span class="mtk12">mat-button</span><span class="mtk1"> </span><span class="mtk12">(click)</span><span class="mtk1">=</span><span class="mtk8">&quot;element.isEdit = !element.isEdit&quot;</span><span class="mtk17">&gt;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> Edit</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk17">&lt;/</span><span class="mtk4">button</span><span class="mtk17">&gt;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk17">&lt;</span><span class="mtk4">button</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">mat-button</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">class</span><span class="mtk1">=</span><span class="mtk8">&quot;button-remove&quot;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">(click)</span><span class="mtk1">=</span><span class="mtk8">&quot;removeRow(element.id)&quot;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk17">&gt;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> Delete</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk17">&lt;/</span><span class="mtk4">button</span><span class="mtk17">&gt;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk17">&lt;/</span><span class="mtk4">div</span><span class="mtk17">&gt;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk17">&lt;</span><span class="mtk4">span</span><span class="mtk1"> </span><span class="mtk12">*ngSwitchCase</span><span class="mtk1">=</span><span class="mtk8">&quot;&#39;date&#39;&quot;</span><span class="mtk17">&gt;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> {{ element[col.key] | date: &#39;mediumDate&#39; }}</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk17">&lt;/</span><span class="mtk4">span</span><span class="mtk17">&gt;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk17">&lt;</span><span class="mtk4">span</span><span class="mtk1"> </span><span class="mtk12">*ngSwitchDefault</span><span class="mtk17">&gt;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> {{ element[col.key] }}</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk17">&lt;/</span><span class="mtk4">span</span><span class="mtk17">&gt;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk17">&lt;/</span><span class="mtk4">div</span><span class="mtk17">&gt;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk17">&lt;</span><span class="mtk4">div</span><span class="mtk1"> </span><span class="mtk12">[ngSwitch]</span><span class="mtk1">=</span><span class="mtk8">&quot;col.type&quot;</span><span class="mtk1"> </span><span class="mtk12">*ngIf</span><span class="mtk1">=</span><span class="mtk8">&quot;element.isEdit&quot;</span><span class="mtk17">&gt;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk17">&lt;</span><span class="mtk4">div</span><span class="mtk1"> </span><span class="mtk12">*ngSwitchCase</span><span class="mtk1">=</span><span class="mtk8">&quot;&#39;isSelected&#39;&quot;</span><span class="mtk17">&gt;&lt;/</span><span class="mtk4">div</span><span class="mtk17">&gt;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk17">&lt;</span><span class="mtk4">div</span><span class="mtk1"> </span><span class="mtk12">class</span><span class="mtk1">=</span><span class="mtk8">&quot;btn-edit&quot;</span><span class="mtk1"> </span><span class="mtk12">*ngSwitchCase</span><span class="mtk1">=</span><span class="mtk8">&quot;&#39;isEdit&#39;&quot;</span><span class="mtk17">&gt;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk17">&lt;</span><span class="mtk4">button</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">mat-button</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">(click)</span><span class="mtk1">=</span><span class="mtk8">&quot;editRow(element)&quot;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">[disabled]</span><span class="mtk1">=</span><span class="mtk8">&quot;valid[element.id] === false&quot;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk17">&gt;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> Done</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk17">&lt;/</span><span class="mtk4">button</span><span class="mtk17">&gt;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk17">&lt;/</span><span class="mtk4">div</span><span class="mtk17">&gt;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk17">&lt;</span><span class="mtk4">mat-form-field</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">class</span><span class="mtk1">=</span><span class="mtk8">&quot;form-input&quot;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">*ngSwitchCase</span><span class="mtk1">=</span><span class="mtk8">&quot;&#39;date&#39;&quot;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">appearance</span><span class="mtk1">=</span><span class="mtk8">&quot;fill&quot;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk17">&gt;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk17">&lt;</span><span class="mtk4">mat-label</span><span class="mtk17">&gt;</span><span class="mtk1">Choose a date</span><span class="mtk17">&lt;/</span><span class="mtk4">mat-label</span><span class="mtk17">&gt;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk17">&lt;</span><span class="mtk4">input</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">matInput</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">[matDatepicker]</span><span class="mtk1">=</span><span class="mtk8">&quot;picker&quot;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">[(ngModel)]</span><span class="mtk1">=</span><span class="mtk8">&quot;element[col.key]&quot;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk17">/&gt;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk17">&lt;</span><span class="mtk4">mat-datepicker-toggle</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">matSuffix</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">[for]</span><span class="mtk1">=</span><span class="mtk8">&quot;picker&quot;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk17">&gt;&lt;/</span><span class="mtk4">mat-datepicker-toggle</span><span class="mtk17">&gt;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk17">&lt;</span><span class="mtk4">mat-datepicker</span><span class="mtk1"> </span><span class="mtk12">#picker</span><span class="mtk17">&gt;&lt;/</span><span class="mtk4">mat-datepicker</span><span class="mtk17">&gt;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk17">&lt;/</span><span class="mtk4">mat-form-field</span><span class="mtk17">&gt;</span></span></span> <span class="grvsc-line grvsc-line-highlighted"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk17">&lt;</span><span class="mtk4">mat-form-field</span><span class="mtk1"> </span><span class="mtk12">class</span><span class="mtk1">=</span><span class="mtk8">&quot;form-input&quot;</span><span class="mtk1"> </span><span class="mtk12">*ngSwitchDefault</span><span class="mtk17">&gt;</span></span></span> <span class="grvsc-line grvsc-line-highlighted"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk17">&lt;</span><span class="mtk4">input</span></span></span> <span class="grvsc-line grvsc-line-highlighted"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">required</span></span></span> <span class="grvsc-line grvsc-line-highlighted"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">[type]</span><span class="mtk1">=</span><span class="mtk8">&quot;col.type&quot;</span></span></span> <span class="grvsc-line grvsc-line-highlighted"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">matInput</span></span></span> <span class="grvsc-line grvsc-line-highlighted"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">[(ngModel)]</span><span class="mtk1">=</span><span class="mtk8">&quot;element[col.key]&quot;</span></span></span> <span class="grvsc-line grvsc-line-highlighted"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk17">/&gt;</span></span></span> <span class="grvsc-line grvsc-line-highlighted"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk17">&lt;/</span><span class="mtk4">mat-form-field</span><span class="mtk17">&gt;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk17">&lt;/</span><span class="mtk4">div</span><span class="mtk17">&gt;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk17">&lt;/</span><span class="mtk4">td</span><span class="mtk17">&gt;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk17">&lt;/</span><span class="mtk4">ng-container</span><span class="mtk17">&gt;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk17">&lt;</span><span class="mtk4">tr</span><span class="mtk1"> </span><span class="mtk12">mat-header-row</span><span class="mtk1"> </span><span class="mtk12">*matHeaderRowDef</span><span class="mtk1">=</span><span class="mtk8">&quot;displayedColumns&quot;</span><span class="mtk17">&gt;&lt;/</span><span class="mtk4">tr</span><span class="mtk17">&gt;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk17">&lt;</span><span class="mtk4">tr</span><span class="mtk1"> </span><span class="mtk12">mat-row</span><span class="mtk1"> </span><span class="mtk12">*matRowDef</span><span class="mtk1">=</span><span class="mtk8">&quot;let row; columns: displayedColumns&quot;</span><span class="mtk17">&gt;&lt;/</span><span class="mtk4">tr</span><span class="mtk17">&gt;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk17">&lt;/</span><span class="mtk4">table</span><span class="mtk17">&gt;</span></span></span></code></pre> <p><span class="gatsby-resp-image-wrapper" style="position: relative; display: block; margin-left: auto; margin-right: auto; max-width: 720px; " > <a class="gatsby-resp-image-link" href="/static/2e1089781baf464427e69780bcfb9f5f/2bef9/image-4-1024x259.png" style="display: block" target="_blank" rel="noopener" > <span class="gatsby-resp-image-background-image" style="padding-bottom: 25.555555555555554%; position: relative; bottom: 0; left: 0; background-image: url('data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABQAAAAFCAIAAADKYVtkAAAACXBIWXMAAAsTAAALEwEAmpwYAAAA6klEQVR42k1OO46DQBTjRFlShU8ySxiYIWKZlWAigWio6RAEBLegAHqKQM0BONtapFlXfn6231P2fS+Kouu6qqrqum7b9nWgaZqyLP+L4FA+qzzPt21T5nn+Op2+CTF0ndyI67qmaRqGQSlljN0OSCmDIMAohCCEQFFVte97ZVkW7XJ5cM4o9TgPhEDecRy4oyjyfZ97XpZlcRxjTJLE8+DiyE/TpLzfi65p3HXp/Y4GZBzq4CyIlE+EcTBN0zAMD0UymBi7GvowDMq6rpZlQbBtmx2wDyD2KwQIHvlUgMOJp358/3o+j+P4B/iiZtWTDT+kAAAAAElFTkSuQmCC'); background-size: cover; display: block;" ></span> <img class="gatsby-resp-image-image" alt="Validate Angular Table" title="" src="/static/2e1089781baf464427e69780bcfb9f5f/37523/image-4-1024x259.png" srcset="/static/2e1089781baf464427e69780bcfb9f5f/e9ff0/image-4-1024x259.png 180w, /static/2e1089781baf464427e69780bcfb9f5f/f21e7/image-4-1024x259.png 360w, /static/2e1089781baf464427e69780bcfb9f5f/37523/image-4-1024x259.png 720w, /static/2e1089781baf464427e69780bcfb9f5f/2bef9/image-4-1024x259.png 1024w" sizes="(max-width: 720px) 100vw, 720px" style="width:100%;height:100%;margin:0;vertical-align:middle;position:absolute;top:0;left:0;" loading="lazy" decoding="async" /> </a> </span></p> <p>As demonstrated above, not specifying a value in the input field will change it to red, indicating that there is an error.</p> <p>There is a slight problem with that approach; since we added the required attribute to all columns, every input field is validated even though it might not be required. Hence, the validation must come from the user model where we define the columns, which will ensure to validate only the specified fields.</p> <p>Let’s modify <code>user.ts</code> and add a new validation definition only for the <code>firstName</code> column:</p> <pre class="grvsc-container grvsc-has-line-highlighting default-dark" data-language="ts" data-index="1"><code class="grvsc-code"><span class="grvsc-line"><span class="grvsc-source"><span class="mtk15">export</span><span class="mtk1"> </span><span class="mtk4">interface</span><span class="mtk1"> </span><span class="mtk10">User</span><span class="mtk1"> {</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">isSelected</span><span class="mtk1">: </span><span class="mtk10">boolean</span><span class="mtk1">;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">id</span><span class="mtk1">: </span><span class="mtk10">number</span><span class="mtk1">;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">firstName</span><span class="mtk1">: </span><span class="mtk10">string</span><span class="mtk1">;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">lastName</span><span class="mtk1">: </span><span class="mtk10">string</span><span class="mtk1">;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">email</span><span class="mtk1">: </span><span class="mtk10">string</span><span class="mtk1">;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">birthDate</span><span class="mtk1">: </span><span class="mtk10">string</span><span class="mtk1">;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">isEdit</span><span class="mtk1">: </span><span class="mtk10">boolean</span><span class="mtk1">;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1">}</span></span></span> <span class="grvsc-line"><span class="grvsc-source"></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk15">export</span><span class="mtk1"> </span><span class="mtk4">const</span><span class="mtk1"> </span><span class="mtk12">UserColumns</span><span class="mtk1"> = [</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> {</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">key:</span><span class="mtk1"> </span><span class="mtk8">&#39;isSelected&#39;</span><span class="mtk1">,</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">type:</span><span class="mtk1"> </span><span class="mtk8">&#39;isSelected&#39;</span><span class="mtk1">,</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">label:</span><span class="mtk1"> </span><span class="mtk8">&#39;&#39;</span><span class="mtk1">,</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> },</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> {</span></span></span> <span class="grvsc-line grvsc-line-highlighted"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">key:</span><span class="mtk1"> </span><span class="mtk8">&#39;firstName&#39;</span><span class="mtk1">,</span></span></span> <span class="grvsc-line grvsc-line-highlighted"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">type:</span><span class="mtk1"> </span><span class="mtk8">&#39;text&#39;</span><span class="mtk1">,</span></span></span> <span class="grvsc-line grvsc-line-highlighted"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">label:</span><span class="mtk1"> </span><span class="mtk8">&#39;First Name&#39;</span><span class="mtk1">,</span></span></span> <span class="grvsc-line grvsc-line-highlighted"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">required:</span><span class="mtk1"> </span><span class="mtk4">true</span><span class="mtk1">,</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> },</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> {</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">key:</span><span class="mtk1"> </span><span class="mtk8">&#39;lastName&#39;</span><span class="mtk1">,</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">type:</span><span class="mtk1"> </span><span class="mtk8">&#39;text&#39;</span><span class="mtk1">,</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">label:</span><span class="mtk1"> </span><span class="mtk8">&#39;Last Name&#39;</span><span class="mtk1">,</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> },</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> {</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">key:</span><span class="mtk1"> </span><span class="mtk8">&#39;email&#39;</span><span class="mtk1">,</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">type:</span><span class="mtk1"> </span><span class="mtk8">&#39;email&#39;</span><span class="mtk1">,</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">label:</span><span class="mtk1"> </span><span class="mtk8">&#39;Email&#39;</span><span class="mtk1">,</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> },</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> {</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">key:</span><span class="mtk1"> </span><span class="mtk8">&#39;birthDate&#39;</span><span class="mtk1">,</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">type:</span><span class="mtk1"> </span><span class="mtk8">&#39;date&#39;</span><span class="mtk1">,</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">label:</span><span class="mtk1"> </span><span class="mtk8">&#39;Date of Birth&#39;</span><span class="mtk1">,</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> },</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> {</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">key:</span><span class="mtk1"> </span><span class="mtk8">&#39;isEdit&#39;</span><span class="mtk1">,</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">type:</span><span class="mtk1"> </span><span class="mtk8">&#39;isEdit&#39;</span><span class="mtk1">,</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">label:</span><span class="mtk1"> </span><span class="mtk8">&#39;&#39;</span><span class="mtk1">,</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> },</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1">];</span></span></span></code></pre> <p>Now in the template, we can pass the <code>required</code> attribute the value from <code>UserColumns</code> to determine whether it’s required or not:</p> <pre class="grvsc-container grvsc-has-line-highlighting default-dark" data-language="html" data-index="2"><code class="grvsc-code"><span class="grvsc-line"><span class="grvsc-source"><span class="mtk17">&lt;</span><span class="mtk4">mat-form-field</span><span class="mtk1"> </span><span class="mtk12">class</span><span class="mtk1">=</span><span class="mtk8">&quot;form-input&quot;</span><span class="mtk1"> </span><span class="mtk12">*ngSwitchDefault</span><span class="mtk17">&gt;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk17">&lt;</span><span class="mtk4">input</span></span></span> <span class="grvsc-line grvsc-line-highlighted"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">[required]</span><span class="mtk1">=</span><span class="mtk8">&quot;col.required&quot;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">[type]</span><span class="mtk1">=</span><span class="mtk8">&quot;col.type&quot;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">matInput</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">[(ngModel)]</span><span class="mtk1">=</span><span class="mtk8">&quot;element[col.key]&quot;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk17">/&gt;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk17">&lt;/</span><span class="mtk4">mat-form-field</span><span class="mtk17">&gt;</span></span></span></code></pre> <p>Below we can see how <code>firstName</code> is the only column being validated:</p> <p><span class="gatsby-resp-image-wrapper" style="position: relative; display: block; margin-left: auto; margin-right: auto; max-width: 720px; " > <a class="gatsby-resp-image-link" href="/static/ed18db4f66311fd1f04487f0536caece/2bef9/image-2-1024x305.png" style="display: block" target="_blank" rel="noopener" > <span class="gatsby-resp-image-background-image" style="padding-bottom: 30%; position: relative; bottom: 0; left: 0; background-image: url('data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABQAAAAGCAIAAABM9SnKAAAACXBIWXMAAAsTAAALEwEAmpwYAAABIElEQVR42iVPy26CQBTli9o0CovycJhhGLAzvAJaZePGpC4oCFHLN9hEo4nfUP+yRzyLyc15zD1X+7vfvzabruuqqqrrpm277wHb7bYaUNd127ZP8sk0TbNer2+3m/Z7PL69vlAysc13SogQwrIs0zQ9zwuCgBDiOM5sNkvT1Pf9KIo457ZtG4aBfdr5fDYNXQk/ZFSGQRzHkJHEUBSFlFL4/mq1KssS+cVigTxURmnf99rpdNJHI8E5c1344H5ojGGAWyqJhctymec5YqgAnlLqTCaHw0G7Xq8uIXCAEgPoAJiyLKOMepyrSIVhCNJ1XeZ5Uik6Hvf7vXa5XEChKl588biNc5wax8nnfB4pBSlJkul0CgPy6PWBdrr+s9v9AwqydV/aRQ6MAAAAAElFTkSuQmCC'); background-size: cover; display: block;" ></span> <img class="gatsby-resp-image-image" alt="Validate Angular Table" title="" src="/static/ed18db4f66311fd1f04487f0536caece/37523/image-2-1024x305.png" srcset="/static/ed18db4f66311fd1f04487f0536caece/e9ff0/image-2-1024x305.png 180w, /static/ed18db4f66311fd1f04487f0536caece/f21e7/image-2-1024x305.png 360w, /static/ed18db4f66311fd1f04487f0536caece/37523/image-2-1024x305.png 720w, /static/ed18db4f66311fd1f04487f0536caece/2bef9/image-2-1024x305.png 1024w" sizes="(max-width: 720px) 100vw, 720px" style="width:100%;height:100%;margin:0;vertical-align:middle;position:absolute;top:0;left:0;" loading="lazy" decoding="async" /> </a> </span></p> <h2 id="pattern-validation" style="position:relative;"><a href="#pattern-validation" aria-label="pattern validation permalink" class="anchor before"><svg aria-hidden="true" focusable="false" height="16" version="1.1" viewBox="0 0 16 16" width="16"><path fill-rule="evenodd" d="M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z"></path></svg></a>Pattern Validation</h2> <p>Another type of validation is the pattern attribute that specifies a regular expression where the input value is checked against. That’s especially useful if the value entered by the user has to contain certain characters or strings.</p> <p>A good use case is the email address field. For example, we can add a pattern validation to <code>UserColumns</code> that requires an email to have ’@’ character:</p> <pre class="grvsc-container grvsc-has-line-highlighting default-dark" data-language="ts" data-index="3"><code class="grvsc-code"><span class="grvsc-line"><span class="grvsc-source"><span class="mtk15">export</span><span class="mtk1"> </span><span class="mtk4">const</span><span class="mtk1"> </span><span class="mtk12">UserColumns</span><span class="mtk1"> = [</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> {</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">key:</span><span class="mtk1"> </span><span class="mtk8">&#39;isSelected&#39;</span><span class="mtk1">,</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">type:</span><span class="mtk1"> </span><span class="mtk8">&#39;isSelected&#39;</span><span class="mtk1">,</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">label:</span><span class="mtk1"> </span><span class="mtk8">&#39;&#39;</span><span class="mtk1">,</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> },</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> {</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">key:</span><span class="mtk1"> </span><span class="mtk8">&#39;firstName&#39;</span><span class="mtk1">,</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">type:</span><span class="mtk1"> </span><span class="mtk8">&#39;text&#39;</span><span class="mtk1">,</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">label:</span><span class="mtk1"> </span><span class="mtk8">&#39;First Name&#39;</span><span class="mtk1">,</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">required:</span><span class="mtk1"> </span><span class="mtk4">true</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> },</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> {</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">key:</span><span class="mtk1"> </span><span class="mtk8">&#39;lastName&#39;</span><span class="mtk1">,</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">type:</span><span class="mtk1"> </span><span class="mtk8">&#39;text&#39;</span><span class="mtk1">,</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">label:</span><span class="mtk1"> </span><span class="mtk8">&#39;Last Name&#39;</span><span class="mtk1">,</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> },</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> {</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">key:</span><span class="mtk1"> </span><span class="mtk8">&#39;email&#39;</span><span class="mtk1">,</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">type:</span><span class="mtk1"> </span><span class="mtk8">&#39;email&#39;</span><span class="mtk1">,</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">label:</span><span class="mtk1"> </span><span class="mtk8">&#39;Email&#39;</span><span class="mtk1">,</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">required:</span><span class="mtk1"> </span><span class="mtk4">true</span><span class="mtk1">,</span></span></span> <span class="grvsc-line grvsc-line-highlighted"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">pattern:</span><span class="mtk1"> </span><span class="mtk8">&#39;.+@.+&#39;</span><span class="mtk1">,</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> },</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> {</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">key:</span><span class="mtk1"> </span><span class="mtk8">&#39;birthDate&#39;</span><span class="mtk1">,</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">type:</span><span class="mtk1"> </span><span class="mtk8">&#39;date&#39;</span><span class="mtk1">,</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">label:</span><span class="mtk1"> </span><span class="mtk8">&#39;Date of Birth&#39;</span><span class="mtk1">,</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> },</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> {</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">key:</span><span class="mtk1"> </span><span class="mtk8">&#39;isEdit&#39;</span><span class="mtk1">,</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">type:</span><span class="mtk1"> </span><span class="mtk8">&#39;isEdit&#39;</span><span class="mtk1">,</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">label:</span><span class="mtk1"> </span><span class="mtk8">&#39;&#39;</span><span class="mtk1">,</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> },</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1">];</span></span></span></code></pre> <p>Then, similar to the previous approach, the <code>pattern</code> property will be passed as an attribute value to the input field:</p> <pre class="grvsc-container grvsc-has-line-highlighting default-dark" data-language="html" data-index="4"><code class="grvsc-code"><span class="grvsc-line"><span class="grvsc-source"><span class="mtk17">&lt;</span><span class="mtk4">mat-form-field</span><span class="mtk1"> </span><span class="mtk12">class</span><span class="mtk1">=</span><span class="mtk8">&quot;form-input&quot;</span><span class="mtk1"> </span><span class="mtk12">*ngSwitchDefault</span><span class="mtk17">&gt;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk17">&lt;</span><span class="mtk4">input</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">[required]</span><span class="mtk1">=</span><span class="mtk8">&quot;col.required&quot;</span></span></span> <span class="grvsc-line grvsc-line-highlighted"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">[pattern]</span><span class="mtk1">=</span><span class="mtk8">&quot;col.pattern&quot;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">[type]</span><span class="mtk1">=</span><span class="mtk8">&quot;col.type&quot;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">matInput</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">[(ngModel)]</span><span class="mtk1">=</span><span class="mtk8">&quot;element[col.key]&quot;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk17">/&gt;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk17">&lt;/</span><span class="mtk4">mat-form-field</span><span class="mtk17">&gt;</span></span></span></code></pre> <p>Now we should have the email input field validating if it doesn’t match the specified criteria:</p> <p><span class="gatsby-resp-image-wrapper" style="position: relative; display: block; margin-left: auto; margin-right: auto; max-width: 720px; " > <a class="gatsby-resp-image-link" href="/static/c5f1696dbd3c73285266d2c524c7caa2/2bef9/image-5-1024x283.png" style="display: block" target="_blank" rel="noopener" > <span class="gatsby-resp-image-background-image" style="padding-bottom: 27.77777777777778%; position: relative; bottom: 0; left: 0; background-image: url('data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABQAAAAGCAIAAABM9SnKAAAACXBIWXMAAAsTAAALEwEAmpwYAAAA6klEQVR42j2P7Y5EMBSGXZJfs8wQqlVaWkN2PkgkLsIvTBA3vq92d5806dOTvOecOvM8H8fxMWzbtu/7sizWP39Ynw3TNMHXdR3H0blcvqIoul6vvu/HcQyH4AkJbrez6vtFUWitKaWc8yzLPM8LgsB1XQclISWqaZoqpZUqIXjqssxxM5Yy2nXdMAx1XT8NiOR5ju5nWOuKGjBBCAFhjCGMQwnBeYP2XVXVt4EQgu5hGDowKSUzIMnPYSdlUVRaZ5zTJGnbtu/7+n5/GGwYmzskSaQQNgDBzr9hpbCnXaRpmufrZX8O/if/APCBcL0lAzfFAAAAAElFTkSuQmCC'); background-size: cover; display: block;" ></span> <img class="gatsby-resp-image-image" alt="Validate Angular Table" title="" src="/static/c5f1696dbd3c73285266d2c524c7caa2/37523/image-5-1024x283.png" srcset="/static/c5f1696dbd3c73285266d2c524c7caa2/e9ff0/image-5-1024x283.png 180w, /static/c5f1696dbd3c73285266d2c524c7caa2/f21e7/image-5-1024x283.png 360w, /static/c5f1696dbd3c73285266d2c524c7caa2/37523/image-5-1024x283.png 720w, /static/c5f1696dbd3c73285266d2c524c7caa2/2bef9/image-5-1024x283.png 1024w" sizes="(max-width: 720px) 100vw, 720px" style="width:100%;height:100%;margin:0;vertical-align:middle;position:absolute;top:0;left:0;" loading="lazy" decoding="async" /> </a> </span></p> <h2 id="enabledisable-row-submit" style="position:relative;"><a href="#enabledisable-row-submit" aria-label="enabledisable row submit permalink" class="anchor before"><svg aria-hidden="true" focusable="false" height="16" version="1.1" viewBox="0 0 16 16" width="16"><path fill-rule="evenodd" d="M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z"></path></svg></a>Enable/disable row submit</h2> <p>So far, we’ve validated input fields and showed the red error from Material input. But that doesn’t stop the user from submitting the row with invalid values. So we need a way to keep track of invalid rows and fields to disable the submit (“Done”) button and prevent users from proceeding with invalid changes.</p> <p>Since we have ids for every row, we can create a key/value object representing the id as key and the validated fields as value. For example:</p> <pre class="grvsc-container default-dark" data-language="ts" data-index="5"><code class="grvsc-code"><span class="grvsc-line"><span class="grvsc-source"><span class="mtk1">{</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk8">&quot;1&quot;</span><span class="mtk1">: {</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk8">&quot;firstName&quot;</span><span class="mtk12">:</span><span class="mtk1"> </span><span class="mtk4">false</span><span class="mtk1">,</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk8">&quot;lastName&quot;</span><span class="mtk12">:</span><span class="mtk1"> </span><span class="mtk4">true</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> },</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk8">&quot;2&quot;</span><span class="mtk1">: {</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk8">&quot;email&quot;</span><span class="mtk12">:</span><span class="mtk1"> </span><span class="mtk4">false</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> }</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1">}</span></span></span></code></pre> <p>The idea is to start with an empty object and dynamically add the validated fields while input changes. Let’s go through the required steps:</p> <ol> <li>Add an input <code>change</code> listener in the template and pass it the event, id, and column key:</li> </ol> <pre class="grvsc-container grvsc-has-line-highlighting default-dark" data-language="html" data-index="6"><code class="grvsc-code"><span class="grvsc-line"><span class="grvsc-source"><span class="mtk17">&lt;</span><span class="mtk4">mat-form-field</span><span class="mtk1"> </span><span class="mtk12">class</span><span class="mtk1">=</span><span class="mtk8">&quot;form-input&quot;</span><span class="mtk1"> </span><span class="mtk12">*ngSwitchDefault</span><span class="mtk17">&gt;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk17">&lt;</span><span class="mtk4">input</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">matInput</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">[required]</span><span class="mtk1">=</span><span class="mtk8">&quot;col.required&quot;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">[pattern]</span><span class="mtk1">=</span><span class="mtk8">&quot;col.pattern&quot;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">[type]</span><span class="mtk1">=</span><span class="mtk8">&quot;col.type&quot;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">[(ngModel)]</span><span class="mtk1">=</span><span class="mtk8">&quot;element[col.key]&quot;</span></span></span> <span class="grvsc-line grvsc-line-highlighted"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">(change)</span><span class="mtk1">=</span><span class="mtk8">&quot;inputHandler($event, element.id, col.key)&quot;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk17">/&gt;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk17">&lt;/</span><span class="mtk4">mat-form-field</span><span class="mtk17">&gt;</span></span></span></code></pre> <ol start="2"> <li>Create a new empty <code>valid</code> object and an <code>inputHandler</code> function in the component class. The function will use the validity value from the event’s target object to attach it to the field:</li> </ol> <pre class="grvsc-container default-dark" data-language="ts" data-index="7"><code class="grvsc-code"><span class="grvsc-line"><span class="grvsc-source"><span class="mtk1">valid: </span><span class="mtk12">any</span><span class="mtk1"> = {};</span></span></span> <span class="grvsc-line"><span class="grvsc-source"></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk11">inputHandler</span><span class="mtk1">(</span><span class="mtk12">e</span><span class="mtk1">: </span><span class="mtk12">any</span><span class="mtk1">, </span><span class="mtk12">id</span><span class="mtk1">: </span><span class="mtk12">number</span><span class="mtk1">, </span><span class="mtk12">key</span><span class="mtk1">: </span><span class="mtk12">string</span><span class="mtk1">) {</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk15">if</span><span class="mtk1"> (!</span><span class="mtk4">this</span><span class="mtk1">.</span><span class="mtk12">valid</span><span class="mtk1">[</span><span class="mtk12">id</span><span class="mtk1">]) {</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk4">this</span><span class="mtk1">.</span><span class="mtk12">valid</span><span class="mtk1">[</span><span class="mtk12">id</span><span class="mtk1">] = {};</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> }</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk4">this</span><span class="mtk1">.</span><span class="mtk12">valid</span><span class="mtk1">[</span><span class="mtk12">id</span><span class="mtk1">][</span><span class="mtk12">key</span><span class="mtk1">] = </span><span class="mtk12">e</span><span class="mtk1">.</span><span class="mtk12">target</span><span class="mtk1">.</span><span class="mtk12">validity</span><span class="mtk1">.</span><span class="mtk12">valid</span><span class="mtk1">;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1">}</span></span></span></code></pre> <p>The <code>key</code> parameter represents the current modified field (e.g. firstName). Also, we need first to check if the <code>id</code> does not exist in the object so we can instantiate a value and avoid an uncaught reference error.</p> <ol start="3"> <li>Create a function that conditionally disables the submit button based on whether or not the row id has any invalid values:</li> </ol> <pre class="grvsc-container default-dark" data-language="ts" data-index="8"><code class="grvsc-code"><span class="grvsc-line"><span class="grvsc-source"><span class="mtk11">disableSubmit</span><span class="mtk1">(</span><span class="mtk12">id</span><span class="mtk1">: </span><span class="mtk12">number</span><span class="mtk1">) {</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk15">if</span><span class="mtk1"> (</span><span class="mtk4">this</span><span class="mtk1">.</span><span class="mtk12">valid</span><span class="mtk1">[</span><span class="mtk12">id</span><span class="mtk1">]) {</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk15">return</span><span class="mtk1"> </span><span class="mtk10">Object</span><span class="mtk1">.</span><span class="mtk11">values</span><span class="mtk1">(</span><span class="mtk4">this</span><span class="mtk1">.</span><span class="mtk12">valid</span><span class="mtk1">[</span><span class="mtk12">id</span><span class="mtk1">]).</span><span class="mtk11">some</span><span class="mtk1">((</span><span class="mtk12">item</span><span class="mtk1">) </span><span class="mtk4">=&gt;</span><span class="mtk1"> </span><span class="mtk12">item</span><span class="mtk1"> === </span><span class="mtk4">false</span><span class="mtk1">);</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> }</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk15">return</span><span class="mtk1"> </span><span class="mtk4">false</span><span class="mtk1">;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1">}</span></span></span></code></pre> <p>The function above converts the <code>valid</code> object with the specified id to a list of values and checks if there is any invalid field.</p> <p>Finally, we need to attach that function to the <code>disable</code> attribute in the template:</p> <pre class="grvsc-container grvsc-has-line-highlighting default-dark" data-language="html" data-index="9"><code class="grvsc-code"><span class="grvsc-line"><span class="grvsc-source"><span class="mtk17">&lt;</span><span class="mtk4">div</span><span class="mtk1"> </span><span class="mtk12">class</span><span class="mtk1">=</span><span class="mtk8">&quot;btn-edit&quot;</span><span class="mtk1"> </span><span class="mtk12">*ngSwitchCase</span><span class="mtk1">=</span><span class="mtk8">&quot;&#39;isEdit&#39;&quot;</span><span class="mtk17">&gt;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk17">&lt;</span><span class="mtk4">button</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">mat-button</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">(click)</span><span class="mtk1">=</span><span class="mtk8">&quot;editRow(element)&quot;</span></span></span> <span class="grvsc-line grvsc-line-highlighted"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">[disabled]</span><span class="mtk1">=</span><span class="mtk8">&quot;disableSubmit(element.id)&quot;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk17">&gt;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> Done</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk17">&lt;/</span><span class="mtk4">button</span><span class="mtk17">&gt;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk17">&lt;/</span><span class="mtk4">div</span><span class="mtk17">&gt;</span></span></span></code></pre> <p>Below we can see how the button is disabled when the field is invalid:</p> <p><span class="gatsby-resp-image-wrapper" style="position: relative; display: block; margin-left: auto; margin-right: auto; max-width: 720px; " > <a class="gatsby-resp-image-link" href="/static/29e946d07db475b2437b3b3176cebb2f/2bef9/image-1-1024x303.png" style="display: block" target="_blank" rel="noopener" > <span class="gatsby-resp-image-background-image" style="padding-bottom: 29.444444444444446%; position: relative; bottom: 0; left: 0; background-image: url('data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABQAAAAGCAIAAABM9SnKAAAACXBIWXMAAAsTAAALEwEAmpwYAAABEElEQVR42iVPO66DMBDkQqkSKSD+EBtj+xE+BSgvHeegAV6AhiZBAuUmiMO9EWxhzc7u7IyVbduauhmGoW3b1+sF8LdX33XtXiD7vgdomqaua4Cu66qqWtdVeb/fp9PJ0HXtetV13bZtTdNUVbUsy7YtYMMw4jgOw9DzPM45eJCQjOOoLMtimSZnjPi+4DxNU0opIQSgKAopJWNhWZaPxwMMXiEEpqZpTtOkzPPsui4o3/eDIMD27XYDlkImSYIW5O/zmWXZ/X7P85wxhghI9fl8lO/367oOjoHCHmy9vYSQcZwAYBRFETS4CBu0knP7cpkO8ZETA0oDuAE7jgPlEZtQAhJ/dvcilP4I7p3PcP4HaqZ8Qgq+XH0AAAAASUVORK5CYII='); background-size: cover; display: block;" ></span> <img class="gatsby-resp-image-image" alt="Validate Angular Table" title="" src="/static/29e946d07db475b2437b3b3176cebb2f/37523/image-1-1024x303.png" srcset="/static/29e946d07db475b2437b3b3176cebb2f/e9ff0/image-1-1024x303.png 180w, /static/29e946d07db475b2437b3b3176cebb2f/f21e7/image-1-1024x303.png 360w, /static/29e946d07db475b2437b3b3176cebb2f/37523/image-1-1024x303.png 720w, /static/29e946d07db475b2437b3b3176cebb2f/2bef9/image-1-1024x303.png 1024w" sizes="(max-width: 720px) 100vw, 720px" style="width:100%;height:100%;margin:0;vertical-align:middle;position:absolute;top:0;left:0;" loading="lazy" decoding="async" /> </a> </span></p> <p>Here is the entire template and component class we did for this section:</p> <pre class="grvsc-container grvsc-has-line-highlighting default-dark" data-language="ts" data-index="10"><code class="grvsc-code"><span class="grvsc-line"><span class="grvsc-source"><span class="mtk15">import</span><span class="mtk1"> { </span><span class="mtk12">Component</span><span class="mtk1">, </span><span class="mtk12">DefaultIterableDiffer</span><span class="mtk1">, </span><span class="mtk12">OnInit</span><span class="mtk1"> } </span><span class="mtk15">from</span><span class="mtk1"> </span><span class="mtk8">&#39;@angular/core&#39;</span><span class="mtk1">;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk15">import</span><span class="mtk1"> { </span><span class="mtk12">MatDialog</span><span class="mtk1"> } </span><span class="mtk15">from</span><span class="mtk1"> </span><span class="mtk8">&#39;@angular/material/dialog&#39;</span><span class="mtk1">;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk15">import</span><span class="mtk1"> { </span><span class="mtk12">MatTableDataSource</span><span class="mtk1"> } </span><span class="mtk15">from</span><span class="mtk1"> </span><span class="mtk8">&#39;@angular/material/table&#39;</span><span class="mtk1">;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk15">import</span><span class="mtk1"> { </span><span class="mtk12">ConfirmDialogComponent</span><span class="mtk1"> } </span><span class="mtk15">from</span><span class="mtk1"> </span><span class="mtk8">&#39;./confirm-dialog/confirm-dialog.component&#39;</span><span class="mtk1">;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk15">import</span><span class="mtk1"> { </span><span class="mtk12">User</span><span class="mtk1">, </span><span class="mtk12">UserColumns</span><span class="mtk1"> } </span><span class="mtk15">from</span><span class="mtk1"> </span><span class="mtk8">&#39;./model/user&#39;</span><span class="mtk1">;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk15">import</span><span class="mtk1"> { </span><span class="mtk12">UserService</span><span class="mtk1"> } </span><span class="mtk15">from</span><span class="mtk1"> </span><span class="mtk8">&#39;./services/user.service&#39;</span><span class="mtk1">;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1">@</span><span class="mtk11">Component</span><span class="mtk1">({</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">selector:</span><span class="mtk1"> </span><span class="mtk8">&#39;app-root&#39;</span><span class="mtk1">,</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">templateUrl:</span><span class="mtk1"> </span><span class="mtk8">&#39;./app.component.html&#39;</span><span class="mtk1">,</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">styleUrls:</span><span class="mtk1"> [</span><span class="mtk8">&#39;./app.component.scss&#39;</span><span class="mtk1">],</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1">})</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk15">export</span><span class="mtk1"> </span><span class="mtk4">class</span><span class="mtk1"> </span><span class="mtk10">AppComponent</span><span class="mtk1"> {</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">displayedColumns</span><span class="mtk1">: </span><span class="mtk10">string</span><span class="mtk1">[] = </span><span class="mtk12">UserColumns</span><span class="mtk1">.</span><span class="mtk11">map</span><span class="mtk1">((</span><span class="mtk12">col</span><span class="mtk1">) </span><span class="mtk4">=&gt;</span><span class="mtk1"> </span><span class="mtk12">col</span><span class="mtk1">.</span><span class="mtk12">key</span><span class="mtk1">);</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">columnsSchema</span><span class="mtk1">: </span><span class="mtk10">any</span><span class="mtk1"> = </span><span class="mtk12">UserColumns</span><span class="mtk1">;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">dataSource</span><span class="mtk1"> = </span><span class="mtk4">new</span><span class="mtk1"> </span><span class="mtk10">MatTableDataSource</span><span class="mtk1">&lt;</span><span class="mtk10">User</span><span class="mtk1">&gt;();</span></span></span> <span class="grvsc-line grvsc-line-highlighted"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">valid</span><span class="mtk1">: </span><span class="mtk10">any</span><span class="mtk1"> = {};</span></span></span> <span class="grvsc-line"><span class="grvsc-source"></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk4">constructor</span><span class="mtk1">(</span><span class="mtk4">public</span><span class="mtk1"> </span><span class="mtk12">dialog</span><span class="mtk1">: </span><span class="mtk10">MatDialog</span><span class="mtk1">, </span><span class="mtk4">private</span><span class="mtk1"> </span><span class="mtk12">userService</span><span class="mtk1">: </span><span class="mtk10">UserService</span><span class="mtk1">) {}</span></span></span> <span class="grvsc-line"><span class="grvsc-source"></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk11">ngOnInit</span><span class="mtk1">() {</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk4">this</span><span class="mtk1">.</span><span class="mtk12">userService</span><span class="mtk1">.</span><span class="mtk11">getUsers</span><span class="mtk1">().</span><span class="mtk11">subscribe</span><span class="mtk1">((</span><span class="mtk12">res</span><span class="mtk1">: </span><span class="mtk10">any</span><span class="mtk1">) </span><span class="mtk4">=&gt;</span><span class="mtk1"> {</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk4">this</span><span class="mtk1">.</span><span class="mtk12">dataSource</span><span class="mtk1">.</span><span class="mtk12">data</span><span class="mtk1"> = </span><span class="mtk12">res</span><span class="mtk1">;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> });</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> }</span></span></span> <span class="grvsc-line"><span class="grvsc-source"></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk11">editRow</span><span class="mtk1">(</span><span class="mtk12">row</span><span class="mtk1">: </span><span class="mtk10">User</span><span class="mtk1">) {</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk15">if</span><span class="mtk1"> (</span><span class="mtk12">row</span><span class="mtk1">.</span><span class="mtk12">id</span><span class="mtk1"> === </span><span class="mtk7">0</span><span class="mtk1">) {</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk4">this</span><span class="mtk1">.</span><span class="mtk12">userService</span><span class="mtk1">.</span><span class="mtk11">addUser</span><span class="mtk1">(</span><span class="mtk12">row</span><span class="mtk1">).</span><span class="mtk11">subscribe</span><span class="mtk1">((</span><span class="mtk12">newUser</span><span class="mtk1">: </span><span class="mtk10">User</span><span class="mtk1">) </span><span class="mtk4">=&gt;</span><span class="mtk1"> {</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">row</span><span class="mtk1">.</span><span class="mtk12">id</span><span class="mtk1"> = </span><span class="mtk12">newUser</span><span class="mtk1">.</span><span class="mtk12">id</span><span class="mtk1">;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">row</span><span class="mtk1">.</span><span class="mtk12">isEdit</span><span class="mtk1"> = </span><span class="mtk4">false</span><span class="mtk1">;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> });</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> } </span><span class="mtk15">else</span><span class="mtk1"> {</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk4">this</span><span class="mtk1">.</span><span class="mtk12">userService</span><span class="mtk1">.</span><span class="mtk11">updateUser</span><span class="mtk1">(</span><span class="mtk12">row</span><span class="mtk1">).</span><span class="mtk11">subscribe</span><span class="mtk1">(() </span><span class="mtk4">=&gt;</span><span class="mtk1"> (</span><span class="mtk12">row</span><span class="mtk1">.</span><span class="mtk12">isEdit</span><span class="mtk1"> = </span><span class="mtk4">false</span><span class="mtk1">));</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> }</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> }</span></span></span> <span class="grvsc-line"><span class="grvsc-source"></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk11">addRow</span><span class="mtk1">() {</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk4">const</span><span class="mtk1"> </span><span class="mtk12">newRow</span><span class="mtk1">: </span><span class="mtk10">User</span><span class="mtk1"> = {</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">id:</span><span class="mtk1"> </span><span class="mtk7">0</span><span class="mtk1">,</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">firstName:</span><span class="mtk1"> </span><span class="mtk8">&#39;&#39;</span><span class="mtk1">,</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">lastName:</span><span class="mtk1"> </span><span class="mtk8">&#39;&#39;</span><span class="mtk1">,</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">email:</span><span class="mtk1"> </span><span class="mtk8">&#39;&#39;</span><span class="mtk1">,</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">birthDate:</span><span class="mtk1"> </span><span class="mtk8">&#39;&#39;</span><span class="mtk1">,</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">isEdit:</span><span class="mtk1"> </span><span class="mtk4">true</span><span class="mtk1">,</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">isSelected:</span><span class="mtk1"> </span><span class="mtk4">false</span><span class="mtk1">,</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> };</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk4">this</span><span class="mtk1">.</span><span class="mtk12">dataSource</span><span class="mtk1">.</span><span class="mtk12">data</span><span class="mtk1"> = [</span><span class="mtk12">newRow</span><span class="mtk1">, ...</span><span class="mtk4">this</span><span class="mtk1">.</span><span class="mtk12">dataSource</span><span class="mtk1">.</span><span class="mtk12">data</span><span class="mtk1">];</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> }</span></span></span> <span class="grvsc-line"><span class="grvsc-source"></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk11">removeRow</span><span class="mtk1">(</span><span class="mtk12">id</span><span class="mtk1">: </span><span class="mtk10">number</span><span class="mtk1">) {</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk4">this</span><span class="mtk1">.</span><span class="mtk12">userService</span><span class="mtk1">.</span><span class="mtk11">deleteUser</span><span class="mtk1">(</span><span class="mtk12">id</span><span class="mtk1">).</span><span class="mtk11">subscribe</span><span class="mtk1">(() </span><span class="mtk4">=&gt;</span><span class="mtk1"> {</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk4">this</span><span class="mtk1">.</span><span class="mtk12">dataSource</span><span class="mtk1">.</span><span class="mtk12">data</span><span class="mtk1"> = </span><span class="mtk4">this</span><span class="mtk1">.</span><span class="mtk12">dataSource</span><span class="mtk1">.</span><span class="mtk12">data</span><span class="mtk1">.</span><span class="mtk11">filter</span><span class="mtk1">(</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> (</span><span class="mtk12">u</span><span class="mtk1">: </span><span class="mtk10">User</span><span class="mtk1">) </span><span class="mtk4">=&gt;</span><span class="mtk1"> </span><span class="mtk12">u</span><span class="mtk1">.</span><span class="mtk12">id</span><span class="mtk1"> !== </span><span class="mtk12">id</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> );</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> });</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> }</span></span></span> <span class="grvsc-line"><span class="grvsc-source"></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk11">removeSelectedRows</span><span class="mtk1">() {</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk4">const</span><span class="mtk1"> </span><span class="mtk12">users</span><span class="mtk1"> = </span><span class="mtk4">this</span><span class="mtk1">.</span><span class="mtk12">dataSource</span><span class="mtk1">.</span><span class="mtk12">data</span><span class="mtk1">.</span><span class="mtk11">filter</span><span class="mtk1">((</span><span class="mtk12">u</span><span class="mtk1">: </span><span class="mtk10">User</span><span class="mtk1">) </span><span class="mtk4">=&gt;</span><span class="mtk1"> </span><span class="mtk12">u</span><span class="mtk1">.</span><span class="mtk12">isSelected</span><span class="mtk1">);</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk4">this</span><span class="mtk1">.</span><span class="mtk12">dialog</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> .</span><span class="mtk11">open</span><span class="mtk1">(</span><span class="mtk12">ConfirmDialogComponent</span><span class="mtk1">)</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> .</span><span class="mtk11">afterClosed</span><span class="mtk1">()</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> .</span><span class="mtk11">subscribe</span><span class="mtk1">((</span><span class="mtk12">confirm</span><span class="mtk1">) </span><span class="mtk4">=&gt;</span><span class="mtk1"> {</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk15">if</span><span class="mtk1"> (</span><span class="mtk12">confirm</span><span class="mtk1">) {</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk4">this</span><span class="mtk1">.</span><span class="mtk12">userService</span><span class="mtk1">.</span><span class="mtk11">deleteUsers</span><span class="mtk1">(</span><span class="mtk12">users</span><span class="mtk1">).</span><span class="mtk11">subscribe</span><span class="mtk1">(() </span><span class="mtk4">=&gt;</span><span class="mtk1"> {</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk4">this</span><span class="mtk1">.</span><span class="mtk12">dataSource</span><span class="mtk1">.</span><span class="mtk12">data</span><span class="mtk1"> = </span><span class="mtk4">this</span><span class="mtk1">.</span><span class="mtk12">dataSource</span><span class="mtk1">.</span><span class="mtk12">data</span><span class="mtk1">.</span><span class="mtk11">filter</span><span class="mtk1">(</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> (</span><span class="mtk12">u</span><span class="mtk1">: </span><span class="mtk10">User</span><span class="mtk1">) </span><span class="mtk4">=&gt;</span><span class="mtk1"> !</span><span class="mtk12">u</span><span class="mtk1">.</span><span class="mtk12">isSelected</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> );</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> });</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> }</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> });</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> }</span></span></span> <span class="grvsc-line"><span class="grvsc-source"></span></span> <span class="grvsc-line grvsc-line-highlighted"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk11">inputHandler</span><span class="mtk1">(</span><span class="mtk12">e</span><span class="mtk1">: </span><span class="mtk10">any</span><span class="mtk1">, </span><span class="mtk12">id</span><span class="mtk1">: </span><span class="mtk10">number</span><span class="mtk1">, </span><span class="mtk12">key</span><span class="mtk1">: </span><span class="mtk10">string</span><span class="mtk1">) {</span></span></span> <span class="grvsc-line grvsc-line-highlighted"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk15">if</span><span class="mtk1"> (!</span><span class="mtk4">this</span><span class="mtk1">.</span><span class="mtk12">valid</span><span class="mtk1">[</span><span class="mtk12">id</span><span class="mtk1">]) {</span></span></span> <span class="grvsc-line grvsc-line-highlighted"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk4">this</span><span class="mtk1">.</span><span class="mtk12">valid</span><span class="mtk1">[</span><span class="mtk12">id</span><span class="mtk1">] = {};</span></span></span> <span class="grvsc-line grvsc-line-highlighted"><span class="grvsc-source"><span class="mtk1"> }</span></span></span> <span class="grvsc-line grvsc-line-highlighted"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk4">this</span><span class="mtk1">.</span><span class="mtk12">valid</span><span class="mtk1">[</span><span class="mtk12">id</span><span class="mtk1">][</span><span class="mtk12">key</span><span class="mtk1">] = </span><span class="mtk12">e</span><span class="mtk1">.</span><span class="mtk12">target</span><span class="mtk1">.</span><span class="mtk12">validity</span><span class="mtk1">.</span><span class="mtk12">valid</span><span class="mtk1">;</span></span></span> <span class="grvsc-line grvsc-line-highlighted"><span class="grvsc-source"><span class="mtk1"> }</span></span></span> <span class="grvsc-line grvsc-line-highlighted"><span class="grvsc-source"></span></span> <span class="grvsc-line grvsc-line-highlighted"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk11">disableSubmit</span><span class="mtk1">(</span><span class="mtk12">id</span><span class="mtk1">: </span><span class="mtk10">number</span><span class="mtk1">) {</span></span></span> <span class="grvsc-line grvsc-line-highlighted"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk15">if</span><span class="mtk1"> (</span><span class="mtk4">this</span><span class="mtk1">.</span><span class="mtk12">valid</span><span class="mtk1">[</span><span class="mtk12">id</span><span class="mtk1">]) {</span></span></span> <span class="grvsc-line grvsc-line-highlighted"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk15">return</span><span class="mtk1"> </span><span class="mtk10">Object</span><span class="mtk1">.</span><span class="mtk11">values</span><span class="mtk1">(</span><span class="mtk4">this</span><span class="mtk1">.</span><span class="mtk12">valid</span><span class="mtk1">[</span><span class="mtk12">id</span><span class="mtk1">]).</span><span class="mtk11">some</span><span class="mtk1">((</span><span class="mtk12">item</span><span class="mtk1">) </span><span class="mtk4">=&gt;</span><span class="mtk1"> </span><span class="mtk12">item</span><span class="mtk1"> === </span><span class="mtk4">false</span><span class="mtk1">);</span></span></span> <span class="grvsc-line grvsc-line-highlighted"><span class="grvsc-source"><span class="mtk1"> }</span></span></span> <span class="grvsc-line grvsc-line-highlighted"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk15">return</span><span class="mtk1"> </span><span class="mtk4">false</span><span class="mtk1">;</span></span></span> <span class="grvsc-line grvsc-line-highlighted"><span class="grvsc-source"><span class="mtk1"> }</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1">}</span></span></span></code></pre> <pre class="grvsc-container grvsc-has-line-highlighting default-dark" data-language="html" data-index="11"><code class="grvsc-code"><span class="grvsc-line"><span class="grvsc-source"><span class="mtk17">&lt;</span><span class="mtk4">article</span><span class="mtk1"> </span><span class="mtk12">class</span><span class="mtk1">=</span><span class="mtk8">&quot;table-header&quot;</span><span class="mtk17">&gt;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk17">&lt;</span><span class="mtk4">button</span><span class="mtk1"> </span><span class="mtk12">class</span><span class="mtk1">=</span><span class="mtk8">&quot;button-remove-rows&quot;</span><span class="mtk1"> </span><span class="mtk12">mat-button</span><span class="mtk1"> </span><span class="mtk12">(click)</span><span class="mtk1">=</span><span class="mtk8">&quot;removeSelectedRows()&quot;</span><span class="mtk17">&gt;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> Remove Rows</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk17">&lt;/</span><span class="mtk4">button</span><span class="mtk17">&gt;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk17">&lt;</span><span class="mtk4">button</span><span class="mtk1"> </span><span class="mtk12">class</span><span class="mtk1">=</span><span class="mtk8">&quot;button-add-row&quot;</span><span class="mtk1"> </span><span class="mtk12">mat-button</span><span class="mtk1"> </span><span class="mtk12">(click)</span><span class="mtk1">=</span><span class="mtk8">&quot;addRow()&quot;</span><span class="mtk17">&gt;</span><span class="mtk1">Add Row</span><span class="mtk17">&lt;/</span><span class="mtk4">button</span><span class="mtk17">&gt;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk17">&lt;/</span><span class="mtk4">article</span><span class="mtk17">&gt;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk17">&lt;</span><span class="mtk4">table</span><span class="mtk1"> </span><span class="mtk12">mat-table</span><span class="mtk1"> </span><span class="mtk12">[dataSource]</span><span class="mtk1">=</span><span class="mtk8">&quot;dataSource&quot;</span><span class="mtk17">&gt;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk17">&lt;</span><span class="mtk4">ng-container</span><span class="mtk1"> </span><span class="mtk12">[matColumnDef]</span><span class="mtk1">=</span><span class="mtk8">&quot;col.key&quot;</span><span class="mtk1"> </span><span class="mtk12">*ngFor</span><span class="mtk1">=</span><span class="mtk8">&quot;let col of columnsSchema&quot;</span><span class="mtk17">&gt;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk17">&lt;</span><span class="mtk4">th</span><span class="mtk1"> </span><span class="mtk12">mat-header-cell</span><span class="mtk1"> </span><span class="mtk12">*matHeaderCellDef</span><span class="mtk17">&gt;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> {{ col.label }}</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk17">&lt;/</span><span class="mtk4">th</span><span class="mtk17">&gt;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk17">&lt;</span><span class="mtk4">td</span><span class="mtk1"> </span><span class="mtk12">mat-cell</span><span class="mtk1"> </span><span class="mtk12">*matCellDef</span><span class="mtk1">=</span><span class="mtk8">&quot;let element&quot;</span><span class="mtk17">&gt;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk17">&lt;</span><span class="mtk4">div</span><span class="mtk1"> </span><span class="mtk12">[ngSwitch]</span><span class="mtk1">=</span><span class="mtk8">&quot;col.type&quot;</span><span class="mtk1"> </span><span class="mtk12">*ngIf</span><span class="mtk1">=</span><span class="mtk8">&quot;!element.isEdit&quot;</span><span class="mtk17">&gt;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk17">&lt;</span><span class="mtk4">ng-container</span><span class="mtk1"> </span><span class="mtk12">*ngSwitchCase</span><span class="mtk1">=</span><span class="mtk8">&quot;&#39;isSelected&#39;&quot;</span><span class="mtk17">&gt;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk17">&lt;</span><span class="mtk4">mat-checkbox</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">(change)</span><span class="mtk1">=</span><span class="mtk8">&quot;element.isSelected = $event.checked&quot;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk17">&gt;&lt;/</span><span class="mtk4">mat-checkbox</span><span class="mtk17">&gt;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk17">&lt;/</span><span class="mtk4">ng-container</span><span class="mtk17">&gt;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk17">&lt;</span><span class="mtk4">div</span><span class="mtk1"> </span><span class="mtk12">class</span><span class="mtk1">=</span><span class="mtk8">&quot;btn-edit&quot;</span><span class="mtk1"> </span><span class="mtk12">*ngSwitchCase</span><span class="mtk1">=</span><span class="mtk8">&quot;&#39;isEdit&#39;&quot;</span><span class="mtk17">&gt;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk17">&lt;</span><span class="mtk4">button</span><span class="mtk1"> </span><span class="mtk12">mat-button</span><span class="mtk1"> </span><span class="mtk12">(click)</span><span class="mtk1">=</span><span class="mtk8">&quot;element.isEdit = !element.isEdit&quot;</span><span class="mtk17">&gt;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> Edit</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk17">&lt;/</span><span class="mtk4">button</span><span class="mtk17">&gt;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk17">&lt;</span><span class="mtk4">button</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">mat-button</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">class</span><span class="mtk1">=</span><span class="mtk8">&quot;button-remove&quot;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">(click)</span><span class="mtk1">=</span><span class="mtk8">&quot;removeRow(element.id)&quot;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk17">&gt;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> Delete</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk17">&lt;/</span><span class="mtk4">button</span><span class="mtk17">&gt;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk17">&lt;/</span><span class="mtk4">div</span><span class="mtk17">&gt;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk17">&lt;</span><span class="mtk4">span</span><span class="mtk1"> </span><span class="mtk12">*ngSwitchCase</span><span class="mtk1">=</span><span class="mtk8">&quot;&#39;date&#39;&quot;</span><span class="mtk17">&gt;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> {{ element[col.key] | date: &#39;mediumDate&#39; }}</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk17">&lt;/</span><span class="mtk4">span</span><span class="mtk17">&gt;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk17">&lt;</span><span class="mtk4">span</span><span class="mtk1"> </span><span class="mtk12">*ngSwitchDefault</span><span class="mtk17">&gt;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> {{ element[col.key] }}</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk17">&lt;/</span><span class="mtk4">span</span><span class="mtk17">&gt;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk17">&lt;/</span><span class="mtk4">div</span><span class="mtk17">&gt;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk17">&lt;</span><span class="mtk4">div</span><span class="mtk1"> </span><span class="mtk12">[ngSwitch]</span><span class="mtk1">=</span><span class="mtk8">&quot;col.type&quot;</span><span class="mtk1"> </span><span class="mtk12">*ngIf</span><span class="mtk1">=</span><span class="mtk8">&quot;element.isEdit&quot;</span><span class="mtk17">&gt;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk17">&lt;</span><span class="mtk4">div</span><span class="mtk1"> </span><span class="mtk12">*ngSwitchCase</span><span class="mtk1">=</span><span class="mtk8">&quot;&#39;isSelected&#39;&quot;</span><span class="mtk17">&gt;&lt;/</span><span class="mtk4">div</span><span class="mtk17">&gt;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk17">&lt;</span><span class="mtk4">div</span><span class="mtk1"> </span><span class="mtk12">class</span><span class="mtk1">=</span><span class="mtk8">&quot;btn-edit&quot;</span><span class="mtk1"> </span><span class="mtk12">*ngSwitchCase</span><span class="mtk1">=</span><span class="mtk8">&quot;&#39;isEdit&#39;&quot;</span><span class="mtk17">&gt;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk17">&lt;</span><span class="mtk4">button</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">mat-button</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">(click)</span><span class="mtk1">=</span><span class="mtk8">&quot;editRow(element)&quot;</span></span></span> <span class="grvsc-line grvsc-line-highlighted"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">[disabled]</span><span class="mtk1">=</span><span class="mtk8">&quot;disableSubmit(element.id)&quot;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk17">&gt;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> Done</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk17">&lt;/</span><span class="mtk4">button</span><span class="mtk17">&gt;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk17">&lt;/</span><span class="mtk4">div</span><span class="mtk17">&gt;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk17">&lt;</span><span class="mtk4">mat-form-field</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">class</span><span class="mtk1">=</span><span class="mtk8">&quot;form-input&quot;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">*ngSwitchCase</span><span class="mtk1">=</span><span class="mtk8">&quot;&#39;date&#39;&quot;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">appearance</span><span class="mtk1">=</span><span class="mtk8">&quot;fill&quot;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk17">&gt;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk17">&lt;</span><span class="mtk4">mat-label</span><span class="mtk17">&gt;</span><span class="mtk1">Choose a date</span><span class="mtk17">&lt;/</span><span class="mtk4">mat-label</span><span class="mtk17">&gt;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk17">&lt;</span><span class="mtk4">input</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">matInput</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">[matDatepicker]</span><span class="mtk1">=</span><span class="mtk8">&quot;picker&quot;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">[(ngModel)]</span><span class="mtk1">=</span><span class="mtk8">&quot;element[col.key]&quot;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk17">/&gt;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk17">&lt;</span><span class="mtk4">mat-datepicker-toggle</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">matSuffix</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">[for]</span><span class="mtk1">=</span><span class="mtk8">&quot;picker&quot;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk17">&gt;&lt;/</span><span class="mtk4">mat-datepicker-toggle</span><span class="mtk17">&gt;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk17">&lt;</span><span class="mtk4">mat-datepicker</span><span class="mtk1"> </span><span class="mtk12">#picker</span><span class="mtk17">&gt;&lt;/</span><span class="mtk4">mat-datepicker</span><span class="mtk17">&gt;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk17">&lt;/</span><span class="mtk4">mat-form-field</span><span class="mtk17">&gt;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk17">&lt;</span><span class="mtk4">mat-form-field</span><span class="mtk1"> </span><span class="mtk12">class</span><span class="mtk1">=</span><span class="mtk8">&quot;form-input&quot;</span><span class="mtk1"> </span><span class="mtk12">*ngSwitchDefault</span><span class="mtk17">&gt;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk17">&lt;</span><span class="mtk4">input</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">matInput</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">[required]</span><span class="mtk1">=</span><span class="mtk8">&quot;col.required&quot;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">[pattern]</span><span class="mtk1">=</span><span class="mtk8">&quot;col.pattern&quot;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">[type]</span><span class="mtk1">=</span><span class="mtk8">&quot;col.type&quot;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">[(ngModel)]</span><span class="mtk1">=</span><span class="mtk8">&quot;element[col.key]&quot;</span></span></span> <span class="grvsc-line grvsc-line-highlighted"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">(change)</span><span class="mtk1">=</span><span class="mtk8">&quot;inputHandler($event, element.id, col.key)&quot;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk17">/&gt;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk17">&lt;/</span><span class="mtk4">mat-form-field</span><span class="mtk17">&gt;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk17">&lt;/</span><span class="mtk4">div</span><span class="mtk17">&gt;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk17">&lt;/</span><span class="mtk4">td</span><span class="mtk17">&gt;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk17">&lt;/</span><span class="mtk4">ng-container</span><span class="mtk17">&gt;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk17">&lt;</span><span class="mtk4">tr</span><span class="mtk1"> </span><span class="mtk12">mat-header-row</span><span class="mtk1"> </span><span class="mtk12">*matHeaderRowDef</span><span class="mtk1">=</span><span class="mtk8">&quot;displayedColumns&quot;</span><span class="mtk17">&gt;&lt;/</span><span class="mtk4">tr</span><span class="mtk17">&gt;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk17">&lt;</span><span class="mtk4">tr</span><span class="mtk1"> </span><span class="mtk12">mat-row</span><span class="mtk1"> </span><span class="mtk12">*matRowDef</span><span class="mtk1">=</span><span class="mtk8">&quot;let row; columns: displayedColumns&quot;</span><span class="mtk17">&gt;&lt;/</span><span class="mtk4">tr</span><span class="mtk17">&gt;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk17">&lt;/</span><span class="mtk4">table</span><span class="mtk17">&gt;</span></span></span></code></pre> <h2 id="summary" style="position:relative;"><a href="#summary" aria-label="summary permalink" class="anchor before"><svg aria-hidden="true" focusable="false" height="16" version="1.1" viewBox="0 0 16 16" width="16"><path fill-rule="evenodd" d="M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z"></path></svg></a>Summary</h2> <p>If you made it to this section, pat yourself on the back! You just learned how to:</p> <ul> <li>Add input field validation for table rows</li> <li>Leverage built-in HTML form validations for adding custom validations</li> <li>Define dynamic validations through the column schema</li> </ul> <p>You can access the <a href="https://github.com/muhimasri/angular-dynamic-table">complete repository here</a>.</p> <p>Bye for now 👋</p> <style class="grvsc-styles"> .grvsc-container { overflow: auto; position: relative; -webkit-overflow-scrolling: touch; padding-top: 1rem; padding-top: var(--grvsc-padding-top, var(--grvsc-padding-v, 1rem)); padding-bottom: 1rem; padding-bottom: var(--grvsc-padding-bottom, var(--grvsc-padding-v, 1rem)); border-radius: 8px; border-radius: var(--grvsc-border-radius, 8px); font-feature-settings: normal; line-height: 1.4; } .grvsc-code { display: table; } .grvsc-line { display: table-row; box-sizing: border-box; width: 100%; position: relative; } .grvsc-line > * { position: relative; } .grvsc-gutter-pad { display: table-cell; padding-left: 0.75rem; padding-left: calc(var(--grvsc-padding-left, var(--grvsc-padding-h, 1.5rem)) / 2); } .grvsc-gutter { display: table-cell; -webkit-user-select: none; -moz-user-select: none; user-select: none; } .grvsc-gutter::before { content: attr(data-content); } .grvsc-source { display: table-cell; padding-left: 1.5rem; padding-left: var(--grvsc-padding-left, var(--grvsc-padding-h, 1.5rem)); padding-right: 1.5rem; padding-right: var(--grvsc-padding-right, var(--grvsc-padding-h, 1.5rem)); } .grvsc-source:empty::after { content: ' '; -webkit-user-select: none; -moz-user-select: none; user-select: none; } .grvsc-gutter + .grvsc-source { padding-left: 0.75rem; padding-left: calc(var(--grvsc-padding-left, var(--grvsc-padding-h, 1.5rem)) / 2); } /* Line transformer styles */ .grvsc-has-line-highlighting > .grvsc-code > .grvsc-line::before { content: ' '; position: absolute; width: 100%; } .grvsc-line-diff-add::before { background-color: var(--grvsc-line-diff-add-background-color, rgba(0, 255, 60, 0.2)); } .grvsc-line-diff-del::before { background-color: var(--grvsc-line-diff-del-background-color, rgba(255, 0, 20, 0.2)); } .grvsc-line-number { padding: 0 2px; text-align: right; opacity: 0.7; } .default-dark { background-color: #1E1E1E; color: #D4D4D4; } .default-dark .mtk17 { color: #808080; } .default-dark .mtk4 { color: #569CD6; } .default-dark .mtk1 { color: #D4D4D4; } .default-dark .mtk12 { color: #9CDCFE; } .default-dark .mtk8 { color: #CE9178; } .default-dark .mtk15 { color: #C586C0; } .default-dark .mtk10 { color: #4EC9B0; } .default-dark .mtk11 { color: #DCDCAA; } .default-dark .mtk7 { color: #B5CEA8; } .default-dark .grvsc-line-highlighted::before { background-color: var(--grvsc-line-highlighted-background-color, rgba(255, 255, 255, 0.1)); box-shadow: inset var(--grvsc-line-highlighted-border-width, 4px) 0 0 0 var(--grvsc-line-highlighted-border-color, rgba(255, 255, 255, 0.5)); } </style><![CDATA[How to Style and Customize a Button with Material UI]]>https://muhimasri.comhow-to-style-and-customize-a-button-with-material-uihttps://muhimasri.comhow-to-style-and-customize-a-button-with-material-ui<p><a href="https://mui.com/">MUI</a> components have plenty of useful built-in styles and variants, but we might still need to customize them (behavioral or styling changes).</p> <p>This tutorial will explain how to create a custom MUI button style and add a new pill-shaped variant. If you’d like to skip all the details, below is the final working code on <a href="https://codesandbox.io/s/mui-custom-button-variant-jnexsk?file=/src/App.js">CodeSandbox</a>:</p> <div data-codesandbox="mui-custom-button-variant-jnexsk"> <button>Run Code</button> </div> <p>It is widespread to have round and square buttons used interchangeably within a web app. Take Airbnb as an example; the search button is round while the signup is square:</p> <p><span class="gatsby-resp-image-wrapper" style="position: relative; display: block; margin-left: auto; margin-right: auto; max-width: 720px; " > <a class="gatsby-resp-image-link" href="/static/88135bade6a67f04a0dcd7b4f5eabb82/2bef9/image-11-1024x84.png" style="display: block" target="_blank" rel="noopener" > <span class="gatsby-resp-image-background-image" style="padding-bottom: 8.333333333333332%; position: relative; bottom: 0; left: 0; background-image: url('data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABQAAAACCAIAAADXZGvcAAAACXBIWXMAAAsTAAALEwEAmpwYAAAAcUlEQVR42h2MMQ4CIRAA76WW/sLS111nSK4AicCyu4guLDlLcxKnmmlmsdbljACZiJg5hGCMiTHSH2vtzJTSdER0zmWA/tlxva2nywKQmJGZWpPeeynF+3utTx2qOnPuHiKvpvKW2qQNHd/j2De/na8/NEpqGetEY6AAAAAASUVORK5CYII='); background-size: cover; display: block;" ></span> <img class="gatsby-resp-image-image" alt="image 11 1024x84" title="" src="/static/88135bade6a67f04a0dcd7b4f5eabb82/37523/image-11-1024x84.png" srcset="/static/88135bade6a67f04a0dcd7b4f5eabb82/e9ff0/image-11-1024x84.png 180w, /static/88135bade6a67f04a0dcd7b4f5eabb82/f21e7/image-11-1024x84.png 360w, /static/88135bade6a67f04a0dcd7b4f5eabb82/37523/image-11-1024x84.png 720w, /static/88135bade6a67f04a0dcd7b4f5eabb82/2bef9/image-11-1024x84.png 1024w" sizes="(max-width: 720px) 100vw, 720px" style="width:100%;height:100%;margin:0;vertical-align:middle;position:absolute;top:0;left:0;" loading="lazy" decoding="async" /> </a> </span></p> <p><span class="gatsby-resp-image-wrapper" style="position: relative; display: block; margin-left: auto; margin-right: auto; max-width: 720px; " > <a class="gatsby-resp-image-link" href="/static/818ffb593f462e0af0b6070fb46040c1/2bef9/image-12-1024x747.png" style="display: block" target="_blank" rel="noopener" > <span class="gatsby-resp-image-background-image" style="padding-bottom: 72.77777777777777%; position: relative; bottom: 0; left: 0; background-image: url('data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABQAAAAPCAIAAABr+ngCAAAACXBIWXMAAAsTAAALEwEAmpwYAAAB7ElEQVR42o1TS2sTURS+f0URtRuLdOFPcNFNpWgotjUglMaKu1YQREQRSbsppVQyoCXNLpCQVfal+II0YGoxocFFxDxMmpnMndd9jH4zt6TTaqkfhzOHc74zc15DDkP0T0LX9Var1Wg0Op0O7FPRbrfLGMtkMsR13d8n4fs+NBj1et0wjKFnCCEEdLFYJHhIKf1/QaX9DZWczWZJlCEjAINzLs8AstLpNLEs62cIVeG5wDdUp4VCIegZ7WFmtm3L/wAqUsm5XI54nkcpdRxnMBjAe6r4s/JBy+fzBENHMj5rUco8TwoZyDEx4IYyNIQaWNCzK7jFPJszR0CObGjqOtSxqefANgPtwoZhc08tYuPNBmk8Xf8We1yLP6vNQJ5XZ19UZ15WZ18dLKwePFyrxlf2p17vTyW/xpJ7d5b3bq98mVwu30qy77+0zbekFlssXZ0oj90tj0KmS6P3Stfipev3KzeXKuNPdm88+jwy92lk/uOV+Q+XE+8vPdi5mNi+kHAqP7Std8S3Xa6bwqARsbhBWc9gXYP3Ta4HntAZSt9ifYqyU1oqOBLMDhOIih+eHZfCD+1oSAZ8eZSMDZmmqRYwRK/Xazab+Cva7TY0Ti0axXYxs5SmESwJq0KYRQAPDk69FxrsaFQdCZL/AJASLIcOVoSKAAAAAElFTkSuQmCC'); background-size: cover; display: block;" ></span> <img class="gatsby-resp-image-image" alt="image 12 1024x747" title="" src="/static/818ffb593f462e0af0b6070fb46040c1/37523/image-12-1024x747.png" srcset="/static/818ffb593f462e0af0b6070fb46040c1/e9ff0/image-12-1024x747.png 180w, /static/818ffb593f462e0af0b6070fb46040c1/f21e7/image-12-1024x747.png 360w, /static/818ffb593f462e0af0b6070fb46040c1/37523/image-12-1024x747.png 720w, /static/818ffb593f462e0af0b6070fb46040c1/2bef9/image-12-1024x747.png 1024w" sizes="(max-width: 720px) 100vw, 720px" style="width:100%;height:100%;margin:0;vertical-align:middle;position:absolute;top:0;left:0;" loading="lazy" decoding="async" /> </a> </span></p> <p>Currently, MUI <code>Button</code> comes with three variants (text, contained, and outlined):</p> <p><span class="gatsby-resp-image-wrapper" style="position: relative; display: block; margin-left: auto; margin-right: auto; max-width: 720px; " > <a class="gatsby-resp-image-link" href="/static/2cbca29bc89145194caae7c1a7c7353f/2bef9/image-5-1024x117.png" style="display: block" target="_blank" rel="noopener" > <span class="gatsby-resp-image-background-image" style="padding-bottom: 11.666666666666666%; position: relative; bottom: 0; left: 0; background-image: url('data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABQAAAACCAIAAADXZGvcAAAACXBIWXMAAAsTAAALEwEAmpwYAAAAcklEQVR42j2LywqDMBQF/fVCV75Cu7Da6u9YJBYL8RsEl3maXEPilULhMJs5kwD4bduNAWSMUSqoW/Z4sqabq9dJcv9+phWVUvCftT6EkGCsNWBszBkL4bKSpgUtbmNGaE7Gy7V/D8tPCWE5d1I6PGN8ANARaBSn+zE6AAAAAElFTkSuQmCC'); background-size: cover; display: block;" ></span> <img class="gatsby-resp-image-image" alt="image 5 1024x117" title="" src="/static/2cbca29bc89145194caae7c1a7c7353f/37523/image-5-1024x117.png" srcset="/static/2cbca29bc89145194caae7c1a7c7353f/e9ff0/image-5-1024x117.png 180w, /static/2cbca29bc89145194caae7c1a7c7353f/f21e7/image-5-1024x117.png 360w, /static/2cbca29bc89145194caae7c1a7c7353f/37523/image-5-1024x117.png 720w, /static/2cbca29bc89145194caae7c1a7c7353f/2bef9/image-5-1024x117.png 1024w" sizes="(max-width: 720px) 100vw, 720px" style="width:100%;height:100%;margin:0;vertical-align:middle;position:absolute;top:0;left:0;" loading="lazy" decoding="async" /> </a> </span></p> <p>The easiest way to add style overrides in MUI is to use <code>sx</code> prop available on all components. Here is an example:</p> <pre class="grvsc-container default-dark" data-language="jsx" data-index="0"><code class="grvsc-code"><span class="grvsc-line"><span class="grvsc-source"><span class="mtk17">&lt;</span><span class="mtk10">Button</span><span class="mtk1"> </span><span class="mtk12">variant</span><span class="mtk1">=</span><span class="mtk8">&quot;contained&quot;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">sx</span><span class="mtk1">=</span><span class="mtk4">{</span><span class="mtk1">{</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">borderRadius:</span><span class="mtk1"> </span><span class="mtk7">50</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> }</span><span class="mtk4">}</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk17">&gt;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> Button</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk17">&lt;/</span><span class="mtk10">Button</span><span class="mtk17">&gt;</span><span class="mtk1">;</span></span></span></code></pre> <p>The code above is perfectly valid to style a pill-shaped button. However, if we want to add more styles and eventually use them in multiple places, it’s always a good practice to encapsulate everything in a custom component.</p> <h2 id="install-mui" style="position:relative;"><a href="#install-mui" aria-label="install mui permalink" class="anchor before"><svg aria-hidden="true" focusable="false" height="16" version="1.1" viewBox="0 0 16 16" width="16"><path fill-rule="evenodd" d="M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z"></path></svg></a>Install MUI</h2> <pre class="grvsc-container default-dark" data-language="" data-index="1"><code class="grvsc-code"><span class="grvsc-line"><span class="grvsc-source">npm install @mui/material @emotion/react @emotion/styled</span></span></code></pre> <p><a href="https://emotion.sh/docs/introduction">Emotion</a> library is required to create React components with styles attached to them.</p> <h2 id="customize-button-style" style="position:relative;"><a href="#customize-button-style" aria-label="customize button style permalink" class="anchor before"><svg aria-hidden="true" focusable="false" height="16" version="1.1" viewBox="0 0 16 16" width="16"><path fill-rule="evenodd" d="M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z"></path></svg></a>Customize button style</h2> <p>Let’s create a new <code>Button</code> component that extends the original MUI <code>Button</code> using <code>styles()</code> utility. That will allow us to customize it and inherit all existing features:</p> <pre class="grvsc-container default-dark" data-language="jsx" data-index="2"><code class="grvsc-code"><span class="grvsc-line"><span class="grvsc-source"><span class="mtk15">import</span><span class="mtk1"> { </span><span class="mtk12">styled</span><span class="mtk1"> } </span><span class="mtk15">from</span><span class="mtk1"> </span><span class="mtk8">&quot;@mui/material/styles&quot;</span><span class="mtk1">;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk15">import</span><span class="mtk1"> </span><span class="mtk12">MuiButton</span><span class="mtk1"> </span><span class="mtk15">from</span><span class="mtk1"> </span><span class="mtk8">&quot;@mui/material/Button&quot;</span><span class="mtk1">;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk15">export</span><span class="mtk1"> </span><span class="mtk4">const</span><span class="mtk1"> </span><span class="mtk12">Button</span><span class="mtk1"> = </span><span class="mtk11">styled</span><span class="mtk1">(</span><span class="mtk12">MuiButton</span><span class="mtk1">)((</span><span class="mtk12">props</span><span class="mtk1">) </span><span class="mtk4">=&gt;</span><span class="mtk1"> ({</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk3">// Custom CSS</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1">}));</span></span></span></code></pre> <p><em>Note: we imported Material Button as <code>MuiButton</code> so it does not conflict with our custom <code>Button</code> component</em></p> <p>To customize the style, we’ll add a <code>pill</code> prop and pass it down as a <code>borderRadius</code> value.</p> <pre class="grvsc-container default-dark" data-language="jsx" data-index="3"><code class="grvsc-code"><span class="grvsc-line"><span class="grvsc-source"><span class="mtk15">export</span><span class="mtk1"> </span><span class="mtk4">const</span><span class="mtk1"> </span><span class="mtk12">Button</span><span class="mtk1"> = </span><span class="mtk11">styled</span><span class="mtk1">(</span><span class="mtk12">MuiButton</span><span class="mtk1">)(({ </span><span class="mtk12">pill</span><span class="mtk1"> }) </span><span class="mtk4">=&gt;</span><span class="mtk1"> ({</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">borderRadius:</span><span class="mtk1"> </span><span class="mtk12">pill</span><span class="mtk1"> ? </span><span class="mtk7">50</span><span class="mtk1"> : </span><span class="mtk7">4</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1">}));</span></span></span></code></pre> <p>If the consumer does not pass the <code>pill</code> prop, the radius value will be the original 4px. Otherwise, it will be set to 50px. Here is how we can consume the component:</p> <pre class="grvsc-container default-dark" data-language="jsx" data-index="4"><code class="grvsc-code"><span class="grvsc-line"><span class="grvsc-source"><span class="mtk15">import</span><span class="mtk1"> { </span><span class="mtk12">Button</span><span class="mtk1"> } </span><span class="mtk15">from</span><span class="mtk1"> </span><span class="mtk8">&quot;./components/Button&quot;</span><span class="mtk1">;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk15">export</span><span class="mtk1"> </span><span class="mtk15">default</span><span class="mtk1"> </span><span class="mtk4">function</span><span class="mtk1"> </span><span class="mtk11">App</span><span class="mtk1">() {</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk15">return</span><span class="mtk1"> (</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk17">&lt;</span><span class="mtk4">div</span><span class="mtk17">&gt;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk17">&lt;</span><span class="mtk10">Button</span><span class="mtk1"> </span><span class="mtk12">variant</span><span class="mtk1">=</span><span class="mtk8">&quot;outlined&quot;</span><span class="mtk1"> </span><span class="mtk12">pill</span><span class="mtk17">&gt;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> Outlined Pill</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk17">&lt;/</span><span class="mtk10">Button</span><span class="mtk17">&gt;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk17">&lt;/</span><span class="mtk4">div</span><span class="mtk17">&gt;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> );</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1">}</span></span></span></code></pre> <p><span class="gatsby-resp-image-wrapper" style="position: relative; display: block; margin-left: auto; margin-right: auto; max-width: 222px; " > <a class="gatsby-resp-image-link" href="/static/76d46fa53e9e052b4c5ce50c18886a10/6bc44/image-2.png" style="display: block" target="_blank" rel="noopener" > <span class="gatsby-resp-image-background-image" style="padding-bottom: 30%; position: relative; bottom: 0; left: 0; background-image: url('data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABQAAAAGCAIAAABM9SnKAAAACXBIWXMAAAsTAAALEwEAmpwYAAAA70lEQVR42j2QfUvDMBDG8/0/kIqgoKAi/rPhOoaT+dJuccrIS9trc0lan2tFeAi/e5K7y50ax9H3+WD5y0Xo6P9O7XiW+GJO7IUBlhISlaP0cQotZ+JEnFtRaoJwH0WAOewmboPcfppwaqIqDfdx2Bu+3vhFRU/v7UXhUP5q489W7nxlAWvd3b3W4GVFYCnEuTJBVZIs337YNfe75nlPhaZFSY9vUuVy7W63daG7l2OHtJttjfDbR84DEpWhVJqAYjEPENyAMwnnQZTgSCgPZp+kLf/UUWFuTI/O2k4rmUDWY/lg/3cmPIczY+BhHH8BVrVR0U/kkkAAAAAASUVORK5CYII='); background-size: cover; display: block;" ></span> <img class="gatsby-resp-image-image" alt="image 2" title="" src="/static/76d46fa53e9e052b4c5ce50c18886a10/6bc44/image-2.png" srcset="/static/76d46fa53e9e052b4c5ce50c18886a10/e9ff0/image-2.png 180w, /static/76d46fa53e9e052b4c5ce50c18886a10/6bc44/image-2.png 222w" sizes="(max-width: 222px) 100vw, 222px" style="width:100%;height:100%;margin:0;vertical-align:middle;position:absolute;top:0;left:0;" loading="lazy" decoding="async" /> </a> </span></p> <h2 id="update-default-theme" style="position:relative;"><a href="#update-default-theme" aria-label="update default theme permalink" class="anchor before"><svg aria-hidden="true" focusable="false" height="16" version="1.1" viewBox="0 0 16 16" width="16"><path fill-rule="evenodd" d="M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z"></path></svg></a>Update default theme</h2> <p>Instead of using a radius value directly, we can define it in the default MUI theme as a new property. This way, all the design tokens will be in one place and re-used in different components.</p> <p>Let’s add a <code>ThemeProvider</code> component and insert a new token in the <code>shape</code> property:</p> <pre class="grvsc-container default-dark" data-language="jsx" data-index="5"><code class="grvsc-code"><span class="grvsc-line"><span class="grvsc-source"><span class="mtk15">import</span><span class="mtk1"> { </span><span class="mtk12">Button</span><span class="mtk1"> } </span><span class="mtk15">from</span><span class="mtk1"> </span><span class="mtk8">&quot;./components/Button&quot;</span><span class="mtk1">;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk15">import</span><span class="mtk1"> { </span><span class="mtk12">createTheme</span><span class="mtk1">, </span><span class="mtk12">ThemeProvider</span><span class="mtk1"> } </span><span class="mtk15">from</span><span class="mtk1"> </span><span class="mtk8">&quot;@mui/material/styles&quot;</span><span class="mtk1">;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk4">let</span><span class="mtk1"> </span><span class="mtk12">theme</span><span class="mtk1"> = </span><span class="mtk11">createTheme</span><span class="mtk1">({</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">shape:</span><span class="mtk1"> {</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">pillRadius:</span><span class="mtk1"> </span><span class="mtk7">50</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> }</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1">});</span></span></span> <span class="grvsc-line"><span class="grvsc-source"></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk15">export</span><span class="mtk1"> </span><span class="mtk15">default</span><span class="mtk1"> </span><span class="mtk4">function</span><span class="mtk1"> </span><span class="mtk11">App</span><span class="mtk1">() {</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk15">return</span><span class="mtk1"> (</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk17">&lt;</span><span class="mtk10">ThemeProvider</span><span class="mtk1"> </span><span class="mtk12">theme</span><span class="mtk1">=</span><span class="mtk4">{</span><span class="mtk12">theme</span><span class="mtk4">}</span><span class="mtk17">&gt;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk17">&lt;</span><span class="mtk10">Button</span><span class="mtk1"> </span><span class="mtk12">variant</span><span class="mtk1">=</span><span class="mtk8">&quot;outlined&quot;</span><span class="mtk1"> </span><span class="mtk12">pill</span><span class="mtk17">&gt;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> Outlined Pill</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk17">&lt;/</span><span class="mtk10">Button</span><span class="mtk17">&gt;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk17">&lt;/</span><span class="mtk10">ThemeProvider</span><span class="mtk17">&gt;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> );</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1">}</span></span></span></code></pre> <p>Now, in the <code>Button</code> component, we can use the new radius token as follows:</p> <pre class="grvsc-container default-dark" data-language="jsx" data-index="6"><code class="grvsc-code"><span class="grvsc-line"><span class="grvsc-source"><span class="mtk15">import</span><span class="mtk1"> { </span><span class="mtk12">styled</span><span class="mtk1"> } </span><span class="mtk15">from</span><span class="mtk1"> </span><span class="mtk8">&quot;@mui/material/styles&quot;</span><span class="mtk1">;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk15">import</span><span class="mtk1"> </span><span class="mtk12">MuiButton</span><span class="mtk1"> </span><span class="mtk15">from</span><span class="mtk1"> </span><span class="mtk8">&quot;@mui/material/Button&quot;</span><span class="mtk1">;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk15">export</span><span class="mtk1"> </span><span class="mtk4">const</span><span class="mtk1"> </span><span class="mtk12">Button</span><span class="mtk1"> = </span><span class="mtk11">styled</span><span class="mtk1">(</span><span class="mtk12">MuiButton</span><span class="mtk1">)(({ </span><span class="mtk12">theme</span><span class="mtk1">, </span><span class="mtk12">pill</span><span class="mtk1"> }) </span><span class="mtk4">=&gt;</span><span class="mtk1"> ({</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">borderRadius:</span><span class="mtk1"> </span><span class="mtk12">pill</span><span class="mtk1"> ? </span><span class="mtk12">theme</span><span class="mtk1">.</span><span class="mtk12">shape</span><span class="mtk1">.</span><span class="mtk12">pillRadius</span><span class="mtk1"> : </span><span class="mtk12">theme</span><span class="mtk1">.</span><span class="mtk12">shape</span><span class="mtk1">.</span><span class="mtk12">borderRadius</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1">}));</span></span></span></code></pre> <p>The <code>shape</code> object already had a default <code>borderRadius</code> token that we can also use.</p> <h2 id="final-thoughts" style="position:relative;"><a href="#final-thoughts" aria-label="final thoughts permalink" class="anchor before"><svg aria-hidden="true" focusable="false" height="16" version="1.1" viewBox="0 0 16 16" width="16"><path fill-rule="evenodd" d="M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z"></path></svg></a>Final Thoughts</h2> <p>Although the solution requires more work than just adding styles directly, it will create better encapsulation, scalability, and re-usability across the project.</p> <p>Bye for now 👋</p> <style class="grvsc-styles"> .grvsc-container { overflow: auto; position: relative; -webkit-overflow-scrolling: touch; padding-top: 1rem; padding-top: var(--grvsc-padding-top, var(--grvsc-padding-v, 1rem)); padding-bottom: 1rem; padding-bottom: var(--grvsc-padding-bottom, var(--grvsc-padding-v, 1rem)); border-radius: 8px; border-radius: var(--grvsc-border-radius, 8px); font-feature-settings: normal; line-height: 1.4; } .grvsc-code { display: table; } .grvsc-line { display: table-row; box-sizing: border-box; width: 100%; position: relative; } .grvsc-line > * { position: relative; } .grvsc-gutter-pad { display: table-cell; padding-left: 0.75rem; padding-left: calc(var(--grvsc-padding-left, var(--grvsc-padding-h, 1.5rem)) / 2); } .grvsc-gutter { display: table-cell; -webkit-user-select: none; -moz-user-select: none; user-select: none; } .grvsc-gutter::before { content: attr(data-content); } .grvsc-source { display: table-cell; padding-left: 1.5rem; padding-left: var(--grvsc-padding-left, var(--grvsc-padding-h, 1.5rem)); padding-right: 1.5rem; padding-right: var(--grvsc-padding-right, var(--grvsc-padding-h, 1.5rem)); } .grvsc-source:empty::after { content: ' '; -webkit-user-select: none; -moz-user-select: none; user-select: none; } .grvsc-gutter + .grvsc-source { padding-left: 0.75rem; padding-left: calc(var(--grvsc-padding-left, var(--grvsc-padding-h, 1.5rem)) / 2); } /* Line transformer styles */ .grvsc-has-line-highlighting > .grvsc-code > .grvsc-line::before { content: ' '; position: absolute; width: 100%; } .grvsc-line-diff-add::before { background-color: var(--grvsc-line-diff-add-background-color, rgba(0, 255, 60, 0.2)); } .grvsc-line-diff-del::before { background-color: var(--grvsc-line-diff-del-background-color, rgba(255, 0, 20, 0.2)); } .grvsc-line-number { padding: 0 2px; text-align: right; opacity: 0.7; } .default-dark { background-color: #1E1E1E; color: #D4D4D4; } .default-dark .mtk17 { color: #808080; } .default-dark .mtk10 { color: #4EC9B0; } .default-dark .mtk1 { color: #D4D4D4; } .default-dark .mtk12 { color: #9CDCFE; } .default-dark .mtk8 { color: #CE9178; } .default-dark .mtk4 { color: #569CD6; } .default-dark .mtk7 { color: #B5CEA8; } .default-dark .mtk15 { color: #C586C0; } .default-dark .mtk11 { color: #DCDCAA; } .default-dark .mtk3 { color: #6A9955; } .default-dark .grvsc-line-highlighted::before { background-color: var(--grvsc-line-highlighted-background-color, rgba(255, 255, 255, 0.1)); box-shadow: inset var(--grvsc-line-highlighted-border-width, 4px) 0 0 0 var(--grvsc-line-highlighted-border-color, rgba(255, 255, 255, 0.5)); } </style><![CDATA[[Part 5] Validate Table Rows and Fields with Bootstrap Vue]]>https://muhimasri.compart-5-validate-table-rows-and-fields-with-bootstrap-vuehttps://muhimasri.compart-5-validate-table-rows-and-fields-with-bootstrap-vue<p>In this part of the BootstrapVue Table series, we will implement table validation for input fields.</p> <p>We will start by adding a basic validation in <code>EditableTable.vue</code>, then work our way up to make it defined and customized by the consumer. Remember, we built this component to support dynamic schemas so developers can re-use it in different features or projects.</p> <p>If you’d like to skip all the details, below is the final interactive demo on <a href="https://codesandbox.io/s/cool-estrela-u5u0i">Condsandbox</a>. In this example, we’re validating the name and email, but the email is customized with regex only to accept strings ending with “bootstrapvue.com”:</p> <div data-codesandbox="table-validation-u5u0i"> <button>Run Code</button> </div> <p><em>As we continue building upon the same code from previous parts in this series, it’s recommended that you go through these tutorials from the beginning to understand how the code structure works as we will not be explaining it here. You can navigate to any part using the table of contents.</em></p> <p>For your reference, below is the complete code from the <a href="https://muhimasri.com/blogs/part-4-load-add-update-and-delete-table-rows-using-api-services/">last part</a>:</p> <h5 id="editabletable-component" style="position:relative;"><a href="#editabletable-component" aria-label="editabletable component permalink" class="anchor before"><svg aria-hidden="true" focusable="false" height="16" version="1.1" viewBox="0 0 16 16" width="16"><path fill-rule="evenodd" d="M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z"></path></svg></a>EditableTable Component</h5> <pre class="grvsc-container default-dark" data-language="html" data-index="0"><code class="grvsc-code"><span class="grvsc-line"><span class="grvsc-source"><span class="mtk17">&lt;</span><span class="mtk4">template</span><span class="mtk17">&gt;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk17">&lt;</span><span class="mtk4">article</span><span class="mtk17">&gt;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk17">&lt;</span><span class="mtk4">b-modal</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">id</span><span class="mtk1">=</span><span class="mtk8">&quot;modal-1&quot;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">title</span><span class="mtk1">=</span><span class="mtk8">&quot;Confirm&quot;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">v-model</span><span class="mtk1">=</span><span class="mtk8">&quot;openDialog&quot;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">ok-title</span><span class="mtk1">=</span><span class="mtk8">&quot;Remove&quot;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">@ok</span><span class="mtk1">=</span><span class="mtk8">&quot;removeRowsHandler&quot;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk17">&gt;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk17">&lt;</span><span class="mtk4">p</span><span class="mtk1"> </span><span class="mtk12">class</span><span class="mtk1">=</span><span class="mtk8">&quot;my-4&quot;</span><span class="mtk17">&gt;</span><span class="mtk1">Are you sure you want to remove the selected rows?</span><span class="mtk17">&lt;/</span><span class="mtk4">p</span><span class="mtk17">&gt;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk17">&lt;/</span><span class="mtk4">b-modal</span><span class="mtk17">&gt;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk17">&lt;</span><span class="mtk4">div</span><span class="mtk1"> </span><span class="mtk12">class</span><span class="mtk1">=</span><span class="mtk8">&quot;action-container&quot;</span><span class="mtk17">&gt;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk17">&lt;</span><span class="mtk4">b-button</span><span class="mtk1"> </span><span class="mtk12">class</span><span class="mtk1">=</span><span class="mtk8">&quot;add-button&quot;</span><span class="mtk1"> </span><span class="mtk12">variant</span><span class="mtk1">=</span><span class="mtk8">&quot;success&quot;</span><span class="mtk1"> </span><span class="mtk12">@click</span><span class="mtk1">=</span><span class="mtk8">&quot;addRowHandler&quot;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk17">&gt;</span><span class="mtk1">Add Row</span><span class="mtk17">&lt;/</span><span class="mtk4">b-button</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk17">&gt;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk17">&lt;</span><span class="mtk4">b-button</span><span class="mtk1"> </span><span class="mtk12">variant</span><span class="mtk1">=</span><span class="mtk8">&quot;danger&quot;</span><span class="mtk1"> </span><span class="mtk12">@click</span><span class="mtk1">=</span><span class="mtk8">&quot;openDialog = true&quot;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk17">&gt;</span><span class="mtk1">Remove Rows</span><span class="mtk17">&lt;/</span><span class="mtk4">b-button</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk17">&gt;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk17">&lt;/</span><span class="mtk4">div</span><span class="mtk17">&gt;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk17">&lt;</span><span class="mtk4">b-table</span><span class="mtk1"> </span><span class="mtk12">class</span><span class="mtk1">=</span><span class="mtk8">&quot;b-table&quot;</span><span class="mtk1"> </span><span class="mtk12">:items</span><span class="mtk1">=</span><span class="mtk8">&quot;tableItems&quot;</span><span class="mtk1"> </span><span class="mtk12">:fields</span><span class="mtk1">=</span><span class="mtk8">&quot;fields&quot;</span><span class="mtk1"> </span><span class="mtk12">fixed</span><span class="mtk17">&gt;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk17">&lt;</span><span class="mtk4">template</span><span class="mtk1"> </span><span class="mtk12">v-for</span><span class="mtk1">=</span><span class="mtk8">&quot;(field, index) in fields&quot;</span><span class="mtk1"> </span><span class="mtk12">#[`cell(${field.key})`]</span><span class="mtk1">=</span><span class="mtk8">&quot;data&quot;</span><span class="mtk17">&gt;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk17">&lt;</span><span class="mtk4">b-form-datepicker</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">v-if</span><span class="mtk1">=</span><span class="mtk8">&quot;field.type === &#39;date&#39; &amp;&amp; tableItems[data.index].isEdit&quot;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">:key</span><span class="mtk1">=</span><span class="mtk8">&quot;index&quot;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">:type</span><span class="mtk1">=</span><span class="mtk8">&quot;field.type&quot;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">:value</span><span class="mtk1">=</span><span class="mtk8">&quot;tableItems[data.index][field.key]&quot;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">@input</span><span class="mtk1">=</span><span class="mtk8">&quot;(value) =&gt; inputHandler(value, data.index, field.key)&quot;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk17">&gt;&lt;/</span><span class="mtk4">b-form-datepicker</span><span class="mtk17">&gt;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk17">&lt;</span><span class="mtk4">b-form-select</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">v-else-if</span><span class="mtk1">=</span><span class="mtk8">&quot;field.type === &#39;select&#39; &amp;&amp; tableItems[data.index].isEdit&quot;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">:key</span><span class="mtk1">=</span><span class="mtk8">&quot;index&quot;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">:value</span><span class="mtk1">=</span><span class="mtk8">&quot;tableItems[data.index][field.key]&quot;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">@input</span><span class="mtk1">=</span><span class="mtk8">&quot;(value) =&gt; inputHandler(value, data.index, field.key)&quot;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">:options</span><span class="mtk1">=</span><span class="mtk8">&quot;field.options&quot;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk17">&gt;&lt;/</span><span class="mtk4">b-form-select</span><span class="mtk17">&gt;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk17">&lt;</span><span class="mtk4">b-checkbox</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">v-else-if</span><span class="mtk1">=</span><span class="mtk8">&quot;field.key === &#39;selectRow&#39;&quot;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">:checked</span><span class="mtk1">=</span><span class="mtk8">&quot;tableItems[data.index].isSelected&quot;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">:key</span><span class="mtk1">=</span><span class="mtk8">&quot;index&quot;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">@change</span><span class="mtk1">=</span><span class="mtk8">&quot;selectRowHandler(data)&quot;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk17">&gt;&lt;/</span><span class="mtk4">b-checkbox</span><span class="mtk17">&gt;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk17">&lt;</span><span class="mtk4">div</span><span class="mtk1"> </span><span class="mtk12">:key</span><span class="mtk1">=</span><span class="mtk8">&quot;index&quot;</span><span class="mtk1"> </span><span class="mtk12">v-else-if</span><span class="mtk1">=</span><span class="mtk8">&quot;field.type === &#39;edit&#39;&quot;</span><span class="mtk17">&gt;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk17">&lt;</span><span class="mtk4">b-button</span><span class="mtk1"> </span><span class="mtk12">@click</span><span class="mtk1">=</span><span class="mtk8">&quot;editRowHandler(data)&quot;</span><span class="mtk17">&gt;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk17">&lt;</span><span class="mtk4">span</span><span class="mtk1"> </span><span class="mtk12">v-if</span><span class="mtk1">=</span><span class="mtk8">&quot;!tableItems[data.index].isEdit&quot;</span><span class="mtk17">&gt;</span><span class="mtk1">Edit</span><span class="mtk17">&lt;/</span><span class="mtk4">span</span><span class="mtk17">&gt;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk17">&lt;</span><span class="mtk4">span</span><span class="mtk1"> </span><span class="mtk12">v-else</span><span class="mtk17">&gt;</span><span class="mtk1">Done</span><span class="mtk17">&lt;/</span><span class="mtk4">span</span><span class="mtk17">&gt;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk17">&lt;/</span><span class="mtk4">b-button</span><span class="mtk17">&gt;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk17">&lt;</span><span class="mtk4">b-button</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">class</span><span class="mtk1">=</span><span class="mtk8">&quot;delete-button&quot;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">variant</span><span class="mtk1">=</span><span class="mtk8">&quot;danger&quot;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">@click</span><span class="mtk1">=</span><span class="mtk8">&quot;removeRowHandler(data.index)&quot;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk17">&gt;</span><span class="mtk1">Remove</span><span class="mtk17">&lt;/</span><span class="mtk4">b-button</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk17">&gt;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk17">&lt;/</span><span class="mtk4">div</span><span class="mtk17">&gt;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk17">&lt;</span><span class="mtk4">b-form-input</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">v-else-if</span><span class="mtk1">=</span><span class="mtk8">&quot;field.type &amp;&amp; tableItems[data.index].isEdit&quot;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">:key</span><span class="mtk1">=</span><span class="mtk8">&quot;index&quot;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">:type</span><span class="mtk1">=</span><span class="mtk8">&quot;field.type&quot;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">:value</span><span class="mtk1">=</span><span class="mtk8">&quot;tableItems[data.index][field.key]&quot;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">@blur</span><span class="mtk1">=</span><span class="mtk8">&quot;(e) =&gt; inputHandler(e.target.value, data.index, field.key)&quot;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk17">&gt;&lt;/</span><span class="mtk4">b-form-input</span><span class="mtk17">&gt;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk17">&lt;</span><span class="mtk4">span</span><span class="mtk1"> </span><span class="mtk12">:key</span><span class="mtk1">=</span><span class="mtk8">&quot;index&quot;</span><span class="mtk1"> </span><span class="mtk12">v-else</span><span class="mtk17">&gt;</span><span class="mtk1">{{ data.value }}</span><span class="mtk17">&lt;/</span><span class="mtk4">span</span><span class="mtk17">&gt;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk17">&lt;/</span><span class="mtk4">template</span><span class="mtk17">&gt;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk17">&lt;/</span><span class="mtk4">b-table</span><span class="mtk17">&gt;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk17">&lt;/</span><span class="mtk4">article</span><span class="mtk17">&gt;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk17">&lt;/</span><span class="mtk4">template</span><span class="mtk17">&gt;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk17">&lt;</span><span class="mtk4">script</span><span class="mtk17">&gt;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk15">export</span><span class="mtk1"> </span><span class="mtk15">default</span><span class="mtk1"> {</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">name:</span><span class="mtk1"> </span><span class="mtk8">&quot;EditableTable&quot;</span><span class="mtk1">,</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">components:</span><span class="mtk1"> {},</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">props:</span><span class="mtk1"> {</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">value:</span><span class="mtk1"> </span><span class="mtk10">Array</span><span class="mtk1">,</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">fields:</span><span class="mtk1"> </span><span class="mtk10">Array</span><span class="mtk1">,</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> },</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk11">data</span><span class="mtk1">() {</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk15">return</span><span class="mtk1"> {</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">tableItems:</span><span class="mtk1"> </span><span class="mtk4">this</span><span class="mtk1">.</span><span class="mtk11">mapItems</span><span class="mtk1">(</span><span class="mtk4">this</span><span class="mtk1">.</span><span class="mtk12">value</span><span class="mtk1">),</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">openDialog:</span><span class="mtk1"> </span><span class="mtk4">false</span><span class="mtk1">,</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> };</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> },</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">watch:</span><span class="mtk1"> {</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk11">value</span><span class="mtk1">(</span><span class="mtk12">newVal</span><span class="mtk1">) {</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk4">this</span><span class="mtk1">.</span><span class="mtk12">tableItems</span><span class="mtk1"> = </span><span class="mtk4">this</span><span class="mtk1">.</span><span class="mtk11">mapItems</span><span class="mtk1">(</span><span class="mtk12">newVal</span><span class="mtk1">);</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> },</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> },</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">methods:</span><span class="mtk1"> {</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk11">editRowHandler</span><span class="mtk1">(</span><span class="mtk12">data</span><span class="mtk1">) {</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk15">if</span><span class="mtk1"> (</span><span class="mtk4">this</span><span class="mtk1">.</span><span class="mtk12">tableItems</span><span class="mtk1">[</span><span class="mtk12">data</span><span class="mtk1">.</span><span class="mtk12">index</span><span class="mtk1">].</span><span class="mtk12">isEdit</span><span class="mtk1">) {</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk4">this</span><span class="mtk1">.</span><span class="mtk11">$emit</span><span class="mtk1">(</span><span class="mtk8">&quot;submit&quot;</span><span class="mtk1">, </span><span class="mtk4">this</span><span class="mtk1">.</span><span class="mtk12">tableItems</span><span class="mtk1">[</span><span class="mtk12">data</span><span class="mtk1">.</span><span class="mtk12">index</span><span class="mtk1">]);</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> }</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk4">this</span><span class="mtk1">.</span><span class="mtk12">tableItems</span><span class="mtk1">[</span><span class="mtk12">data</span><span class="mtk1">.</span><span class="mtk12">index</span><span class="mtk1">].</span><span class="mtk12">isEdit</span><span class="mtk1"> = !</span><span class="mtk4">this</span><span class="mtk1">.</span><span class="mtk12">tableItems</span><span class="mtk1">[</span><span class="mtk12">data</span><span class="mtk1">.</span><span class="mtk12">index</span><span class="mtk1">].</span><span class="mtk12">isEdit</span><span class="mtk1">;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> },</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk11">inputHandler</span><span class="mtk1">(</span><span class="mtk12">value</span><span class="mtk1">, </span><span class="mtk12">index</span><span class="mtk1">, </span><span class="mtk12">key</span><span class="mtk1">) {</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk4">this</span><span class="mtk1">.</span><span class="mtk12">tableItems</span><span class="mtk1">[</span><span class="mtk12">index</span><span class="mtk1">][</span><span class="mtk12">key</span><span class="mtk1">] = </span><span class="mtk12">value</span><span class="mtk1">;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk4">this</span><span class="mtk1">.</span><span class="mtk11">$set</span><span class="mtk1">(</span><span class="mtk4">this</span><span class="mtk1">.</span><span class="mtk12">tableItems</span><span class="mtk1">, </span><span class="mtk12">index</span><span class="mtk1">, </span><span class="mtk4">this</span><span class="mtk1">.</span><span class="mtk12">tableItems</span><span class="mtk1">[</span><span class="mtk12">index</span><span class="mtk1">]);</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk4">this</span><span class="mtk1">.</span><span class="mtk11">$emit</span><span class="mtk1">(</span><span class="mtk8">&quot;input&quot;</span><span class="mtk1">, </span><span class="mtk4">this</span><span class="mtk1">.</span><span class="mtk12">tableItems</span><span class="mtk1">);</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> },</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk11">addRowHandler</span><span class="mtk1">() {</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk4">const</span><span class="mtk1"> </span><span class="mtk12">newRow</span><span class="mtk1"> = </span><span class="mtk4">this</span><span class="mtk1">.</span><span class="mtk12">fields</span><span class="mtk1">.</span><span class="mtk11">reduce</span><span class="mtk1">(</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> (</span><span class="mtk12">a</span><span class="mtk1">, </span><span class="mtk12">c</span><span class="mtk1">) </span><span class="mtk4">=&gt;</span><span class="mtk1"> ({ ...</span><span class="mtk12">a</span><span class="mtk1">, </span><span class="mtk12">[c.key]:</span><span class="mtk1"> </span><span class="mtk4">null</span><span class="mtk1"> }),</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> {}</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> );</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">newRow</span><span class="mtk1">.</span><span class="mtk12">isEdit</span><span class="mtk1"> = </span><span class="mtk4">true</span><span class="mtk1">;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk4">this</span><span class="mtk1">.</span><span class="mtk12">tableItems</span><span class="mtk1">.</span><span class="mtk11">unshift</span><span class="mtk1">(</span><span class="mtk12">newRow</span><span class="mtk1">);</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk4">this</span><span class="mtk1">.</span><span class="mtk11">$emit</span><span class="mtk1">(</span><span class="mtk8">&quot;input&quot;</span><span class="mtk1">, </span><span class="mtk4">this</span><span class="mtk1">.</span><span class="mtk12">tableItems</span><span class="mtk1">);</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> },</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk11">removeRowHandler</span><span class="mtk1">(</span><span class="mtk12">index</span><span class="mtk1">) {</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk4">this</span><span class="mtk1">.</span><span class="mtk12">tableItems</span><span class="mtk1"> = </span><span class="mtk4">this</span><span class="mtk1">.</span><span class="mtk12">tableItems</span><span class="mtk1">.</span><span class="mtk11">filter</span><span class="mtk1">((</span><span class="mtk12">item</span><span class="mtk1">, </span><span class="mtk12">i</span><span class="mtk1">) </span><span class="mtk4">=&gt;</span><span class="mtk1"> </span><span class="mtk12">i</span><span class="mtk1"> !== </span><span class="mtk12">index</span><span class="mtk1">);</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk4">this</span><span class="mtk1">.</span><span class="mtk11">$emit</span><span class="mtk1">(</span><span class="mtk8">&quot;input&quot;</span><span class="mtk1">, </span><span class="mtk4">this</span><span class="mtk1">.</span><span class="mtk12">tableItems</span><span class="mtk1">);</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk4">this</span><span class="mtk1">.</span><span class="mtk11">$emit</span><span class="mtk1">(</span><span class="mtk8">&quot;remove&quot;</span><span class="mtk1">, </span><span class="mtk4">this</span><span class="mtk1">.</span><span class="mtk12">tableItems</span><span class="mtk1">[</span><span class="mtk12">index</span><span class="mtk1">]);</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> },</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk11">removeRowsHandler</span><span class="mtk1">() {</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk4">const</span><span class="mtk1"> </span><span class="mtk12">selectedItems</span><span class="mtk1"> = </span><span class="mtk4">this</span><span class="mtk1">.</span><span class="mtk12">tableItems</span><span class="mtk1">.</span><span class="mtk11">filter</span><span class="mtk1">(</span><span class="mtk12">item</span><span class="mtk1"> </span><span class="mtk4">=&gt;</span><span class="mtk1"> </span><span class="mtk12">item</span><span class="mtk1">.</span><span class="mtk12">isSelected</span><span class="mtk1">);</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk4">this</span><span class="mtk1">.</span><span class="mtk12">tableItems</span><span class="mtk1"> = </span><span class="mtk4">this</span><span class="mtk1">.</span><span class="mtk12">tableItems</span><span class="mtk1">.</span><span class="mtk11">filter</span><span class="mtk1">(</span><span class="mtk12">item</span><span class="mtk1"> </span><span class="mtk4">=&gt;</span><span class="mtk1"> !</span><span class="mtk12">item</span><span class="mtk1">.</span><span class="mtk12">isSelected</span><span class="mtk1">);</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk4">this</span><span class="mtk1">.</span><span class="mtk11">$emit</span><span class="mtk1">(</span><span class="mtk8">&quot;input&quot;</span><span class="mtk1">, </span><span class="mtk4">this</span><span class="mtk1">.</span><span class="mtk12">tableItems</span><span class="mtk1">);</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk4">this</span><span class="mtk1">.</span><span class="mtk11">$emit</span><span class="mtk1">(</span><span class="mtk8">&quot;remove&quot;</span><span class="mtk1">, </span><span class="mtk12">selectedItems</span><span class="mtk1">);</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> },</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk11">selectRowHandler</span><span class="mtk1">(</span><span class="mtk12">data</span><span class="mtk1">) {</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk4">this</span><span class="mtk1">.</span><span class="mtk12">tableItems</span><span class="mtk1">[</span><span class="mtk12">data</span><span class="mtk1">.</span><span class="mtk12">index</span><span class="mtk1">].</span><span class="mtk12">isSelected</span><span class="mtk1"> =</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> !</span><span class="mtk4">this</span><span class="mtk1">.</span><span class="mtk12">tableItems</span><span class="mtk1">[</span><span class="mtk12">data</span><span class="mtk1">.</span><span class="mtk12">index</span><span class="mtk1">].</span><span class="mtk12">isSelected</span><span class="mtk1">;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> },</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk11">mapItems</span><span class="mtk1">(</span><span class="mtk12">data</span><span class="mtk1">) {</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk15">return</span><span class="mtk1"> </span><span class="mtk12">data</span><span class="mtk1">.</span><span class="mtk11">map</span><span class="mtk1">((</span><span class="mtk12">item</span><span class="mtk1">, </span><span class="mtk12">index</span><span class="mtk1">) </span><span class="mtk4">=&gt;</span><span class="mtk1"> ({</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> ...</span><span class="mtk12">item</span><span class="mtk1">,</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">isEdit:</span><span class="mtk1"> </span><span class="mtk4">this</span><span class="mtk1">.</span><span class="mtk12">tableItems</span><span class="mtk1">[</span><span class="mtk12">index</span><span class="mtk1">] ? </span><span class="mtk4">this</span><span class="mtk1">.</span><span class="mtk12">tableItems</span><span class="mtk1">[</span><span class="mtk12">index</span><span class="mtk1">].</span><span class="mtk12">isEdit</span><span class="mtk1"> : </span><span class="mtk4">false</span><span class="mtk1">,</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">isSelected:</span><span class="mtk1"> </span><span class="mtk4">this</span><span class="mtk1">.</span><span class="mtk12">tableItems</span><span class="mtk1">[</span><span class="mtk12">index</span><span class="mtk1">]</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> ? </span><span class="mtk4">this</span><span class="mtk1">.</span><span class="mtk12">tableItems</span><span class="mtk1">[</span><span class="mtk12">index</span><span class="mtk1">].</span><span class="mtk12">isSelected</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> : </span><span class="mtk4">false</span><span class="mtk1">,</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> }));</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> },</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> },</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1">};</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk17">&lt;/</span><span class="mtk4">script</span><span class="mtk17">&gt;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk17">&lt;</span><span class="mtk4">style</span><span class="mtk17">&gt;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk6">.action-container</span><span class="mtk1"> {</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">margin-bottom</span><span class="mtk1">: </span><span class="mtk7">10px</span><span class="mtk1">;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1">}</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk6">.action-container</span><span class="mtk1"> </span><span class="mtk6">button</span><span class="mtk1"> {</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">margin-right</span><span class="mtk1">: </span><span class="mtk7">5px</span><span class="mtk1">;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1">}</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk6">.delete-button</span><span class="mtk1"> {</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">margin-left</span><span class="mtk1">: </span><span class="mtk7">5px</span><span class="mtk1">;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1">}</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk17">&lt;/</span><span class="mtk4">style</span><span class="mtk17">&gt;</span></span></span></code></pre> <h5 id="app-component" style="position:relative;"><a href="#app-component" aria-label="app component permalink" class="anchor before"><svg aria-hidden="true" focusable="false" height="16" version="1.1" viewBox="0 0 16 16" width="16"><path fill-rule="evenodd" d="M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z"></path></svg></a>App component</h5> <pre class="grvsc-container default-dark" data-language="html" data-index="1"><code class="grvsc-code"><span class="grvsc-line"><span class="grvsc-source"><span class="mtk17">&lt;</span><span class="mtk4">template</span><span class="mtk17">&gt;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk17">&lt;</span><span class="mtk4">div</span><span class="mtk1"> </span><span class="mtk12">id</span><span class="mtk1">=</span><span class="mtk8">&quot;app&quot;</span><span class="mtk17">&gt;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk17">&lt;</span><span class="mtk4">EditableTable</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">v-model</span><span class="mtk1">=</span><span class="mtk8">&quot;users&quot;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">:fields</span><span class="mtk1">=</span><span class="mtk8">&quot;fields&quot;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">@submit</span><span class="mtk1">=</span><span class="mtk8">&quot;handleUpdateUser($event)&quot;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">@remove</span><span class="mtk1">=</span><span class="mtk8">&quot;handleRemoveUser($event)&quot;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk17">&gt;&lt;/</span><span class="mtk4">EditableTable</span><span class="mtk17">&gt;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk17">&lt;/</span><span class="mtk4">div</span><span class="mtk17">&gt;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk17">&lt;/</span><span class="mtk4">template</span><span class="mtk17">&gt;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk17">&lt;</span><span class="mtk4">script</span><span class="mtk17">&gt;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk15">import</span><span class="mtk1"> </span><span class="mtk12">EditableTable</span><span class="mtk1"> </span><span class="mtk15">from</span><span class="mtk1"> </span><span class="mtk8">&quot;./components/EditableTable.vue&quot;</span><span class="mtk1">;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk15">import</span><span class="mtk1"> { </span><span class="mtk12">addUser</span><span class="mtk1">, </span><span class="mtk12">deleteUser</span><span class="mtk1">, </span><span class="mtk12">getUsers</span><span class="mtk1">, </span><span class="mtk12">updateUser</span><span class="mtk1"> } </span><span class="mtk15">from</span><span class="mtk1"> </span><span class="mtk8">&quot;./services/user&quot;</span><span class="mtk1">;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk15">export</span><span class="mtk1"> </span><span class="mtk15">default</span><span class="mtk1"> {</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">name:</span><span class="mtk1"> </span><span class="mtk8">&quot;App&quot;</span><span class="mtk1">,</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">components:</span><span class="mtk1"> {</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">EditableTable</span><span class="mtk1">,</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> },</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk11">data</span><span class="mtk1">() {</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk15">return</span><span class="mtk1"> {</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">fields:</span><span class="mtk1"> [</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> { </span><span class="mtk12">key:</span><span class="mtk1"> </span><span class="mtk8">&quot;selectRow&quot;</span><span class="mtk1">, </span><span class="mtk12">label:</span><span class="mtk1"> </span><span class="mtk8">&quot;&quot;</span><span class="mtk1"> },</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> { </span><span class="mtk12">key:</span><span class="mtk1"> </span><span class="mtk8">&quot;name&quot;</span><span class="mtk1">, </span><span class="mtk12">label:</span><span class="mtk1"> </span><span class="mtk8">&quot;Name&quot;</span><span class="mtk1">, </span><span class="mtk12">type:</span><span class="mtk1"> </span><span class="mtk8">&quot;text&quot;</span><span class="mtk1">, </span><span class="mtk12">required:</span><span class="mtk1"> </span><span class="mtk4">true</span><span class="mtk1"> },</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> { </span><span class="mtk12">key:</span><span class="mtk1"> </span><span class="mtk8">&quot;email&quot;</span><span class="mtk1">, </span><span class="mtk12">label:</span><span class="mtk1"> </span><span class="mtk8">&quot;Email&quot;</span><span class="mtk1">, </span><span class="mtk12">type:</span><span class="mtk1"> </span><span class="mtk8">&quot;email&quot;</span><span class="mtk1">, </span><span class="mtk12">required:</span><span class="mtk1"> </span><span class="mtk4">true</span><span class="mtk1">, </span><span class="mtk12">pattern:</span><span class="mtk1"> </span><span class="mtk8">&quot;.+@bootstrapvue</span><span class="mtk6">\\</span><span class="mtk8">.com&quot;</span><span class="mtk1"> },</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> { </span><span class="mtk12">key:</span><span class="mtk1"> </span><span class="mtk8">&quot;phone&quot;</span><span class="mtk1">, </span><span class="mtk12">label:</span><span class="mtk1"> </span><span class="mtk8">&quot;Phone&quot;</span><span class="mtk1">, </span><span class="mtk12">type:</span><span class="mtk1"> </span><span class="mtk8">&quot;text&quot;</span><span class="mtk1"> },</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> { </span><span class="mtk12">key:</span><span class="mtk1"> </span><span class="mtk8">&quot;edit&quot;</span><span class="mtk1">, </span><span class="mtk12">label:</span><span class="mtk1"> </span><span class="mtk8">&quot;&quot;</span><span class="mtk1">, </span><span class="mtk12">type:</span><span class="mtk1"> </span><span class="mtk8">&quot;edit&quot;</span><span class="mtk1"> },</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> ],</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">users:</span><span class="mtk1"> [],</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> };</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> },</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk4">async</span><span class="mtk1"> </span><span class="mtk11">mounted</span><span class="mtk1">() {</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk4">this</span><span class="mtk1">.</span><span class="mtk12">users</span><span class="mtk1"> = </span><span class="mtk15">await</span><span class="mtk1"> </span><span class="mtk11">getUsers</span><span class="mtk1">();</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> },</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">methods:</span><span class="mtk1"> {</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk4">async</span><span class="mtk1"> </span><span class="mtk11">handleUpdateUser</span><span class="mtk1">(</span><span class="mtk12">user</span><span class="mtk1">) {</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk15">if</span><span class="mtk1"> (</span><span class="mtk12">user</span><span class="mtk1">.</span><span class="mtk12">id</span><span class="mtk1">) {</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk15">await</span><span class="mtk1"> </span><span class="mtk11">updateUser</span><span class="mtk1">(</span><span class="mtk12">user</span><span class="mtk1">);</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> } </span><span class="mtk15">else</span><span class="mtk1"> {</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk15">await</span><span class="mtk1"> </span><span class="mtk11">addUser</span><span class="mtk1">(</span><span class="mtk12">user</span><span class="mtk1">);</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> }</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> },</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk4">async</span><span class="mtk1"> </span><span class="mtk11">handleRemoveUser</span><span class="mtk1">(</span><span class="mtk12">user</span><span class="mtk1">) {</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk15">if</span><span class="mtk1"> (</span><span class="mtk12">user</span><span class="mtk1">.</span><span class="mtk12">length</span><span class="mtk1"> &gt; </span><span class="mtk7">0</span><span class="mtk1">) {</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk15">await</span><span class="mtk1"> </span><span class="mtk12">user</span><span class="mtk1">.</span><span class="mtk11">map</span><span class="mtk1">(</span><span class="mtk4">async</span><span class="mtk1"> (</span><span class="mtk12">item</span><span class="mtk1">) </span><span class="mtk4">=&gt;</span><span class="mtk1"> {</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk15">await</span><span class="mtk1"> </span><span class="mtk11">deleteUser</span><span class="mtk1">(</span><span class="mtk12">item</span><span class="mtk1">.</span><span class="mtk12">id</span><span class="mtk1">); </span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> })</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> } </span><span class="mtk15">else</span><span class="mtk1"> {</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk15">await</span><span class="mtk1"> </span><span class="mtk11">deleteUser</span><span class="mtk1">(</span><span class="mtk12">user</span><span class="mtk1">.</span><span class="mtk12">id</span><span class="mtk1">);</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> }</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> }</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> },</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1">};</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk17">&lt;/</span><span class="mtk4">script</span><span class="mtk17">&gt;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk17">&lt;</span><span class="mtk4">style</span><span class="mtk17">&gt;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk6">#app</span><span class="mtk1"> {</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">margin</span><span class="mtk1">: </span><span class="mtk7">20px</span><span class="mtk1">;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1">}</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk17">&lt;/</span><span class="mtk4">style</span><span class="mtk17">&gt;</span></span></span></code></pre> <h2 id="add-table-row-validation" style="position:relative;"><a href="#add-table-row-validation" aria-label="add table row validation permalink" class="anchor before"><svg aria-hidden="true" focusable="false" height="16" version="1.1" viewBox="0 0 16 16" width="16"><path fill-rule="evenodd" d="M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z"></path></svg></a>Add Table Row Validation</h2> <p>To validate a specific field in a table row, we need to flag that row so that other rows are not validated.</p> <p>Following the same approach we did in previous parts, we’ll add a new <code>validity</code> property within every row in the <code>tableItems</code> data:</p> <pre class="grvsc-container grvsc-has-line-highlighting default-dark" data-language="javascript" data-index="2"><code class="grvsc-code"><span class="grvsc-line"><span class="grvsc-source"><span class="mtk11">mapItems</span><span class="mtk1">(</span><span class="mtk12">data</span><span class="mtk1">) {</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk15">return</span><span class="mtk1"> </span><span class="mtk12">data</span><span class="mtk1">.</span><span class="mtk11">map</span><span class="mtk1">((</span><span class="mtk12">item</span><span class="mtk1">, </span><span class="mtk12">index</span><span class="mtk1">) </span><span class="mtk4">=&gt;</span><span class="mtk1"> ({</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> ...</span><span class="mtk12">item</span><span class="mtk1">,</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">isEdit:</span><span class="mtk1"> </span><span class="mtk4">this</span><span class="mtk1">.</span><span class="mtk12">tableItems</span><span class="mtk1">[</span><span class="mtk12">index</span><span class="mtk1">] ? </span><span class="mtk4">this</span><span class="mtk1">.</span><span class="mtk12">tableItems</span><span class="mtk1">[</span><span class="mtk12">index</span><span class="mtk1">].</span><span class="mtk12">isEdit</span><span class="mtk1"> : </span><span class="mtk4">false</span><span class="mtk1">,</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">isSelected:</span><span class="mtk1"> </span><span class="mtk4">this</span><span class="mtk1">.</span><span class="mtk12">tableItems</span><span class="mtk1">[</span><span class="mtk12">index</span><span class="mtk1">]</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> ? </span><span class="mtk4">this</span><span class="mtk1">.</span><span class="mtk12">tableItems</span><span class="mtk1">[</span><span class="mtk12">index</span><span class="mtk1">].</span><span class="mtk12">isSelected</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> : </span><span class="mtk4">false</span><span class="mtk1">,</span></span></span> <span class="grvsc-line grvsc-line-highlighted"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">validity:</span><span class="mtk1"> </span><span class="mtk4">this</span><span class="mtk1">.</span><span class="mtk12">tableItems</span><span class="mtk1">[</span><span class="mtk12">index</span><span class="mtk1">] ? </span><span class="mtk4">this</span><span class="mtk1">.</span><span class="mtk12">tableItems</span><span class="mtk1">[</span><span class="mtk12">index</span><span class="mtk1">].</span><span class="mtk12">validity</span><span class="mtk1"> : {},</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> }));</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1">}</span></span></span></code></pre> <p>Similar to <code>isEdit</code> and <code>isSelected</code> properties, each row will have its validity object that will contain the fields that are being validated. For example, if the name and email fields of the first row are required, and the user leaves them empty, then the data array will look as follows:</p> <pre class="grvsc-container grvsc-has-line-highlighting default-dark" data-language="javascript" data-index="3"><code class="grvsc-code"><span class="grvsc-line"><span class="grvsc-source"><span class="mtk1">[</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> {</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">name:</span><span class="mtk1"> </span><span class="mtk8">&#39;&#39;</span><span class="mtk1">,</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">email:</span><span class="mtk1"> </span><span class="mtk8">&#39;&#39;</span><span class="mtk1">,</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">phone:</span><span class="mtk1"> </span><span class="mtk8">&#39;&#39;</span><span class="mtk1">,</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">isEdit:</span><span class="mtk1"> </span><span class="mtk4">true</span><span class="mtk1">,</span></span></span> <span class="grvsc-line grvsc-line-highlighted"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">validity:</span><span class="mtk1"> {</span></span></span> <span class="grvsc-line grvsc-line-highlighted"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">name:</span><span class="mtk1"> </span><span class="mtk4">false</span><span class="mtk1">,</span></span></span> <span class="grvsc-line grvsc-line-highlighted"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">email:</span><span class="mtk1"> </span><span class="mtk4">false</span></span></span> <span class="grvsc-line grvsc-line-highlighted"><span class="grvsc-source"><span class="mtk1"> },</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> ...</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> }</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1">]</span></span></span></code></pre> <p>Now, in the template, let’s add a <a href="https://bootstrap-vue.org/docs/components/form-input">bootstrap</a> <code>state</code> property that will automatically change the style of the input field based on a <code>Boolean</code> value:</p> <p><span class="gatsby-resp-image-wrapper" style="position: relative; display: block; margin-left: auto; margin-right: auto; max-width: 720px; " > <a class="gatsby-resp-image-link" href="/static/22901a0d40d7b1aecde2998f97a49114/2bef9/image-2-1024x176.png" style="display: block" target="_blank" rel="noopener" > <span class="gatsby-resp-image-background-image" style="padding-bottom: 17.22222222222222%; position: relative; bottom: 0; left: 0; background-image: url('data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABQAAAADCAIAAAAcOLh5AAAACXBIWXMAAAsTAAALEwEAmpwYAAAAVklEQVR42n3LSQ6AMAxD0d7/qqCCItI4I1R0DdZbePMbgN6PzLzfRQSPIUDd9S+rmqrO2MxWLBh7366LTEU/mIIHQaW5O9F8umIH6DiFucLTP0Q4cwAP6iuvwooNu3YAAAAASUVORK5CYII='); background-size: cover; display: block;" ></span> <img class="gatsby-resp-image-image" alt="image 2 1024x176" title="" src="/static/22901a0d40d7b1aecde2998f97a49114/37523/image-2-1024x176.png" srcset="/static/22901a0d40d7b1aecde2998f97a49114/e9ff0/image-2-1024x176.png 180w, /static/22901a0d40d7b1aecde2998f97a49114/f21e7/image-2-1024x176.png 360w, /static/22901a0d40d7b1aecde2998f97a49114/37523/image-2-1024x176.png 720w, /static/22901a0d40d7b1aecde2998f97a49114/2bef9/image-2-1024x176.png 1024w" sizes="(max-width: 720px) 100vw, 720px" style="width:100%;height:100%;margin:0;vertical-align:middle;position:absolute;top:0;left:0;" loading="lazy" decoding="async" /> </a> </span></p> <pre class="grvsc-container grvsc-has-line-highlighting default-dark" data-language="html" data-index="4"><code class="grvsc-code"><span class="grvsc-line"><span class="grvsc-source"><span class="mtk17">&lt;</span><span class="mtk4">b-form-input</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">v-else-if</span><span class="mtk1">=</span><span class="mtk8">&quot;field.type &amp;&amp; tableItems[data.index].isEdit&quot;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">:key</span><span class="mtk1">=</span><span class="mtk8">&quot;index&quot;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">:type</span><span class="mtk1">=</span><span class="mtk8">&quot;field.type&quot;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">:value</span><span class="mtk1">=</span><span class="mtk8">&quot;tableItems[data.index][field.key]&quot;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">@blur</span><span class="mtk1">=</span><span class="mtk8">&quot;(e) =&gt; inputHandler(e, data.index, field)&quot;</span></span></span> <span class="grvsc-line grvsc-line-highlighted"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">:state</span><span class="mtk1">=</span><span class="mtk8">&quot;tableItems[data.index].validity[field.key]&quot;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk17">&gt;&lt;/</span><span class="mtk4">b-form-input</span><span class="mtk17">&gt;</span></span></span></code></pre> <p>Since the template is iterating through rows and fields, we can quickly get the validity value using the index and field key (<code>true</code>, <code>false</code>, or <code>null</code> value).</p> <h2 id="add-input-field-validation" style="position:relative;"><a href="#add-input-field-validation" aria-label="add input field validation permalink" class="anchor before"><svg aria-hidden="true" focusable="false" height="16" version="1.1" viewBox="0 0 16 16" width="16"><path fill-rule="evenodd" d="M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z"></path></svg></a>Add Input Field Validation</h2> <p>There are multiple ways to validate the HTML input field. This tutorial will leverage the built-in HTML form validation by using the <code>required</code> and <code>pattern</code> attributes.</p> <p>Let’s start with a basic empty field validation:</p> <pre class="grvsc-container grvsc-has-line-highlighting default-dark" data-language="html" data-index="5"><code class="grvsc-code"><span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk17">&lt;</span><span class="mtk4">b-form-input</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">v-else-if</span><span class="mtk1">=</span><span class="mtk8">&quot;field.type &amp;&amp; tableItems[data.index].isEdit&quot;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">:key</span><span class="mtk1">=</span><span class="mtk8">&quot;index&quot;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">:type</span><span class="mtk1">=</span><span class="mtk8">&quot;field.type&quot;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">:value</span><span class="mtk1">=</span><span class="mtk8">&quot;tableItems[data.index][field.key]&quot;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">@blur</span><span class="mtk1">=</span><span class="mtk8">&quot;(e) =&gt; inputHandler(e, data.index, field)&quot;</span></span></span> <span class="grvsc-line grvsc-line-highlighted"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">:required</span><span class="mtk1">=</span><span class="mtk8">&quot;true&quot;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">:state</span><span class="mtk1">=</span><span class="mtk8">&quot;tableItems[data.index].validity[field.key]&quot;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk17">&gt;&lt;/</span><span class="mtk4">b-form-input</span><span class="mtk17">&gt;</span></span></span></code></pre> <p>Using the <code>inputHandler</code> event, we can get the validity value from the <code>target</code> object to set the required field of the current row.</p> <pre class="grvsc-container grvsc-has-line-highlighting default-dark" data-language="javascript" data-index="6"><code class="grvsc-code"><span class="grvsc-line"><span class="grvsc-source"><span class="mtk11">inputHandler</span><span class="mtk1">(</span><span class="mtk12">e</span><span class="mtk1">, </span><span class="mtk12">index</span><span class="mtk1">, </span><span class="mtk12">field</span><span class="mtk1">) {</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk3">// If the input is not valid, assign the validity of the specific field to false</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk15">if</span><span class="mtk1"> (!</span><span class="mtk12">e</span><span class="mtk1">.</span><span class="mtk12">target</span><span class="mtk1">.</span><span class="mtk12">validity</span><span class="mtk1">.</span><span class="mtk12">valid</span><span class="mtk1">) {</span></span></span> <span class="grvsc-line grvsc-line-highlighted"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk4">this</span><span class="mtk1">.</span><span class="mtk12">tableItems</span><span class="mtk1">[</span><span class="mtk12">index</span><span class="mtk1">].</span><span class="mtk12">validity</span><span class="mtk1">[</span><span class="mtk12">field</span><span class="mtk1">.</span><span class="mtk12">key</span><span class="mtk1">] = </span><span class="mtk4">false</span><span class="mtk1">;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk4">this</span><span class="mtk1">.</span><span class="mtk11">$set</span><span class="mtk1">(</span><span class="mtk4">this</span><span class="mtk1">.</span><span class="mtk12">tableItems</span><span class="mtk1">, </span><span class="mtk12">index</span><span class="mtk1">, </span><span class="mtk4">this</span><span class="mtk1">.</span><span class="mtk12">tableItems</span><span class="mtk1">[</span><span class="mtk12">index</span><span class="mtk1">]);</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> } </span><span class="mtk15">else</span><span class="mtk1"> { </span><span class="mtk3">// Otherwise make sure to assign the validity back to true or null</span></span></span> <span class="grvsc-line grvsc-line-highlighted"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk4">this</span><span class="mtk1">.</span><span class="mtk12">tableItems</span><span class="mtk1">[</span><span class="mtk12">index</span><span class="mtk1">].</span><span class="mtk12">validity</span><span class="mtk1">[</span><span class="mtk12">field</span><span class="mtk1">.</span><span class="mtk12">key</span><span class="mtk1">] = </span><span class="mtk4">true</span><span class="mtk1">;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk4">this</span><span class="mtk1">.</span><span class="mtk12">tableItems</span><span class="mtk1">[</span><span class="mtk12">index</span><span class="mtk1">][</span><span class="mtk12">field</span><span class="mtk1">.</span><span class="mtk12">key</span><span class="mtk1">] = </span><span class="mtk12">e</span><span class="mtk1">.</span><span class="mtk12">target</span><span class="mtk1">.</span><span class="mtk12">value</span><span class="mtk1">;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk4">this</span><span class="mtk1">.</span><span class="mtk11">$set</span><span class="mtk1">(</span><span class="mtk4">this</span><span class="mtk1">.</span><span class="mtk12">tableItems</span><span class="mtk1">, </span><span class="mtk12">index</span><span class="mtk1">, </span><span class="mtk4">this</span><span class="mtk1">.</span><span class="mtk12">tableItems</span><span class="mtk1">[</span><span class="mtk12">index</span><span class="mtk1">]);</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk4">this</span><span class="mtk1">.</span><span class="mtk11">$emit</span><span class="mtk1">(</span><span class="mtk8">&quot;input&quot;</span><span class="mtk1">, </span><span class="mtk4">this</span><span class="mtk1">.</span><span class="mtk12">tableItems</span><span class="mtk1">);</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> }</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1">}</span></span></span></code></pre> <p>Now, let’s try the <code>pattern</code> attribute for custom validation. For example, the regex pattern below only allows an email value that ends with “bootstrapvue.com”:</p> <pre class="grvsc-container grvsc-has-line-highlighting default-dark" data-language="html" data-index="7"><code class="grvsc-code"><span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk17">&lt;</span><span class="mtk4">b-form-input</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">v-else-if</span><span class="mtk1">=</span><span class="mtk8">&quot;field.type &amp;&amp; tableItems[data.index].isEdit&quot;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">:key</span><span class="mtk1">=</span><span class="mtk8">&quot;index&quot;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">:type</span><span class="mtk1">=</span><span class="mtk8">&quot;field.type&quot;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">:value</span><span class="mtk1">=</span><span class="mtk8">&quot;tableItems[data.index][field.key]&quot;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">@blur</span><span class="mtk1">=</span><span class="mtk8">&quot;(e) =&gt; inputHandler(e, data.index, field)&quot;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">:required</span><span class="mtk1">=</span><span class="mtk8">&quot;true&quot;</span></span></span> <span class="grvsc-line grvsc-line-highlighted"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">:pattern</span><span class="mtk1">=</span><span class="mtk8">&quot;.+@bootstrapvue\.com&quot;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">:state</span><span class="mtk1">=</span><span class="mtk8">&quot;tableItems[data.index].validity[field.key]&quot;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk17">&gt;&lt;/</span><span class="mtk4">b-form-input</span><span class="mtk17">&gt;</span></span></span></code></pre> <p>Lastly, we can disable the “Done” button if the fields are invalid using the <code>disabled</code> attribute.</p> <p>Let’s write a function that checks if any of the <code>validity</code> values are <code>false</code>, then the button gets disabled:</p> <pre class="grvsc-container default-dark" data-language="javascript" data-index="8"><code class="grvsc-code"><span class="grvsc-line"><span class="grvsc-source"><span class="mtk11">disableButton</span><span class="mtk1">(</span><span class="mtk12">data</span><span class="mtk1">) {</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk15">return</span><span class="mtk1"> </span><span class="mtk10">Object</span><span class="mtk1">.</span><span class="mtk11">values</span><span class="mtk1">(</span><span class="mtk12">data</span><span class="mtk1">.</span><span class="mtk12">item</span><span class="mtk1">.</span><span class="mtk12">validity</span><span class="mtk1">).</span><span class="mtk11">some</span><span class="mtk1">(</span><span class="mtk12">valid</span><span class="mtk1"> </span><span class="mtk4">=&gt;</span><span class="mtk1"> !</span><span class="mtk12">valid</span><span class="mtk1">);</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1">}</span></span></span></code></pre> <pre class="grvsc-container default-dark" data-language="html" data-index="9"><code class="grvsc-code"><span class="grvsc-line"><span class="grvsc-source"><span class="mtk17">&lt;</span><span class="mtk4">b-button</span><span class="mtk1"> </span><span class="mtk12">@click</span><span class="mtk1">=</span><span class="mtk8">&quot;editRowHandler(data, field)&quot;</span><span class="mtk1"> </span><span class="mtk12">:disabled</span><span class="mtk1">=</span><span class="mtk8">&quot;disableButton(data)&quot;</span><span class="mtk17">&gt;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk17">&lt;</span><span class="mtk4">span</span><span class="mtk1"> </span><span class="mtk12">v-if</span><span class="mtk1">=</span><span class="mtk8">&quot;!tableItems[data.index].isEdit&quot;</span><span class="mtk17">&gt;</span><span class="mtk1">Edit</span><span class="mtk17">&lt;/</span><span class="mtk4">span</span><span class="mtk17">&gt;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk17">&lt;</span><span class="mtk4">span</span><span class="mtk1"> </span><span class="mtk12">v-else</span><span class="mtk17">&gt;</span><span class="mtk1">Done</span><span class="mtk17">&lt;/</span><span class="mtk4">span</span><span class="mtk17">&gt;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk17">&lt;/</span><span class="mtk4">b-button</span><span class="mtk17">&gt;</span></span></span></code></pre> <p><span class="gatsby-resp-image-wrapper" style="position: relative; display: block; margin-left: auto; margin-right: auto; max-width: 720px; " > <a class="gatsby-resp-image-link" href="/static/5d3252d56b6ca84e096eb11f0903860c/2bef9/image-3-1024x119.png" style="display: block" target="_blank" rel="noopener" > <span class="gatsby-resp-image-background-image" style="padding-bottom: 11.666666666666666%; position: relative; bottom: 0; left: 0; background-image: url('data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABQAAAACCAIAAADXZGvcAAAACXBIWXMAAAsTAAALEwEAmpwYAAAAbklEQVR42iWLSwrCQBAFc/8zCNl4C0EIiAtPYMgRNNPT3+npBMYG3+pRVE1nrsfR/PD+P8EiFeHzZahJQjTMRBWRENG9jzEez9d73aZstVmphZXjjBZNXCvhDiUhILCxuokIMRNx+hlf5uvtvvwAQXdwphKawXsAAAAASUVORK5CYII='); background-size: cover; display: block;" ></span> <img class="gatsby-resp-image-image" alt="image 3 1024x119" title="" src="/static/5d3252d56b6ca84e096eb11f0903860c/37523/image-3-1024x119.png" srcset="/static/5d3252d56b6ca84e096eb11f0903860c/e9ff0/image-3-1024x119.png 180w, /static/5d3252d56b6ca84e096eb11f0903860c/f21e7/image-3-1024x119.png 360w, /static/5d3252d56b6ca84e096eb11f0903860c/37523/image-3-1024x119.png 720w, /static/5d3252d56b6ca84e096eb11f0903860c/2bef9/image-3-1024x119.png 1024w" sizes="(max-width: 720px) 100vw, 720px" style="width:100%;height:100%;margin:0;vertical-align:middle;position:absolute;top:0;left:0;" loading="lazy" decoding="async" /> </a> </span></p> <h2 id="enable-dynamic-validation" style="position:relative;"><a href="#enable-dynamic-validation" aria-label="enable dynamic validation permalink" class="anchor before"><svg aria-hidden="true" focusable="false" height="16" version="1.1" viewBox="0 0 16 16" width="16"><path fill-rule="evenodd" d="M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z"></path></svg></a>Enable Dynamic Validation</h2> <p>So far, we were able to add a required and custom validation to the input field. But since the code above is hard coded, every input field will be validated.</p> <p>Since this is a dynamic table and column types are defined by the consumer in the main <code>app.vue</code> component, we can enable passing the validation attributes as well so only required columns are validated:</p> <pre class="grvsc-container grvsc-has-line-highlighting default-dark" data-language="javascript" data-index="10"><code class="grvsc-code"><span class="grvsc-line"><span class="grvsc-source"><span class="mtk1">fields: [</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> { </span><span class="mtk12">key:</span><span class="mtk1"> </span><span class="mtk8">&quot;selectRow&quot;</span><span class="mtk1">, </span><span class="mtk12">label:</span><span class="mtk1"> </span><span class="mtk8">&quot;&quot;</span><span class="mtk1"> },</span></span></span> <span class="grvsc-line grvsc-line-highlighted"><span class="grvsc-source"><span class="mtk1"> { </span><span class="mtk12">key:</span><span class="mtk1"> </span><span class="mtk8">&quot;name&quot;</span><span class="mtk1">, </span><span class="mtk12">label:</span><span class="mtk1"> </span><span class="mtk8">&quot;Name&quot;</span><span class="mtk1">, </span><span class="mtk12">type:</span><span class="mtk1"> </span><span class="mtk8">&quot;text&quot;</span><span class="mtk1">, </span><span class="mtk12">required:</span><span class="mtk1"> </span><span class="mtk4">true</span><span class="mtk1"> },</span></span></span> <span class="grvsc-line grvsc-line-highlighted"><span class="grvsc-source"><span class="mtk1"> { </span><span class="mtk12">key:</span><span class="mtk1"> </span><span class="mtk8">&quot;email&quot;</span><span class="mtk1">, </span><span class="mtk12">label:</span><span class="mtk1"> </span><span class="mtk8">&quot;Email&quot;</span><span class="mtk1">, </span><span class="mtk12">type:</span><span class="mtk1"> </span><span class="mtk8">&quot;email&quot;</span><span class="mtk1">, </span><span class="mtk12">required:</span><span class="mtk1"> </span><span class="mtk4">true</span><span class="mtk1">, </span><span class="mtk12">pattern:</span><span class="mtk1"> </span><span class="mtk8">&quot;.+@bootstrapvue</span><span class="mtk6">\\</span><span class="mtk8">.com&quot;</span><span class="mtk1"> },</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> { </span><span class="mtk12">key:</span><span class="mtk1"> </span><span class="mtk8">&quot;phone&quot;</span><span class="mtk1">, </span><span class="mtk12">label:</span><span class="mtk1"> </span><span class="mtk8">&quot;Phone&quot;</span><span class="mtk1">, </span><span class="mtk12">type:</span><span class="mtk1"> </span><span class="mtk8">&quot;text&quot;</span><span class="mtk1"> },</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> { </span><span class="mtk12">key:</span><span class="mtk1"> </span><span class="mtk8">&quot;edit&quot;</span><span class="mtk1">, </span><span class="mtk12">label:</span><span class="mtk1"> </span><span class="mtk8">&quot;&quot;</span><span class="mtk1">, </span><span class="mtk12">type:</span><span class="mtk1"> </span><span class="mtk8">&quot;edit&quot;</span><span class="mtk1"> },</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1">]</span></span></span></code></pre> <p>Then, in <code>EditableTable.vue</code>, the <code>required</code> and <code>pattern</code> attributes will read from the <code>field</code> object instead of hard coding a value.</p> <pre class="grvsc-container grvsc-has-line-highlighting default-dark" data-language="html" data-index="11"><code class="grvsc-code"><span class="grvsc-line"><span class="grvsc-source"><span class="mtk17">&lt;</span><span class="mtk4">b-form-input</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">v-else-if</span><span class="mtk1">=</span><span class="mtk8">&quot;field.type &amp;&amp; tableItems[data.index].isEdit&quot;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">:key</span><span class="mtk1">=</span><span class="mtk8">&quot;index&quot;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">:type</span><span class="mtk1">=</span><span class="mtk8">&quot;field.type&quot;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">:value</span><span class="mtk1">=</span><span class="mtk8">&quot;tableItems[data.index][field.key]&quot;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">@blur</span><span class="mtk1">=</span><span class="mtk8">&quot;(e) =&gt; inputHandler(e, data.index, field)&quot;</span></span></span> <span class="grvsc-line grvsc-line-highlighted"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">:required</span><span class="mtk1">=</span><span class="mtk8">&quot;field.required&quot;</span></span></span> <span class="grvsc-line grvsc-line-highlighted"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">:pattern</span><span class="mtk1">=</span><span class="mtk8">&quot;field.pattern&quot;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">:state</span><span class="mtk1">=</span><span class="mtk8">&quot;tableItems[data.index].validity[field.key]&quot;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk17">&gt;&lt;/</span><span class="mtk4">b-form-input</span><span class="mtk17">&gt;</span></span></span></code></pre> <p>This way, if needed, each column can have its’ own custom validation.</p> <p>Below is the complete code:</p> <h5 id="editabletable-component-1" style="position:relative;"><a href="#editabletable-component-1" aria-label="editabletable component 1 permalink" class="anchor before"><svg aria-hidden="true" focusable="false" height="16" version="1.1" viewBox="0 0 16 16" width="16"><path fill-rule="evenodd" d="M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z"></path></svg></a>EditableTable Component</h5> <pre class="grvsc-container default-dark" data-language="html" data-index="12"><code class="grvsc-code"><span class="grvsc-line"><span class="grvsc-source"><span class="mtk17">&lt;</span><span class="mtk4">template</span><span class="mtk17">&gt;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk17">&lt;</span><span class="mtk4">article</span><span class="mtk17">&gt;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk17">&lt;</span><span class="mtk4">b-modal</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">id</span><span class="mtk1">=</span><span class="mtk8">&quot;modal-1&quot;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">title</span><span class="mtk1">=</span><span class="mtk8">&quot;Confirm&quot;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">v-model</span><span class="mtk1">=</span><span class="mtk8">&quot;openDialog&quot;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">ok-title</span><span class="mtk1">=</span><span class="mtk8">&quot;Remove&quot;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">@ok</span><span class="mtk1">=</span><span class="mtk8">&quot;removeRowsHandler&quot;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk17">&gt;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk17">&lt;</span><span class="mtk4">p</span><span class="mtk1"> </span><span class="mtk12">class</span><span class="mtk1">=</span><span class="mtk8">&quot;my-4&quot;</span><span class="mtk17">&gt;</span><span class="mtk1">Are you sure you want to remove the selected rows?</span><span class="mtk17">&lt;/</span><span class="mtk4">p</span><span class="mtk17">&gt;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk17">&lt;/</span><span class="mtk4">b-modal</span><span class="mtk17">&gt;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk17">&lt;</span><span class="mtk4">div</span><span class="mtk1"> </span><span class="mtk12">class</span><span class="mtk1">=</span><span class="mtk8">&quot;action-container&quot;</span><span class="mtk17">&gt;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk17">&lt;</span><span class="mtk4">b-button</span><span class="mtk1"> </span><span class="mtk12">class</span><span class="mtk1">=</span><span class="mtk8">&quot;add-button&quot;</span><span class="mtk1"> </span><span class="mtk12">variant</span><span class="mtk1">=</span><span class="mtk8">&quot;success&quot;</span><span class="mtk1"> </span><span class="mtk12">@click</span><span class="mtk1">=</span><span class="mtk8">&quot;addRowHandler&quot;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk17">&gt;</span><span class="mtk1">Add Row</span><span class="mtk17">&lt;/</span><span class="mtk4">b-button</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk17">&gt;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk17">&lt;</span><span class="mtk4">b-button</span><span class="mtk1"> </span><span class="mtk12">variant</span><span class="mtk1">=</span><span class="mtk8">&quot;danger&quot;</span><span class="mtk1"> </span><span class="mtk12">@click</span><span class="mtk1">=</span><span class="mtk8">&quot;openDialog = true&quot;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk17">&gt;</span><span class="mtk1">Remove Rows</span><span class="mtk17">&lt;/</span><span class="mtk4">b-button</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk17">&gt;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk17">&lt;/</span><span class="mtk4">div</span><span class="mtk17">&gt;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk17">&lt;</span><span class="mtk4">b-table</span><span class="mtk1"> </span><span class="mtk12">class</span><span class="mtk1">=</span><span class="mtk8">&quot;b-table&quot;</span><span class="mtk1"> </span><span class="mtk12">:items</span><span class="mtk1">=</span><span class="mtk8">&quot;tableItems&quot;</span><span class="mtk1"> </span><span class="mtk12">:fields</span><span class="mtk1">=</span><span class="mtk8">&quot;fields&quot;</span><span class="mtk1"> </span><span class="mtk12">fixed</span><span class="mtk17">&gt;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk17">&lt;</span><span class="mtk4">template</span><span class="mtk1"> </span><span class="mtk12">v-for</span><span class="mtk1">=</span><span class="mtk8">&quot;(field, index) in fields&quot;</span><span class="mtk1"> </span><span class="mtk12">#[`cell(${field.key})`]</span><span class="mtk1">=</span><span class="mtk8">&quot;data&quot;</span><span class="mtk17">&gt;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk17">&lt;</span><span class="mtk4">b-form-datepicker</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">v-if</span><span class="mtk1">=</span><span class="mtk8">&quot;field.type === &#39;date&#39; &amp;&amp; tableItems[data.index].isEdit&quot;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">:key</span><span class="mtk1">=</span><span class="mtk8">&quot;index&quot;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">:type</span><span class="mtk1">=</span><span class="mtk8">&quot;field.type&quot;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">:value</span><span class="mtk1">=</span><span class="mtk8">&quot;tableItems[data.index][field.key]&quot;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">@input</span><span class="mtk1">=</span><span class="mtk8">&quot;(value) =&gt; inputHandler(value, data.index, field)&quot;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk17">&gt;&lt;/</span><span class="mtk4">b-form-datepicker</span><span class="mtk17">&gt;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk17">&lt;</span><span class="mtk4">b-form-select</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">v-else-if</span><span class="mtk1">=</span><span class="mtk8">&quot;field.type === &#39;select&#39; &amp;&amp; tableItems[data.index].isEdit&quot;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">:key</span><span class="mtk1">=</span><span class="mtk8">&quot;index&quot;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">:value</span><span class="mtk1">=</span><span class="mtk8">&quot;tableItems[data.index][field.key]&quot;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">@input</span><span class="mtk1">=</span><span class="mtk8">&quot;(value) =&gt; inputHandler(value, data.index, field)&quot;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">:options</span><span class="mtk1">=</span><span class="mtk8">&quot;field.options&quot;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk17">&gt;&lt;/</span><span class="mtk4">b-form-select</span><span class="mtk17">&gt;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk17">&lt;</span><span class="mtk4">b-checkbox</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">v-else-if</span><span class="mtk1">=</span><span class="mtk8">&quot;field.key === &#39;selectRow&#39;&quot;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">:checked</span><span class="mtk1">=</span><span class="mtk8">&quot;tableItems[data.index].isSelected&quot;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">:key</span><span class="mtk1">=</span><span class="mtk8">&quot;index&quot;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">@change</span><span class="mtk1">=</span><span class="mtk8">&quot;selectRowHandler(data)&quot;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk17">&gt;&lt;/</span><span class="mtk4">b-checkbox</span><span class="mtk17">&gt;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk17">&lt;</span><span class="mtk4">div</span><span class="mtk1"> </span><span class="mtk12">:key</span><span class="mtk1">=</span><span class="mtk8">&quot;index&quot;</span><span class="mtk1"> </span><span class="mtk12">v-else-if</span><span class="mtk1">=</span><span class="mtk8">&quot;field.type === &#39;edit&#39;&quot;</span><span class="mtk17">&gt;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk17">&lt;</span><span class="mtk4">b-button</span><span class="mtk1"> </span><span class="mtk12">@click</span><span class="mtk1">=</span><span class="mtk8">&quot;editRowHandler(data, field)&quot;</span><span class="mtk1"> </span><span class="mtk12">:disabled</span><span class="mtk1">=</span><span class="mtk8">&quot;disableButton(data)&quot;</span><span class="mtk17">&gt;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk17">&lt;</span><span class="mtk4">span</span><span class="mtk1"> </span><span class="mtk12">v-if</span><span class="mtk1">=</span><span class="mtk8">&quot;!tableItems[data.index].isEdit&quot;</span><span class="mtk17">&gt;</span><span class="mtk1">Edit</span><span class="mtk17">&lt;/</span><span class="mtk4">span</span><span class="mtk17">&gt;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk17">&lt;</span><span class="mtk4">span</span><span class="mtk1"> </span><span class="mtk12">v-else</span><span class="mtk17">&gt;</span><span class="mtk1">Done</span><span class="mtk17">&lt;/</span><span class="mtk4">span</span><span class="mtk17">&gt;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk17">&lt;/</span><span class="mtk4">b-button</span><span class="mtk17">&gt;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk17">&lt;</span><span class="mtk4">b-button</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">v-if</span><span class="mtk1">=</span><span class="mtk8">&quot;!tableItems[data.index].isEdit&quot;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">class</span><span class="mtk1">=</span><span class="mtk8">&quot;delete-button&quot;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">variant</span><span class="mtk1">=</span><span class="mtk8">&quot;danger&quot;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">@click</span><span class="mtk1">=</span><span class="mtk8">&quot;removeRowHandler(data.index)&quot;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk17">&gt;</span><span class="mtk1">Remove</span><span class="mtk17">&lt;/</span><span class="mtk4">b-button</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk17">&gt;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk17">&lt;/</span><span class="mtk4">div</span><span class="mtk17">&gt;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk17">&lt;</span><span class="mtk4">b-form-input</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">v-else-if</span><span class="mtk1">=</span><span class="mtk8">&quot;field.type &amp;&amp; tableItems[data.index].isEdit&quot;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">:key</span><span class="mtk1">=</span><span class="mtk8">&quot;index&quot;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">:type</span><span class="mtk1">=</span><span class="mtk8">&quot;field.type&quot;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">:value</span><span class="mtk1">=</span><span class="mtk8">&quot;tableItems[data.index][field.key]&quot;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">@blur</span><span class="mtk1">=</span><span class="mtk8">&quot;(e) =&gt; inputHandler(e, data.index, field)&quot;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">:required</span><span class="mtk1">=</span><span class="mtk8">&quot;field.required&quot;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">:pattern</span><span class="mtk1">=</span><span class="mtk8">&quot;field.pattern&quot;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">:state</span><span class="mtk1">=</span><span class="mtk8">&quot;tableItems[data.index].validity[field.key]&quot;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk17">&gt;&lt;/</span><span class="mtk4">b-form-input</span><span class="mtk17">&gt;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk17">&lt;</span><span class="mtk4">span</span><span class="mtk1"> </span><span class="mtk12">:key</span><span class="mtk1">=</span><span class="mtk8">&quot;index&quot;</span><span class="mtk1"> </span><span class="mtk12">v-else</span><span class="mtk17">&gt;</span><span class="mtk1">{{ data.value }}</span><span class="mtk17">&lt;/</span><span class="mtk4">span</span><span class="mtk17">&gt;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk17">&lt;/</span><span class="mtk4">template</span><span class="mtk17">&gt;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk17">&lt;/</span><span class="mtk4">b-table</span><span class="mtk17">&gt;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk17">&lt;/</span><span class="mtk4">article</span><span class="mtk17">&gt;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk17">&lt;/</span><span class="mtk4">template</span><span class="mtk17">&gt;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk17">&lt;</span><span class="mtk4">script</span><span class="mtk17">&gt;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk15">export</span><span class="mtk1"> </span><span class="mtk15">default</span><span class="mtk1"> {</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">name:</span><span class="mtk1"> </span><span class="mtk8">&quot;EditableTable&quot;</span><span class="mtk1">,</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">components:</span><span class="mtk1"> {},</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">props:</span><span class="mtk1"> {</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">value:</span><span class="mtk1"> </span><span class="mtk10">Array</span><span class="mtk1">,</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">fields:</span><span class="mtk1"> </span><span class="mtk10">Array</span><span class="mtk1">,</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> },</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk11">data</span><span class="mtk1">() {</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk15">return</span><span class="mtk1"> {</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">tableItems:</span><span class="mtk1"> </span><span class="mtk4">this</span><span class="mtk1">.</span><span class="mtk11">mapItems</span><span class="mtk1">(</span><span class="mtk4">this</span><span class="mtk1">.</span><span class="mtk12">value</span><span class="mtk1">),</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">openDialog:</span><span class="mtk1"> </span><span class="mtk4">false</span><span class="mtk1">,</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> };</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> },</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">watch:</span><span class="mtk1"> {</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk11">value</span><span class="mtk1">(</span><span class="mtk12">newVal</span><span class="mtk1">) {</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk4">this</span><span class="mtk1">.</span><span class="mtk12">tableItems</span><span class="mtk1"> = </span><span class="mtk4">this</span><span class="mtk1">.</span><span class="mtk11">mapItems</span><span class="mtk1">(</span><span class="mtk12">newVal</span><span class="mtk1">);</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> },</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> },</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">methods:</span><span class="mtk1"> {</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk11">editRowHandler</span><span class="mtk1">(</span><span class="mtk12">data</span><span class="mtk1">) {</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk15">if</span><span class="mtk1"> (</span><span class="mtk4">this</span><span class="mtk1">.</span><span class="mtk12">tableItems</span><span class="mtk1">[</span><span class="mtk12">data</span><span class="mtk1">.</span><span class="mtk12">index</span><span class="mtk1">].</span><span class="mtk12">isEdit</span><span class="mtk1">) {</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk4">this</span><span class="mtk1">.</span><span class="mtk11">$emit</span><span class="mtk1">(</span><span class="mtk8">&quot;submit&quot;</span><span class="mtk1">, </span><span class="mtk4">this</span><span class="mtk1">.</span><span class="mtk12">tableItems</span><span class="mtk1">[</span><span class="mtk12">data</span><span class="mtk1">.</span><span class="mtk12">index</span><span class="mtk1">]);</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> }</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk4">this</span><span class="mtk1">.</span><span class="mtk12">tableItems</span><span class="mtk1">[</span><span class="mtk12">data</span><span class="mtk1">.</span><span class="mtk12">index</span><span class="mtk1">].</span><span class="mtk12">isEdit</span><span class="mtk1"> = !</span><span class="mtk4">this</span><span class="mtk1">.</span><span class="mtk12">tableItems</span><span class="mtk1">[</span><span class="mtk12">data</span><span class="mtk1">.</span><span class="mtk12">index</span><span class="mtk1">].</span><span class="mtk12">isEdit</span><span class="mtk1">;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk4">this</span><span class="mtk1">.</span><span class="mtk12">tableItems</span><span class="mtk1">[</span><span class="mtk12">data</span><span class="mtk1">.</span><span class="mtk12">index</span><span class="mtk1">].</span><span class="mtk12">validity</span><span class="mtk1"> = {};</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk4">this</span><span class="mtk1">.</span><span class="mtk11">$set</span><span class="mtk1">(</span><span class="mtk4">this</span><span class="mtk1">.</span><span class="mtk12">tableItems</span><span class="mtk1">, </span><span class="mtk12">data</span><span class="mtk1">.</span><span class="mtk12">index</span><span class="mtk1">, </span><span class="mtk4">this</span><span class="mtk1">.</span><span class="mtk12">tableItems</span><span class="mtk1">[</span><span class="mtk12">data</span><span class="mtk1">.</span><span class="mtk12">index</span><span class="mtk1">]);</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> },</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk11">inputHandler</span><span class="mtk1">(</span><span class="mtk12">e</span><span class="mtk1">, </span><span class="mtk12">index</span><span class="mtk1">, </span><span class="mtk12">field</span><span class="mtk1">) {</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk15">if</span><span class="mtk1"> (!</span><span class="mtk12">e</span><span class="mtk1">.</span><span class="mtk12">target</span><span class="mtk1">.</span><span class="mtk12">validity</span><span class="mtk1">.</span><span class="mtk12">valid</span><span class="mtk1">) {</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk4">this</span><span class="mtk1">.</span><span class="mtk12">tableItems</span><span class="mtk1">[</span><span class="mtk12">index</span><span class="mtk1">].</span><span class="mtk12">validity</span><span class="mtk1">[</span><span class="mtk12">field</span><span class="mtk1">.</span><span class="mtk12">key</span><span class="mtk1">] = </span><span class="mtk4">false</span><span class="mtk1">;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk4">this</span><span class="mtk1">.</span><span class="mtk11">$set</span><span class="mtk1">(</span><span class="mtk4">this</span><span class="mtk1">.</span><span class="mtk12">tableItems</span><span class="mtk1">, </span><span class="mtk12">index</span><span class="mtk1">, </span><span class="mtk4">this</span><span class="mtk1">.</span><span class="mtk12">tableItems</span><span class="mtk1">[</span><span class="mtk12">index</span><span class="mtk1">]);</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> } </span><span class="mtk15">else</span><span class="mtk1"> {</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk15">if</span><span class="mtk1"> (</span><span class="mtk12">field</span><span class="mtk1">.</span><span class="mtk12">required</span><span class="mtk1"> || </span><span class="mtk12">field</span><span class="mtk1">.</span><span class="mtk12">patter</span><span class="mtk1">) {</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk4">this</span><span class="mtk1">.</span><span class="mtk12">tableItems</span><span class="mtk1">[</span><span class="mtk12">index</span><span class="mtk1">].</span><span class="mtk12">validity</span><span class="mtk1">[</span><span class="mtk12">field</span><span class="mtk1">.</span><span class="mtk12">key</span><span class="mtk1">] = </span><span class="mtk4">true</span><span class="mtk1">;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> }</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk4">this</span><span class="mtk1">.</span><span class="mtk12">tableItems</span><span class="mtk1">[</span><span class="mtk12">index</span><span class="mtk1">][</span><span class="mtk12">field</span><span class="mtk1">.</span><span class="mtk12">key</span><span class="mtk1">] = </span><span class="mtk12">e</span><span class="mtk1">.</span><span class="mtk12">target</span><span class="mtk1">.</span><span class="mtk12">value</span><span class="mtk1">;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk4">this</span><span class="mtk1">.</span><span class="mtk11">$set</span><span class="mtk1">(</span><span class="mtk4">this</span><span class="mtk1">.</span><span class="mtk12">tableItems</span><span class="mtk1">, </span><span class="mtk12">index</span><span class="mtk1">, </span><span class="mtk4">this</span><span class="mtk1">.</span><span class="mtk12">tableItems</span><span class="mtk1">[</span><span class="mtk12">index</span><span class="mtk1">]);</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk4">this</span><span class="mtk1">.</span><span class="mtk11">$emit</span><span class="mtk1">(</span><span class="mtk8">&quot;input&quot;</span><span class="mtk1">, </span><span class="mtk4">this</span><span class="mtk1">.</span><span class="mtk12">tableItems</span><span class="mtk1">);</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> }</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> },</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk11">addRowHandler</span><span class="mtk1">() {</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk4">const</span><span class="mtk1"> </span><span class="mtk12">newRow</span><span class="mtk1"> = </span><span class="mtk4">this</span><span class="mtk1">.</span><span class="mtk12">fields</span><span class="mtk1">.</span><span class="mtk11">reduce</span><span class="mtk1">(</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> (</span><span class="mtk12">a</span><span class="mtk1">, </span><span class="mtk12">c</span><span class="mtk1">) </span><span class="mtk4">=&gt;</span><span class="mtk1"> ({ ...</span><span class="mtk12">a</span><span class="mtk1">, </span><span class="mtk12">[c.key]:</span><span class="mtk1"> </span><span class="mtk4">null</span><span class="mtk1"> }),</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> {}</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> );</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">newRow</span><span class="mtk1">.</span><span class="mtk12">isEdit</span><span class="mtk1"> = </span><span class="mtk4">true</span><span class="mtk1">;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk4">this</span><span class="mtk1">.</span><span class="mtk12">tableItems</span><span class="mtk1">.</span><span class="mtk11">unshift</span><span class="mtk1">(</span><span class="mtk12">newRow</span><span class="mtk1">);</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk4">this</span><span class="mtk1">.</span><span class="mtk11">$emit</span><span class="mtk1">(</span><span class="mtk8">&quot;input&quot;</span><span class="mtk1">, </span><span class="mtk4">this</span><span class="mtk1">.</span><span class="mtk12">tableItems</span><span class="mtk1">);</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> },</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk11">removeRowHandler</span><span class="mtk1">(</span><span class="mtk12">index</span><span class="mtk1">) {</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk4">this</span><span class="mtk1">.</span><span class="mtk12">tableItems</span><span class="mtk1"> = </span><span class="mtk4">this</span><span class="mtk1">.</span><span class="mtk12">tableItems</span><span class="mtk1">.</span><span class="mtk11">filter</span><span class="mtk1">((</span><span class="mtk12">item</span><span class="mtk1">, </span><span class="mtk12">i</span><span class="mtk1">) </span><span class="mtk4">=&gt;</span><span class="mtk1"> </span><span class="mtk12">i</span><span class="mtk1"> !== </span><span class="mtk12">index</span><span class="mtk1">);</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk4">this</span><span class="mtk1">.</span><span class="mtk11">$emit</span><span class="mtk1">(</span><span class="mtk8">&quot;input&quot;</span><span class="mtk1">, </span><span class="mtk4">this</span><span class="mtk1">.</span><span class="mtk12">tableItems</span><span class="mtk1">);</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk4">this</span><span class="mtk1">.</span><span class="mtk11">$emit</span><span class="mtk1">(</span><span class="mtk8">&quot;remove&quot;</span><span class="mtk1">, </span><span class="mtk4">this</span><span class="mtk1">.</span><span class="mtk12">tableItems</span><span class="mtk1">[</span><span class="mtk12">index</span><span class="mtk1">]);</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> },</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk11">removeRowsHandler</span><span class="mtk1">() {</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk4">const</span><span class="mtk1"> </span><span class="mtk12">selectedItems</span><span class="mtk1"> = </span><span class="mtk4">this</span><span class="mtk1">.</span><span class="mtk12">tableItems</span><span class="mtk1">.</span><span class="mtk11">filter</span><span class="mtk1">((</span><span class="mtk12">item</span><span class="mtk1">) </span><span class="mtk4">=&gt;</span><span class="mtk1"> </span><span class="mtk12">item</span><span class="mtk1">.</span><span class="mtk12">isSelected</span><span class="mtk1">);</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk4">this</span><span class="mtk1">.</span><span class="mtk12">tableItems</span><span class="mtk1"> = </span><span class="mtk4">this</span><span class="mtk1">.</span><span class="mtk12">tableItems</span><span class="mtk1">.</span><span class="mtk11">filter</span><span class="mtk1">((</span><span class="mtk12">item</span><span class="mtk1">) </span><span class="mtk4">=&gt;</span><span class="mtk1"> !</span><span class="mtk12">item</span><span class="mtk1">.</span><span class="mtk12">isSelected</span><span class="mtk1">);</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk4">this</span><span class="mtk1">.</span><span class="mtk11">$emit</span><span class="mtk1">(</span><span class="mtk8">&quot;input&quot;</span><span class="mtk1">, </span><span class="mtk4">this</span><span class="mtk1">.</span><span class="mtk12">tableItems</span><span class="mtk1">);</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk4">this</span><span class="mtk1">.</span><span class="mtk11">$emit</span><span class="mtk1">(</span><span class="mtk8">&quot;remove&quot;</span><span class="mtk1">, </span><span class="mtk12">selectedItems</span><span class="mtk1">);</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> },</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk11">selectRowHandler</span><span class="mtk1">(</span><span class="mtk12">data</span><span class="mtk1">) {</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk4">this</span><span class="mtk1">.</span><span class="mtk12">tableItems</span><span class="mtk1">[</span><span class="mtk12">data</span><span class="mtk1">.</span><span class="mtk12">index</span><span class="mtk1">].</span><span class="mtk12">isSelected</span><span class="mtk1"> = !</span><span class="mtk4">this</span><span class="mtk1">.</span><span class="mtk12">tableItems</span><span class="mtk1">[</span><span class="mtk12">data</span><span class="mtk1">.</span><span class="mtk12">index</span><span class="mtk1">]</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> .</span><span class="mtk12">isSelected</span><span class="mtk1">;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> },</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk11">disableButton</span><span class="mtk1">(</span><span class="mtk12">data</span><span class="mtk1">) {</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk15">return</span><span class="mtk1"> </span><span class="mtk10">Object</span><span class="mtk1">.</span><span class="mtk11">values</span><span class="mtk1">(</span><span class="mtk12">data</span><span class="mtk1">.</span><span class="mtk12">item</span><span class="mtk1">.</span><span class="mtk12">validity</span><span class="mtk1">).</span><span class="mtk11">some</span><span class="mtk1">(</span><span class="mtk12">valid</span><span class="mtk1"> </span><span class="mtk4">=&gt;</span><span class="mtk1"> !</span><span class="mtk12">valid</span><span class="mtk1">);</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> },</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk11">mapItems</span><span class="mtk1">(</span><span class="mtk12">data</span><span class="mtk1">) {</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk15">return</span><span class="mtk1"> </span><span class="mtk12">data</span><span class="mtk1">.</span><span class="mtk11">map</span><span class="mtk1">((</span><span class="mtk12">item</span><span class="mtk1">, </span><span class="mtk12">index</span><span class="mtk1">) </span><span class="mtk4">=&gt;</span><span class="mtk1"> ({</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> ...</span><span class="mtk12">item</span><span class="mtk1">,</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">isEdit:</span><span class="mtk1"> </span><span class="mtk4">this</span><span class="mtk1">.</span><span class="mtk12">tableItems</span><span class="mtk1">[</span><span class="mtk12">index</span><span class="mtk1">] ? </span><span class="mtk4">this</span><span class="mtk1">.</span><span class="mtk12">tableItems</span><span class="mtk1">[</span><span class="mtk12">index</span><span class="mtk1">].</span><span class="mtk12">isEdit</span><span class="mtk1"> : </span><span class="mtk4">false</span><span class="mtk1">,</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">isSelected:</span><span class="mtk1"> </span><span class="mtk4">this</span><span class="mtk1">.</span><span class="mtk12">tableItems</span><span class="mtk1">[</span><span class="mtk12">index</span><span class="mtk1">]</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> ? </span><span class="mtk4">this</span><span class="mtk1">.</span><span class="mtk12">tableItems</span><span class="mtk1">[</span><span class="mtk12">index</span><span class="mtk1">].</span><span class="mtk12">isSelected</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> : </span><span class="mtk4">false</span><span class="mtk1">,</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">validity:</span><span class="mtk1"> </span><span class="mtk4">this</span><span class="mtk1">.</span><span class="mtk12">tableItems</span><span class="mtk1">[</span><span class="mtk12">index</span><span class="mtk1">] ? </span><span class="mtk4">this</span><span class="mtk1">.</span><span class="mtk12">tableItems</span><span class="mtk1">[</span><span class="mtk12">index</span><span class="mtk1">].</span><span class="mtk12">validity</span><span class="mtk1"> : {},</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> }));</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> },</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> },</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1">};</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk17">&lt;/</span><span class="mtk4">script</span><span class="mtk17">&gt;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk17">&lt;</span><span class="mtk4">style</span><span class="mtk17">&gt;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk6">.action-container</span><span class="mtk1"> {</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">margin-bottom</span><span class="mtk1">: </span><span class="mtk7">10px</span><span class="mtk1">;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1">}</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk6">.action-container</span><span class="mtk1"> </span><span class="mtk6">button</span><span class="mtk1"> {</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">margin-right</span><span class="mtk1">: </span><span class="mtk7">5px</span><span class="mtk1">;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1">}</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk6">.delete-button</span><span class="mtk1"> {</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">margin-left</span><span class="mtk1">: </span><span class="mtk7">5px</span><span class="mtk1">;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1">}</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk17">&lt;/</span><span class="mtk4">style</span><span class="mtk17">&gt;</span></span></span></code></pre> <h5 id="app-component-1" style="position:relative;"><a href="#app-component-1" aria-label="app component 1 permalink" class="anchor before"><svg aria-hidden="true" focusable="false" height="16" version="1.1" viewBox="0 0 16 16" width="16"><path fill-rule="evenodd" d="M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z"></path></svg></a>App Component:</h5> <pre class="grvsc-container default-dark" data-language="html" data-index="13"><code class="grvsc-code"><span class="grvsc-line"><span class="grvsc-source"><span class="mtk17">&lt;</span><span class="mtk4">template</span><span class="mtk17">&gt;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk17">&lt;</span><span class="mtk4">div</span><span class="mtk1"> </span><span class="mtk12">id</span><span class="mtk1">=</span><span class="mtk8">&quot;app&quot;</span><span class="mtk17">&gt;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk17">&lt;</span><span class="mtk4">EditableTable</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">v-model</span><span class="mtk1">=</span><span class="mtk8">&quot;users&quot;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">:fields</span><span class="mtk1">=</span><span class="mtk8">&quot;fields&quot;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">@submit</span><span class="mtk1">=</span><span class="mtk8">&quot;handleUpdateUser($event)&quot;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">@remove</span><span class="mtk1">=</span><span class="mtk8">&quot;handleRemoveUser($event)&quot;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk17">&gt;&lt;/</span><span class="mtk4">EditableTable</span><span class="mtk17">&gt;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk17">&lt;/</span><span class="mtk4">div</span><span class="mtk17">&gt;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk17">&lt;/</span><span class="mtk4">template</span><span class="mtk17">&gt;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk17">&lt;</span><span class="mtk4">script</span><span class="mtk17">&gt;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk15">import</span><span class="mtk1"> </span><span class="mtk12">EditableTable</span><span class="mtk1"> </span><span class="mtk15">from</span><span class="mtk1"> </span><span class="mtk8">&quot;./components/EditableTable.vue&quot;</span><span class="mtk1">;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk15">import</span><span class="mtk1"> { </span><span class="mtk12">addUser</span><span class="mtk1">, </span><span class="mtk12">deleteUser</span><span class="mtk1">, </span><span class="mtk12">getUsers</span><span class="mtk1">, </span><span class="mtk12">updateUser</span><span class="mtk1"> } </span><span class="mtk15">from</span><span class="mtk1"> </span><span class="mtk8">&quot;./services/user&quot;</span><span class="mtk1">;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk15">export</span><span class="mtk1"> </span><span class="mtk15">default</span><span class="mtk1"> {</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">name:</span><span class="mtk1"> </span><span class="mtk8">&quot;App&quot;</span><span class="mtk1">,</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">components:</span><span class="mtk1"> {</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">EditableTable</span><span class="mtk1">,</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> },</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk11">data</span><span class="mtk1">() {</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk15">return</span><span class="mtk1"> {</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">fields:</span><span class="mtk1"> [</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> { </span><span class="mtk12">key:</span><span class="mtk1"> </span><span class="mtk8">&quot;selectRow&quot;</span><span class="mtk1">, </span><span class="mtk12">label:</span><span class="mtk1"> </span><span class="mtk8">&quot;&quot;</span><span class="mtk1"> },</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> { </span><span class="mtk12">key:</span><span class="mtk1"> </span><span class="mtk8">&quot;name&quot;</span><span class="mtk1">, </span><span class="mtk12">label:</span><span class="mtk1"> </span><span class="mtk8">&quot;Name&quot;</span><span class="mtk1">, </span><span class="mtk12">type:</span><span class="mtk1"> </span><span class="mtk8">&quot;text&quot;</span><span class="mtk1">, </span><span class="mtk12">required:</span><span class="mtk1"> </span><span class="mtk4">true</span><span class="mtk1"> },</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> { </span><span class="mtk12">key:</span><span class="mtk1"> </span><span class="mtk8">&quot;email&quot;</span><span class="mtk1">, </span><span class="mtk12">label:</span><span class="mtk1"> </span><span class="mtk8">&quot;Email&quot;</span><span class="mtk1">, </span><span class="mtk12">type:</span><span class="mtk1"> </span><span class="mtk8">&quot;email&quot;</span><span class="mtk1">, </span><span class="mtk12">required:</span><span class="mtk1"> </span><span class="mtk4">true</span><span class="mtk1">, </span><span class="mtk12">pattern:</span><span class="mtk1"> </span><span class="mtk8">&quot;.+@bootstrapvue</span><span class="mtk6">\\</span><span class="mtk8">.com&quot;</span><span class="mtk1"> },</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> { </span><span class="mtk12">key:</span><span class="mtk1"> </span><span class="mtk8">&quot;phone&quot;</span><span class="mtk1">, </span><span class="mtk12">label:</span><span class="mtk1"> </span><span class="mtk8">&quot;Phone&quot;</span><span class="mtk1">, </span><span class="mtk12">type:</span><span class="mtk1"> </span><span class="mtk8">&quot;text&quot;</span><span class="mtk1"> },</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> { </span><span class="mtk12">key:</span><span class="mtk1"> </span><span class="mtk8">&quot;edit&quot;</span><span class="mtk1">, </span><span class="mtk12">label:</span><span class="mtk1"> </span><span class="mtk8">&quot;&quot;</span><span class="mtk1">, </span><span class="mtk12">type:</span><span class="mtk1"> </span><span class="mtk8">&quot;edit&quot;</span><span class="mtk1"> },</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> ],</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">users:</span><span class="mtk1"> [],</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> };</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> },</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk4">async</span><span class="mtk1"> </span><span class="mtk11">mounted</span><span class="mtk1">() {</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk4">this</span><span class="mtk1">.</span><span class="mtk12">users</span><span class="mtk1"> = </span><span class="mtk15">await</span><span class="mtk1"> </span><span class="mtk11">getUsers</span><span class="mtk1">();</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> },</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">methods:</span><span class="mtk1"> {</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk4">async</span><span class="mtk1"> </span><span class="mtk11">handleUpdateUser</span><span class="mtk1">(</span><span class="mtk12">user</span><span class="mtk1">) {</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk15">if</span><span class="mtk1"> (</span><span class="mtk12">user</span><span class="mtk1">.</span><span class="mtk12">id</span><span class="mtk1">) {</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk15">await</span><span class="mtk1"> </span><span class="mtk11">updateUser</span><span class="mtk1">(</span><span class="mtk12">user</span><span class="mtk1">);</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> } </span><span class="mtk15">else</span><span class="mtk1"> {</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk15">await</span><span class="mtk1"> </span><span class="mtk11">addUser</span><span class="mtk1">(</span><span class="mtk12">user</span><span class="mtk1">);</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> }</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> },</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk4">async</span><span class="mtk1"> </span><span class="mtk11">handleRemoveUser</span><span class="mtk1">(</span><span class="mtk12">user</span><span class="mtk1">) {</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk15">if</span><span class="mtk1"> (</span><span class="mtk12">user</span><span class="mtk1">.</span><span class="mtk12">length</span><span class="mtk1"> &gt; </span><span class="mtk7">0</span><span class="mtk1">) {</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk15">await</span><span class="mtk1"> </span><span class="mtk12">user</span><span class="mtk1">.</span><span class="mtk11">map</span><span class="mtk1">(</span><span class="mtk4">async</span><span class="mtk1"> (</span><span class="mtk12">item</span><span class="mtk1">) </span><span class="mtk4">=&gt;</span><span class="mtk1"> {</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk15">await</span><span class="mtk1"> </span><span class="mtk11">deleteUser</span><span class="mtk1">(</span><span class="mtk12">item</span><span class="mtk1">.</span><span class="mtk12">id</span><span class="mtk1">); </span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> })</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> } </span><span class="mtk15">else</span><span class="mtk1"> {</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk15">await</span><span class="mtk1"> </span><span class="mtk11">deleteUser</span><span class="mtk1">(</span><span class="mtk12">user</span><span class="mtk1">.</span><span class="mtk12">id</span><span class="mtk1">);</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> }</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> }</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> },</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1">};</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk17">&lt;/</span><span class="mtk4">script</span><span class="mtk17">&gt;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk17">&lt;</span><span class="mtk4">style</span><span class="mtk17">&gt;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk6">#app</span><span class="mtk1"> {</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">margin</span><span class="mtk1">: </span><span class="mtk7">20px</span><span class="mtk1">;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1">}</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk17">&lt;/</span><span class="mtk4">style</span><span class="mtk17">&gt;</span></span></span></code></pre> <h2 id="summary" style="position:relative;"><a href="#summary" aria-label="summary permalink" class="anchor before"><svg aria-hidden="true" focusable="false" height="16" version="1.1" viewBox="0 0 16 16" width="16"><path fill-rule="evenodd" d="M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z"></path></svg></a>Summary</h2> <p>If you made it to this section, pat yourself on the back! You just learned how to:</p> <ul> <li>Update <code>EditableTable.vue</code> to support input field validation</li> <li>Leverage built-in HTML form validations for adding custom validations</li> <li>Enable the consumer to dynamically add validations</li> </ul> <p>You can access the <a href="https://github.com/muhimasri/vue-editable-table-example">complete repository here</a>.</p> <p>Bye for now 👋</p> <style class="grvsc-styles"> .grvsc-container { overflow: auto; position: relative; -webkit-overflow-scrolling: touch; padding-top: 1rem; padding-top: var(--grvsc-padding-top, var(--grvsc-padding-v, 1rem)); padding-bottom: 1rem; padding-bottom: var(--grvsc-padding-bottom, var(--grvsc-padding-v, 1rem)); border-radius: 8px; border-radius: var(--grvsc-border-radius, 8px); font-feature-settings: normal; line-height: 1.4; } .grvsc-code { display: table; } .grvsc-line { display: table-row; box-sizing: border-box; width: 100%; position: relative; } .grvsc-line > * { position: relative; } .grvsc-gutter-pad { display: table-cell; padding-left: 0.75rem; padding-left: calc(var(--grvsc-padding-left, var(--grvsc-padding-h, 1.5rem)) / 2); } .grvsc-gutter { display: table-cell; -webkit-user-select: none; -moz-user-select: none; user-select: none; } .grvsc-gutter::before { content: attr(data-content); } .grvsc-source { display: table-cell; padding-left: 1.5rem; padding-left: var(--grvsc-padding-left, var(--grvsc-padding-h, 1.5rem)); padding-right: 1.5rem; padding-right: var(--grvsc-padding-right, var(--grvsc-padding-h, 1.5rem)); } .grvsc-source:empty::after { content: ' '; -webkit-user-select: none; -moz-user-select: none; user-select: none; } .grvsc-gutter + .grvsc-source { padding-left: 0.75rem; padding-left: calc(var(--grvsc-padding-left, var(--grvsc-padding-h, 1.5rem)) / 2); } /* Line transformer styles */ .grvsc-has-line-highlighting > .grvsc-code > .grvsc-line::before { content: ' '; position: absolute; width: 100%; } .grvsc-line-diff-add::before { background-color: var(--grvsc-line-diff-add-background-color, rgba(0, 255, 60, 0.2)); } .grvsc-line-diff-del::before { background-color: var(--grvsc-line-diff-del-background-color, rgba(255, 0, 20, 0.2)); } .grvsc-line-number { padding: 0 2px; text-align: right; opacity: 0.7; } .default-dark { background-color: #1E1E1E; color: #D4D4D4; } .default-dark .mtk17 { color: #808080; } .default-dark .mtk4 { color: #569CD6; } .default-dark .mtk1 { color: #D4D4D4; } .default-dark .mtk12 { color: #9CDCFE; } .default-dark .mtk8 { color: #CE9178; } .default-dark .mtk15 { color: #C586C0; } .default-dark .mtk10 { color: #4EC9B0; } .default-dark .mtk11 { color: #DCDCAA; } .default-dark .mtk6 { color: #D7BA7D; } .default-dark .mtk7 { color: #B5CEA8; } .default-dark .mtk3 { color: #6A9955; } .default-dark .grvsc-line-highlighted::before { background-color: var(--grvsc-line-highlighted-background-color, rgba(255, 255, 255, 0.1)); box-shadow: inset var(--grvsc-line-highlighted-border-width, 4px) 0 0 0 var(--grvsc-line-highlighted-border-color, rgba(255, 255, 255, 0.5)); } </style><![CDATA[How to Create an Icon Text Field Component with Material UI]]>https://muhimasri.comhow-to-create-an-icon-text-field-component-with-material-uihttps://muhimasri.comhow-to-create-an-icon-text-field-component-with-material-ui<p><a href="https://mui.com/components/text-fields/">MUI</a> provides an easy way to add icons to a <code>TextField</code> component:</p> <pre class="grvsc-container default-dark" data-language="jsx" data-index="0"><code class="grvsc-code"><span class="grvsc-line"><span class="grvsc-source"><span class="mtk15">import</span><span class="mtk1"> </span><span class="mtk12">InputAdornment</span><span class="mtk1"> </span><span class="mtk15">from</span><span class="mtk1"> </span><span class="mtk8">&#39;@mui/material/InputAdornment&#39;</span><span class="mtk1">;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk15">import</span><span class="mtk1"> </span><span class="mtk12">TextField</span><span class="mtk1"> </span><span class="mtk15">from</span><span class="mtk1"> </span><span class="mtk8">&#39;@mui/material/TextField&#39;</span><span class="mtk1">;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk15">import</span><span class="mtk1"> </span><span class="mtk12">AttachMoneyIcon</span><span class="mtk1"> </span><span class="mtk15">from</span><span class="mtk1"> </span><span class="mtk8">&#39;@mui/icons-material/AttachMoney&#39;</span><span class="mtk1">;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk15">export</span><span class="mtk1"> </span><span class="mtk15">default</span><span class="mtk1"> </span><span class="mtk4">function</span><span class="mtk1"> </span><span class="mtk11">InputIcon</span><span class="mtk1">() {</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk15">return</span><span class="mtk1"> (</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk17">&lt;</span><span class="mtk10">TextField</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">id</span><span class="mtk1">=</span><span class="mtk8">&quot;input-with-icon-textfield&quot;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">label</span><span class="mtk1">=</span><span class="mtk8">&quot;TextField&quot;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">InputProps</span><span class="mtk1">=</span><span class="mtk4">{</span><span class="mtk1">{</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk11">startAdornment</span><span class="mtk12">:</span><span class="mtk1"> (</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk17">&lt;</span><span class="mtk10">InputAdornment</span><span class="mtk1"> </span><span class="mtk12">position</span><span class="mtk1">=</span><span class="mtk8">&quot;start&quot;</span><span class="mtk17">&gt;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk17">&lt;</span><span class="mtk10">AttachMoneyIcon</span><span class="mtk1"> </span><span class="mtk17">/&gt;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk17">&lt;/</span><span class="mtk10">InputAdornment</span><span class="mtk17">&gt;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> ),</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> }</span><span class="mtk4">}</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">variant</span><span class="mtk1">=</span><span class="mtk8">&quot;standard&quot;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk17">/&gt;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> );</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1">}</span></span></span></code></pre> <p><code>TextField</code> component internally encapsulates <code>FormControl</code>, <code>InputLabel</code>, and <code>Input</code> elements together. That’s why it provides <code>InputProps</code> to pass in other required properties to the <code>Input</code> component. In the above example, we added an icon at the beginning of the <code>TextField</code>.</p> <p>Although this seems like a simple code to write, it will become redundant as we keep doing it in many places in our project. So it’s much nicer if we can do something like:</p> <pre class="grvsc-container default-dark" data-language="jsx" data-index="1"><code class="grvsc-code"><span class="grvsc-line"><span class="grvsc-source"><span class="mtk17">&lt;</span><span class="mtk10">IconTextField</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">label</span><span class="mtk1">=</span><span class="mtk8">&quot;TextField&quot;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">variant</span><span class="mtk1">=</span><span class="mtk8">&quot;standard&quot;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">iconStart</span><span class="mtk1">=</span><span class="mtk4">{</span><span class="mtk17">&lt;</span><span class="mtk10">AccountCircle</span><span class="mtk1"> </span><span class="mtk17">/&gt;</span><span class="mtk4">}</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk17">/&gt;</span><span class="mtk1">;</span></span></span></code></pre> <p>In this tutorial, we will go through a simple guided solution to creating a re-usable <code>IconTextField</code> component. If you’d like to skip all the details, below is the final working code on <a href="https://codesandbox.io/s/mui-input-icons-02ylt?file=/src/App.js:331-482">CodeSandbox</a>:</p> <div data-codesandbox="mui-input-icons-02ylt"> <button>Run Code</button> </div> <h2 id="install-mui" style="position:relative;"><a href="#install-mui" aria-label="install mui permalink" class="anchor before"><svg aria-hidden="true" focusable="false" height="16" version="1.1" viewBox="0 0 16 16" width="16"><path fill-rule="evenodd" d="M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z"></path></svg></a>Install MUI</h2> <pre class="grvsc-container default-dark" data-language="" data-index="2"><code class="grvsc-code"><span class="grvsc-line"><span class="grvsc-source">npm install @mui/material @emotion/react @emotion/styled</span></span></code></pre> <p><a href="https://emotion.sh/docs/introduction">Emotion</a> library is required to create React components that have styles attached to them.</p> <h2 id="create-a-new-component" style="position:relative;"><a href="#create-a-new-component" aria-label="create a new component permalink" class="anchor before"><svg aria-hidden="true" focusable="false" height="16" version="1.1" viewBox="0 0 16 16" width="16"><path fill-rule="evenodd" d="M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z"></path></svg></a>Create a new component</h2> <p>Let’s create a new <code>IconTextField</code> component that inherits all props from <code>TextField</code>:</p> <pre class="grvsc-container default-dark" data-language="jsx" data-index="3"><code class="grvsc-code"><span class="grvsc-line"><span class="grvsc-source"><span class="mtk15">import</span><span class="mtk1"> </span><span class="mtk12">TextField</span><span class="mtk1"> </span><span class="mtk15">from</span><span class="mtk1"> </span><span class="mtk8">&quot;@mui/material/TextField&quot;</span><span class="mtk1">;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk4">const</span><span class="mtk1"> </span><span class="mtk11">IconTextField</span><span class="mtk1"> = (</span><span class="mtk12">props</span><span class="mtk1">) </span><span class="mtk4">=&gt;</span><span class="mtk1"> {</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk15">return</span><span class="mtk1"> </span><span class="mtk17">&lt;</span><span class="mtk10">TextField</span><span class="mtk1"> </span><span class="mtk4">{</span><span class="mtk1">...</span><span class="mtk12">props</span><span class="mtk4">}</span><span class="mtk1"> </span><span class="mtk17">/&gt;</span><span class="mtk1">;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1">};</span></span></span></code></pre> <p>That way, when consuming it, we can use any feature that MUI provides:</p> <pre class="grvsc-container grvsc-has-line-highlighting default-dark" data-language="jsx" data-index="4"><code class="grvsc-code"><span class="grvsc-line"><span class="grvsc-source"><span class="mtk15">import</span><span class="mtk1"> </span><span class="mtk12">TextField</span><span class="mtk1"> </span><span class="mtk15">from</span><span class="mtk1"> </span><span class="mtk8">&quot;@mui/material/TextField&quot;</span><span class="mtk1">;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk15">export</span><span class="mtk1"> </span><span class="mtk15">default</span><span class="mtk1"> </span><span class="mtk4">function</span><span class="mtk1"> </span><span class="mtk11">App</span><span class="mtk1">() {</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk15">return</span><span class="mtk1"> (</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk17">&lt;</span><span class="mtk4">div</span><span class="mtk1"> </span><span class="mtk12">className</span><span class="mtk1">=</span><span class="mtk8">&quot;App&quot;</span><span class="mtk17">&gt;</span></span></span> <span class="grvsc-line grvsc-line-highlighted"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk17">&lt;</span><span class="mtk10">IconTextField</span><span class="mtk1"> </span><span class="mtk12">label</span><span class="mtk1">=</span><span class="mtk8">&quot;TextField&quot;</span><span class="mtk1"> </span><span class="mtk12">variant</span><span class="mtk1">=</span><span class="mtk8">&quot;standard&quot;</span><span class="mtk1"> </span><span class="mtk17">/&gt;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk17">&lt;/</span><span class="mtk4">div</span><span class="mtk17">&gt;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> );</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1">}</span></span></span> <span class="grvsc-line"><span class="grvsc-source"></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk4">const</span><span class="mtk1"> </span><span class="mtk11">IconTextField</span><span class="mtk1"> = (</span><span class="mtk12">props</span><span class="mtk1">) </span><span class="mtk4">=&gt;</span><span class="mtk1"> {</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk15">return</span><span class="mtk1"> </span><span class="mtk17">&lt;</span><span class="mtk10">TextField</span><span class="mtk1"> </span><span class="mtk4">{</span><span class="mtk1">...</span><span class="mtk12">props</span><span class="mtk4">}</span><span class="mtk1"> </span><span class="mtk17">/&gt;</span><span class="mtk1">;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1">};</span></span></span></code></pre> <h2 id="add-icons" style="position:relative;"><a href="#add-icons" aria-label="add icons permalink" class="anchor before"><svg aria-hidden="true" focusable="false" height="16" version="1.1" viewBox="0 0 16 16" width="16"><path fill-rule="evenodd" d="M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z"></path></svg></a>Add icons</h2> <p>The goal here is to avoid having to write the code below every time we need to use icons:</p> <pre class="grvsc-container default-dark" data-language="jsx" data-index="5"><code class="grvsc-code"><span class="grvsc-line"><span class="grvsc-source"><span class="mtk12">InputProps</span><span class="mtk1">={{</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk11">startAdornment</span><span class="mtk12">:</span><span class="mtk1"> (</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk17">&lt;</span><span class="mtk10">InputAdornment</span><span class="mtk1"> </span><span class="mtk12">position</span><span class="mtk1">=</span><span class="mtk8">&quot;start&quot;</span><span class="mtk17">&gt;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk17">&lt;</span><span class="mtk10">AttachMoneyIcon</span><span class="mtk1"> </span><span class="mtk17">/&gt;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk17">&lt;/</span><span class="mtk10">InputAdornment</span><span class="mtk17">&gt;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> ),</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk11">endAdornment</span><span class="mtk12">:</span><span class="mtk1"> (</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk17">&lt;</span><span class="mtk10">InputAdornment</span><span class="mtk1"> </span><span class="mtk12">position</span><span class="mtk1">=</span><span class="mtk8">&quot;end&quot;</span><span class="mtk17">&gt;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk17">&lt;</span><span class="mtk10">QuestionMark</span><span class="mtk1"> </span><span class="mtk17">/&gt;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk17">&lt;/</span><span class="mtk10">InputAdornment</span><span class="mtk17">&gt;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> ),</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1">}}</span></span></span></code></pre> <p>Let’s add two new props - <code>startIcon</code> and <code>endIcon</code>; each will accept any element as a value. Then, in <code>InputProp</code>, we can dynamically add and remove <code>InputAdorment</code> based on the icon value:</p> <pre class="grvsc-container grvsc-has-line-highlighting default-dark" data-language="jsx" data-index="6"><code class="grvsc-code"><span class="grvsc-line"><span class="grvsc-source"><span class="mtk4">const</span><span class="mtk1"> </span><span class="mtk11">IconTextField</span><span class="mtk1"> = ({ </span><span class="mtk12">iconStart</span><span class="mtk1">, </span><span class="mtk12">iconEnd</span><span class="mtk1">, ...</span><span class="mtk12">props</span><span class="mtk1"> }) </span><span class="mtk4">=&gt;</span><span class="mtk1"> {</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk15">return</span><span class="mtk1"> (</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk17">&lt;</span><span class="mtk10">TextField</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk4">{</span><span class="mtk1">...</span><span class="mtk12">props</span><span class="mtk4">}</span></span></span> <span class="grvsc-line grvsc-line-highlighted"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">InputProps</span><span class="mtk1">=</span><span class="mtk4">{</span><span class="mtk1">{</span></span></span> <span class="grvsc-line grvsc-line-highlighted"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">startAdornment:</span><span class="mtk1"> </span><span class="mtk12">iconStart</span><span class="mtk1"> ? (</span></span></span> <span class="grvsc-line grvsc-line-highlighted"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk17">&lt;</span><span class="mtk10">InputAdornment</span><span class="mtk1"> </span><span class="mtk12">position</span><span class="mtk1">=</span><span class="mtk8">&quot;start&quot;</span><span class="mtk17">&gt;</span><span class="mtk4">{</span><span class="mtk12">iconStart</span><span class="mtk4">}</span><span class="mtk17">&lt;/</span><span class="mtk10">InputAdornment</span><span class="mtk17">&gt;</span></span></span> <span class="grvsc-line grvsc-line-highlighted"><span class="grvsc-source"><span class="mtk1"> ) : </span><span class="mtk4">null</span><span class="mtk1">,</span></span></span> <span class="grvsc-line grvsc-line-highlighted"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">endAdornment:</span><span class="mtk1"> </span><span class="mtk12">iconEnd</span><span class="mtk1"> ? (</span></span></span> <span class="grvsc-line grvsc-line-highlighted"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk17">&lt;</span><span class="mtk10">InputAdornment</span><span class="mtk1"> </span><span class="mtk12">position</span><span class="mtk1">=</span><span class="mtk8">&quot;end&quot;</span><span class="mtk17">&gt;</span><span class="mtk4">{</span><span class="mtk12">iconEnd</span><span class="mtk4">}</span><span class="mtk17">&lt;/</span><span class="mtk10">InputAdornment</span><span class="mtk17">&gt;</span></span></span> <span class="grvsc-line grvsc-line-highlighted"><span class="grvsc-source"><span class="mtk1"> ) : </span><span class="mtk4">null</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> }</span><span class="mtk4">}</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk17">/&gt;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> );</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1">};</span></span></span></code></pre> <p>Now when consuming it, the code will be shorter and simpler to write:</p> <pre class="grvsc-container default-dark" data-language="jsx" data-index="7"><code class="grvsc-code"><span class="grvsc-line"><span class="grvsc-source"><span class="mtk17">&lt;</span><span class="mtk10">IconTextField</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">label</span><span class="mtk1">=</span><span class="mtk8">&quot;TextField&quot;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">iconStart</span><span class="mtk1">=</span><span class="mtk4">{</span><span class="mtk17">&lt;</span><span class="mtk10">AttachMoneyIcon</span><span class="mtk1"> </span><span class="mtk17">/&gt;</span><span class="mtk4">}</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">iconEnd</span><span class="mtk1">=</span><span class="mtk4">{</span><span class="mtk17">&lt;</span><span class="mtk10">QuestionMark</span><span class="mtk1"> </span><span class="mtk17">/&gt;</span><span class="mtk4">}</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk17">/&gt;</span><span class="mtk1">;</span></span></span></code></pre> <p>One last addition, if we want to enable all other <code>Input</code> props, we need to pass it down explicitly:</p> <pre class="grvsc-container grvsc-has-line-highlighting default-dark" data-language="jsx" data-index="8"><code class="grvsc-code"><span class="grvsc-line"><span class="grvsc-source"><span class="mtk4">const</span><span class="mtk1"> </span><span class="mtk11">IconTextField</span><span class="mtk1"> = ({ </span><span class="mtk12">iconStart</span><span class="mtk1">, </span><span class="mtk12">iconEnd</span><span class="mtk1">, </span><span class="mtk12">InputProps</span><span class="mtk1">, ...</span><span class="mtk12">props</span><span class="mtk1"> }) </span><span class="mtk4">=&gt;</span><span class="mtk1"> {</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk15">return</span><span class="mtk1"> (</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk17">&lt;</span><span class="mtk10">TextField</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk4">{</span><span class="mtk1">...</span><span class="mtk12">props</span><span class="mtk4">}</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">InputProps</span><span class="mtk1">=</span><span class="mtk4">{</span><span class="mtk1">{</span></span></span> <span class="grvsc-line grvsc-line-highlighted"><span class="grvsc-source"><span class="mtk1"> ...</span><span class="mtk12">InputProps</span><span class="mtk1">,</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">startAdornment:</span><span class="mtk1"> </span><span class="mtk12">iconStart</span><span class="mtk1"> ? (</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk17">&lt;</span><span class="mtk10">InputAdornment</span><span class="mtk1"> </span><span class="mtk12">position</span><span class="mtk1">=</span><span class="mtk8">&quot;start&quot;</span><span class="mtk17">&gt;</span><span class="mtk4">{</span><span class="mtk12">iconStart</span><span class="mtk4">}</span><span class="mtk17">&lt;/</span><span class="mtk10">InputAdornment</span><span class="mtk17">&gt;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> ) : </span><span class="mtk4">null</span><span class="mtk1">,</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">endAdornment:</span><span class="mtk1"> </span><span class="mtk12">iconEnd</span><span class="mtk1"> ? (</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk17">&lt;</span><span class="mtk10">InputAdornment</span><span class="mtk1"> </span><span class="mtk12">position</span><span class="mtk1">=</span><span class="mtk8">&quot;end&quot;</span><span class="mtk17">&gt;</span><span class="mtk4">{</span><span class="mtk12">iconEnd</span><span class="mtk4">}</span><span class="mtk17">&lt;/</span><span class="mtk10">InputAdornment</span><span class="mtk17">&gt;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> ) : </span><span class="mtk4">null</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> }</span><span class="mtk4">}</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk17">/&gt;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> );</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1">};</span></span></span></code></pre> <h2 id="style-icons" style="position:relative;"><a href="#style-icons" aria-label="style icons permalink" class="anchor before"><svg aria-hidden="true" focusable="false" height="16" version="1.1" viewBox="0 0 16 16" width="16"><path fill-rule="evenodd" d="M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z"></path></svg></a>Style Icons</h2> <p>We can style an icon by using <code>sx</code> prop directly in the component:</p> <pre class="grvsc-container default-dark" data-language="jsx" data-index="9"><code class="grvsc-code"><span class="grvsc-line"><span class="grvsc-source"><span class="mtk17">&lt;</span><span class="mtk10">IconTextField</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">label</span><span class="mtk1">=</span><span class="mtk8">&quot;TextField&quot;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">iconStart</span><span class="mtk1">=</span><span class="mtk4">{</span><span class="mtk17">&lt;</span><span class="mtk10">AttachMoneyIcon</span><span class="mtk1"> </span><span class="mtk12">sx</span><span class="mtk1">=</span><span class="mtk4">{</span><span class="mtk1">{ </span><span class="mtk12">color:</span><span class="mtk1"> </span><span class="mtk8">&quot;green&quot;</span><span class="mtk1">, </span><span class="mtk12">fontSize:</span><span class="mtk1"> </span><span class="mtk7">20</span><span class="mtk1"> }</span><span class="mtk4">}</span><span class="mtk1"> </span><span class="mtk17">/&gt;</span><span class="mtk4">}</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">iconEnd</span><span class="mtk1">=</span><span class="mtk4">{</span><span class="mtk17">&lt;</span><span class="mtk10">QuestionMark</span><span class="mtk1"> </span><span class="mtk12">sx</span><span class="mtk1">=</span><span class="mtk4">{</span><span class="mtk1">{ </span><span class="mtk12">color:</span><span class="mtk1"> </span><span class="mtk8">&quot;#0089ff&quot;</span><span class="mtk1">, </span><span class="mtk12">fontSize:</span><span class="mtk1"> </span><span class="mtk7">20</span><span class="mtk1"> }</span><span class="mtk4">}</span><span class="mtk1"> </span><span class="mtk17">/&gt;</span><span class="mtk4">}</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk17">/&gt;</span><span class="mtk1">;</span></span></span></code></pre> <h2 id="take-away" style="position:relative;"><a href="#take-away" aria-label="take away permalink" class="anchor before"><svg aria-hidden="true" focusable="false" height="16" version="1.1" viewBox="0 0 16 16" width="16"><path fill-rule="evenodd" d="M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z"></path></svg></a>Take away</h2> <p>Although MUI provides us with excellent features encapsulated with easy-to-use components, we can still further refine and customize elements to make development more productive and fun!</p> <p>Bye for now 👋</p> <style class="grvsc-styles"> .grvsc-container { overflow: auto; position: relative; -webkit-overflow-scrolling: touch; padding-top: 1rem; padding-top: var(--grvsc-padding-top, var(--grvsc-padding-v, 1rem)); padding-bottom: 1rem; padding-bottom: var(--grvsc-padding-bottom, var(--grvsc-padding-v, 1rem)); border-radius: 8px; border-radius: var(--grvsc-border-radius, 8px); font-feature-settings: normal; line-height: 1.4; } .grvsc-code { display: table; } .grvsc-line { display: table-row; box-sizing: border-box; width: 100%; position: relative; } .grvsc-line > * { position: relative; } .grvsc-gutter-pad { display: table-cell; padding-left: 0.75rem; padding-left: calc(var(--grvsc-padding-left, var(--grvsc-padding-h, 1.5rem)) / 2); } .grvsc-gutter { display: table-cell; -webkit-user-select: none; -moz-user-select: none; user-select: none; } .grvsc-gutter::before { content: attr(data-content); } .grvsc-source { display: table-cell; padding-left: 1.5rem; padding-left: var(--grvsc-padding-left, var(--grvsc-padding-h, 1.5rem)); padding-right: 1.5rem; padding-right: var(--grvsc-padding-right, var(--grvsc-padding-h, 1.5rem)); } .grvsc-source:empty::after { content: ' '; -webkit-user-select: none; -moz-user-select: none; user-select: none; } .grvsc-gutter + .grvsc-source { padding-left: 0.75rem; padding-left: calc(var(--grvsc-padding-left, var(--grvsc-padding-h, 1.5rem)) / 2); } /* Line transformer styles */ .grvsc-has-line-highlighting > .grvsc-code > .grvsc-line::before { content: ' '; position: absolute; width: 100%; } .grvsc-line-diff-add::before { background-color: var(--grvsc-line-diff-add-background-color, rgba(0, 255, 60, 0.2)); } .grvsc-line-diff-del::before { background-color: var(--grvsc-line-diff-del-background-color, rgba(255, 0, 20, 0.2)); } .grvsc-line-number { padding: 0 2px; text-align: right; opacity: 0.7; } .default-dark { background-color: #1E1E1E; color: #D4D4D4; } .default-dark .mtk15 { color: #C586C0; } .default-dark .mtk1 { color: #D4D4D4; } .default-dark .mtk12 { color: #9CDCFE; } .default-dark .mtk8 { color: #CE9178; } .default-dark .mtk4 { color: #569CD6; } .default-dark .mtk11 { color: #DCDCAA; } .default-dark .mtk17 { color: #808080; } .default-dark .mtk10 { color: #4EC9B0; } .default-dark .mtk7 { color: #B5CEA8; } .default-dark .grvsc-line-highlighted::before { background-color: var(--grvsc-line-highlighted-background-color, rgba(255, 255, 255, 0.1)); box-shadow: inset var(--grvsc-line-highlighted-border-width, 4px) 0 0 0 var(--grvsc-line-highlighted-border-color, rgba(255, 255, 255, 0.5)); } </style><![CDATA[How to Create Circular, Linear, and Skeleton Loading with Material UI]]>https://muhimasri.comhow-to-create-circular-linear-and-skeleton-loading-with-material-uihttps://muhimasri.comhow-to-create-circular-linear-and-skeleton-loading-with-material-ui<p>In this article, we’re going to learn and apply some useful loading techniques using <a href="https://mui.com/getting-started/usage/">Material UI</a> and React components.</p> <p>If you’d like to jump right into the code without a step-by-step guide, below is the final interactive demo on <a href="https://codesandbox.io/s/material-ui-loading-f8uv9?file=/src/App.js">CodeSandbox</a>. Clicking on each button will trigger a different loading style:</p> <div data-codesandbox="material-ui-loading-f8uv9"> <button>Run Code</button> </div> <h2 id="install-mui" style="position:relative;"><a href="#install-mui" aria-label="install mui permalink" class="anchor before"><svg aria-hidden="true" focusable="false" height="16" version="1.1" viewBox="0 0 16 16" width="16"><path fill-rule="evenodd" d="M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z"></path></svg></a>Install MUI</h2> <pre class="grvsc-container default-dark" data-language="" data-index="0"><code class="grvsc-code"><span class="grvsc-line"><span class="grvsc-source">npm install @mui/material @emotion/react @emotion/styled</span></span></code></pre> <p><a href="https://emotion.sh/docs/introduction">Emotion</a> library is required if you prefer creating React components that have styles attached to them.</p> <h2 id="add-page-content" style="position:relative;"><a href="#add-page-content" aria-label="add page content permalink" class="anchor before"><svg aria-hidden="true" focusable="false" height="16" version="1.1" viewBox="0 0 16 16" width="16"><path fill-rule="evenodd" d="M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z"></path></svg></a>Add Page Content</h2> <p>Let’s start with adding some content to make the loading feel and behave like a real-world app.</p> <p>We’ll create a <code>Content</code> component that displays a title with three cards. The data is coming from a static JSON object at the beginning of the code:</p> <pre class="grvsc-container default-dark" data-language="jsx" data-index="1"><code class="grvsc-code"><span class="grvsc-line"><span class="grvsc-source"><span class="mtk15">import</span><span class="mtk1"> </span><span class="mtk8">&quot;./styles.css&quot;</span><span class="mtk1">;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk15">import</span><span class="mtk1"> </span><span class="mtk12">Grid</span><span class="mtk1"> </span><span class="mtk15">from</span><span class="mtk1"> </span><span class="mtk8">&quot;@mui/material/Grid&quot;</span><span class="mtk1">;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk15">import</span><span class="mtk1"> </span><span class="mtk12">Box</span><span class="mtk1"> </span><span class="mtk15">from</span><span class="mtk1"> </span><span class="mtk8">&quot;@mui/material/Box&quot;</span><span class="mtk1">;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk15">import</span><span class="mtk1"> </span><span class="mtk12">Typography</span><span class="mtk1"> </span><span class="mtk15">from</span><span class="mtk1"> </span><span class="mtk8">&quot;@mui/material/Typography&quot;</span><span class="mtk1">;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk4">const</span><span class="mtk1"> </span><span class="mtk12">data</span><span class="mtk1"> = [</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> {</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">src:</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk8">&quot;https://i.ytimg.com/vi/pLqipJNItIo/hqdefault.jpg?sqp=-oaymwEYCNIBEHZIVfKriqkDCwgBFQAAiEIYAXAB&amp;rs=AOn4CLBkklsyaw9FxDmMKapyBYCn9tbPNQ&quot;</span><span class="mtk1">,</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">title:</span><span class="mtk1"> </span><span class="mtk8">&quot;Don Diablo @ Tomorrowland&quot;</span><span class="mtk1">,</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">channel:</span><span class="mtk1"> </span><span class="mtk8">&quot;Don Diablo&quot;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> },</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> {</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">src:</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk8">&quot;https://i.ytimg.com/vi/_Uu12zY01ts/hqdefault.jpg?sqp=-oaymwEZCPYBEIoBSFXyq4qpAwsIARUAAIhCGAFwAQ==&amp;rs=AOn4CLCpX6Jan2rxrCAZxJYDXppTP4MoQA&quot;</span><span class="mtk1">,</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">title:</span><span class="mtk1"> </span><span class="mtk8">&quot;Queen - Greatest Hits&quot;</span><span class="mtk1">,</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">channel:</span><span class="mtk1"> </span><span class="mtk8">&quot;Queen Official&quot;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> },</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> {</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">src:</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk8">&quot;https://i.ytimg.com/vi/kkLk2XWMBf8/hqdefault.jpg?sqp=-oaymwEYCNIBEHZIVfKriqkDCwgBFQAAiEIYAXAB&amp;rs=AOn4CLB4GZTFu1Ju2EPPPXnhMZtFVvYBaw&quot;</span><span class="mtk1">,</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">title:</span><span class="mtk1"> </span><span class="mtk8">&quot;Promises (Official Video)&quot;</span><span class="mtk1">,</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">channel:</span><span class="mtk1"> </span><span class="mtk8">&quot;Calvin Harris&quot;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> }</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1">];</span></span></span> <span class="grvsc-line"><span class="grvsc-source"></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk15">export</span><span class="mtk1"> </span><span class="mtk15">default</span><span class="mtk1"> </span><span class="mtk4">function</span><span class="mtk1"> </span><span class="mtk11">App</span><span class="mtk1">() {</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk15">return</span><span class="mtk1"> (</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk17">&lt;</span><span class="mtk10">Box</span><span class="mtk17">&gt;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk17">&lt;</span><span class="mtk10">Content</span><span class="mtk1"> </span><span class="mtk17">/&gt;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk17">&lt;/</span><span class="mtk10">Box</span><span class="mtk17">&gt;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> );</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1">}</span></span></span> <span class="grvsc-line"><span class="grvsc-source"></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk4">const</span><span class="mtk1"> </span><span class="mtk11">Content</span><span class="mtk1"> = () </span><span class="mtk4">=&gt;</span><span class="mtk1"> (</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk17">&lt;</span><span class="mtk10">Box</span><span class="mtk1"> </span><span class="mtk12">sx</span><span class="mtk1">=</span><span class="mtk4">{</span><span class="mtk1">{ </span><span class="mtk12">p:</span><span class="mtk1"> </span><span class="mtk7">1</span><span class="mtk1"> }</span><span class="mtk4">}</span><span class="mtk17">&gt;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk17">&lt;</span><span class="mtk10">Typography</span><span class="mtk1"> </span><span class="mtk12">variant</span><span class="mtk1">=</span><span class="mtk8">&quot;h4&quot;</span><span class="mtk17">&gt;</span><span class="mtk1">Loading Techniques</span><span class="mtk17">&lt;/</span><span class="mtk10">Typography</span><span class="mtk17">&gt;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk17">&lt;</span><span class="mtk10">Grid</span><span class="mtk1"> </span><span class="mtk12">container</span><span class="mtk1"> </span><span class="mtk12">wrap</span><span class="mtk1">=</span><span class="mtk8">&quot;nowrap&quot;</span><span class="mtk17">&gt;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk4">{</span><span class="mtk12">data</span><span class="mtk1">.</span><span class="mtk11">map</span><span class="mtk1">((</span><span class="mtk12">item</span><span class="mtk1">, </span><span class="mtk12">index</span><span class="mtk1">) </span><span class="mtk4">=&gt;</span><span class="mtk1"> (</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk17">&lt;</span><span class="mtk10">Box</span><span class="mtk1"> </span><span class="mtk12">key</span><span class="mtk1">=</span><span class="mtk4">{</span><span class="mtk12">index</span><span class="mtk4">}</span><span class="mtk1"> </span><span class="mtk12">sx</span><span class="mtk1">=</span><span class="mtk4">{</span><span class="mtk1">{ </span><span class="mtk12">width:</span><span class="mtk1"> </span><span class="mtk7">210</span><span class="mtk1">, </span><span class="mtk12">marginRight:</span><span class="mtk1"> </span><span class="mtk7">1</span><span class="mtk1">, </span><span class="mtk12">my:</span><span class="mtk1"> </span><span class="mtk7">2</span><span class="mtk1"> }</span><span class="mtk4">}</span><span class="mtk17">&gt;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk17">&lt;</span><span class="mtk4">img</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">style</span><span class="mtk1">=</span><span class="mtk4">{</span><span class="mtk1">{ </span><span class="mtk12">width:</span><span class="mtk1"> </span><span class="mtk7">210</span><span class="mtk1">, </span><span class="mtk12">height:</span><span class="mtk1"> </span><span class="mtk7">118</span><span class="mtk1"> }</span><span class="mtk4">}</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">alt</span><span class="mtk1">=</span><span class="mtk4">{</span><span class="mtk12">item</span><span class="mtk1">.</span><span class="mtk12">title</span><span class="mtk4">}</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">src</span><span class="mtk1">=</span><span class="mtk4">{</span><span class="mtk12">item</span><span class="mtk1">.</span><span class="mtk12">src</span><span class="mtk4">}</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk17">/&gt;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk17">&lt;</span><span class="mtk10">Box</span><span class="mtk1"> </span><span class="mtk12">sx</span><span class="mtk1">=</span><span class="mtk4">{</span><span class="mtk1">{ </span><span class="mtk12">pr:</span><span class="mtk1"> </span><span class="mtk7">2</span><span class="mtk1"> }</span><span class="mtk4">}</span><span class="mtk17">&gt;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk17">&lt;</span><span class="mtk10">Typography</span><span class="mtk1"> </span><span class="mtk12">gutterBottom</span><span class="mtk1"> </span><span class="mtk12">variant</span><span class="mtk1">=</span><span class="mtk8">&quot;body2&quot;</span><span class="mtk17">&gt;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk4">{</span><span class="mtk12">item</span><span class="mtk1">.</span><span class="mtk12">title</span><span class="mtk4">}</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk17">&lt;/</span><span class="mtk10">Typography</span><span class="mtk17">&gt;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk17">&lt;</span><span class="mtk10">Typography</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">display</span><span class="mtk1">=</span><span class="mtk8">&quot;block&quot;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">variant</span><span class="mtk1">=</span><span class="mtk8">&quot;caption&quot;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">color</span><span class="mtk1">=</span><span class="mtk8">&quot;text.secondary&quot;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk17">&gt;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk4">{</span><span class="mtk12">item</span><span class="mtk1">.</span><span class="mtk12">channel</span><span class="mtk4">}</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk17">&lt;/</span><span class="mtk10">Typography</span><span class="mtk17">&gt;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk17">&lt;/</span><span class="mtk10">Box</span><span class="mtk17">&gt;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk17">&lt;/</span><span class="mtk10">Box</span><span class="mtk17">&gt;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> ))</span><span class="mtk4">}</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk17">&lt;/</span><span class="mtk10">Grid</span><span class="mtk17">&gt;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk17">&lt;/</span><span class="mtk10">Box</span><span class="mtk17">&gt;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1">);</span></span></span></code></pre> <p><span class="gatsby-resp-image-wrapper" style="position: relative; display: block; margin-left: auto; margin-right: auto; max-width: 720px; " > <a class="gatsby-resp-image-link" href="/static/93482f25f547bff9eae67251047af6cc/b2982/image.png" style="display: block" target="_blank" rel="noopener" > <span class="gatsby-resp-image-background-image" style="padding-bottom: 35%; position: relative; bottom: 0; left: 0; background-image: url('data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABQAAAAHCAIAAACHqfpvAAAACXBIWXMAAAsTAAALEwEAmpwYAAABeElEQVR42mN49vzZ1cuXHz+4/+De3WuXLz26d/fv37//iQMMHz5+fPb27aNPXx98+X7z5ft7775evHTx2PFj5y9cOHP61NGjR86ePfPx0/cnT988ffrm85dfjx+9fP/+K1TzzecvN128s2Tz0dlT15Rvu5E9c4eVrS0/L6exnrqGnBQHG7OqqvLx4/cmNs5bMmn1zePPeor7Dm06B9VcWzqjMKa0y0o/ycAxOKImwi/PysoKqNnSQF1XRU6Yj1NNW3ND+5pm85SF6ZM2bdvSuapuza7Nf36CNc+vnlrqlR6mrR1poNfpVdAemR3g76GhpWVpY2NlomeooWLlaLeoZEq3S1WrXX77isqpx5sWHJ/669dvkOanz5/dunv70eNHd+7cvffgyetXrx89AvIe3b9//8GDB2/evPnw4cPzF88fP3r66MHjJ88ev/v49uef7//+/wNp/v3r188fP5CC8N+v379//Pjx588fuNBvoMjPn3///UMLbQBjPDXcyamwawAAAABJRU5ErkJggg=='); background-size: cover; display: block;" ></span> <img class="gatsby-resp-image-image" alt="Page Content" title="" src="/static/93482f25f547bff9eae67251047af6cc/37523/image.png" srcset="/static/93482f25f547bff9eae67251047af6cc/e9ff0/image.png 180w, /static/93482f25f547bff9eae67251047af6cc/f21e7/image.png 360w, /static/93482f25f547bff9eae67251047af6cc/37523/image.png 720w, /static/93482f25f547bff9eae67251047af6cc/b2982/image.png 729w" sizes="(max-width: 720px) 100vw, 720px" style="width:100%;height:100%;margin:0;vertical-align:middle;position:absolute;top:0;left:0;" loading="lazy" decoding="async" /> </a> </span></p> <h2 id="button-circular-loading" style="position:relative;"><a href="#button-circular-loading" aria-label="button circular loading permalink" class="anchor before"><svg aria-hidden="true" focusable="false" height="16" version="1.1" viewBox="0 0 16 16" width="16"><path fill-rule="evenodd" d="M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z"></path></svg></a>Button Circular Loading</h2> <p>MUI Button provides an option to add an icon or any component to either side of the button. In our case, we’ll add a <code>CircularProgress</code> component at the end of the button element and modify the size to make it fit evenly:</p> <pre class="grvsc-container grvsc-has-line-highlighting default-dark" data-language="jsx" data-index="2"><code class="grvsc-code"><span class="grvsc-line"><span class="grvsc-source"><span class="mtk15">import</span><span class="mtk1"> </span><span class="mtk8">&quot;./styles.css&quot;</span><span class="mtk1">;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk15">import</span><span class="mtk1"> </span><span class="mtk12">Grid</span><span class="mtk1"> </span><span class="mtk15">from</span><span class="mtk1"> </span><span class="mtk8">&quot;@mui/material/Grid&quot;</span><span class="mtk1">;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk15">import</span><span class="mtk1"> </span><span class="mtk12">Box</span><span class="mtk1"> </span><span class="mtk15">from</span><span class="mtk1"> </span><span class="mtk8">&quot;@mui/material/Box&quot;</span><span class="mtk1">;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk15">import</span><span class="mtk1"> </span><span class="mtk12">Typography</span><span class="mtk1"> </span><span class="mtk15">from</span><span class="mtk1"> </span><span class="mtk8">&quot;@mui/material/Typography&quot;</span><span class="mtk1">;</span></span></span> <span class="grvsc-line grvsc-line-highlighted"><span class="grvsc-source"><span class="mtk15">import</span><span class="mtk1"> </span><span class="mtk12">Button</span><span class="mtk1"> </span><span class="mtk15">from</span><span class="mtk1"> </span><span class="mtk8">&quot;@mui/material/Button&quot;</span><span class="mtk1">;</span></span></span> <span class="grvsc-line grvsc-line-highlighted"><span class="grvsc-source"><span class="mtk15">import</span><span class="mtk1"> </span><span class="mtk12">CircularProgress</span><span class="mtk1"> </span><span class="mtk15">from</span><span class="mtk1"> </span><span class="mtk8">&quot;@mui/material/CircularProgress&quot;</span><span class="mtk1">;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk4">const</span><span class="mtk1"> </span><span class="mtk12">data</span><span class="mtk1"> = [...];</span></span></span> <span class="grvsc-line"><span class="grvsc-source"></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk15">export</span><span class="mtk1"> </span><span class="mtk15">default</span><span class="mtk1"> </span><span class="mtk4">function</span><span class="mtk1"> </span><span class="mtk11">App</span><span class="mtk1">() {</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk15">return</span><span class="mtk1"> (</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk17">&lt;</span><span class="mtk10">Box</span><span class="mtk17">&gt;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk17">&lt;</span><span class="mtk10">Content</span><span class="mtk1"> </span><span class="mtk17">/&gt;</span></span></span> <span class="grvsc-line grvsc-line-highlighted"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk17">&lt;</span><span class="mtk10">Button</span><span class="mtk1"> </span><span class="mtk12">endIcon</span><span class="mtk1">=</span><span class="mtk4">{</span><span class="mtk17">&lt;</span><span class="mtk10">CircularProgress</span><span class="mtk1"> </span><span class="mtk12">size</span><span class="mtk1">=</span><span class="mtk4">{</span><span class="mtk7">20</span><span class="mtk4">}</span><span class="mtk1"> </span><span class="mtk17">/&gt;</span><span class="mtk4">}</span><span class="mtk1"> </span><span class="mtk12">variant</span><span class="mtk1">=</span><span class="mtk8">&quot;outlined&quot;</span><span class="mtk17">&gt;</span></span></span> <span class="grvsc-line grvsc-line-highlighted"><span class="grvsc-source"><span class="mtk1"> Button Loader</span></span></span> <span class="grvsc-line grvsc-line-highlighted"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk17">&lt;/</span><span class="mtk10">Button</span><span class="mtk17">&gt;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk17">&lt;/</span><span class="mtk10">Box</span><span class="mtk17">&gt;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> );</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1">}</span></span></span> <span class="grvsc-line"><span class="grvsc-source"></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk4">const</span><span class="mtk1"> </span><span class="mtk11">Content</span><span class="mtk1"> = () </span><span class="mtk4">=&gt;</span><span class="mtk1"> (</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk17">&lt;</span><span class="mtk10">Box</span><span class="mtk1"> </span><span class="mtk12">sx</span><span class="mtk1">=</span><span class="mtk4">{</span><span class="mtk1">{ </span><span class="mtk12">p:</span><span class="mtk1"> </span><span class="mtk7">1</span><span class="mtk1"> }</span><span class="mtk4">}</span><span class="mtk17">&gt;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk17">&lt;</span><span class="mtk10">Typography</span><span class="mtk1"> </span><span class="mtk12">variant</span><span class="mtk1">=</span><span class="mtk8">&quot;h4&quot;</span><span class="mtk17">&gt;</span><span class="mtk1">Loading Techniques</span><span class="mtk17">&lt;/</span><span class="mtk10">Typography</span><span class="mtk17">&gt;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk17">&lt;</span><span class="mtk10">Grid</span><span class="mtk1"> </span><span class="mtk12">container</span><span class="mtk1"> </span><span class="mtk12">wrap</span><span class="mtk1">=</span><span class="mtk8">&quot;nowrap&quot;</span><span class="mtk17">&gt;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk4">{</span><span class="mtk12">data</span><span class="mtk1">.</span><span class="mtk11">map</span><span class="mtk1">((</span><span class="mtk12">item</span><span class="mtk1">, </span><span class="mtk12">index</span><span class="mtk1">) </span><span class="mtk4">=&gt;</span><span class="mtk1"> (</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk17">&lt;</span><span class="mtk10">Box</span><span class="mtk1"> </span><span class="mtk12">key</span><span class="mtk1">=</span><span class="mtk4">{</span><span class="mtk12">index</span><span class="mtk4">}</span><span class="mtk1"> </span><span class="mtk12">sx</span><span class="mtk1">=</span><span class="mtk4">{</span><span class="mtk1">{ </span><span class="mtk12">width:</span><span class="mtk1"> </span><span class="mtk7">210</span><span class="mtk1">, </span><span class="mtk12">marginRight:</span><span class="mtk1"> </span><span class="mtk7">1</span><span class="mtk1">, </span><span class="mtk12">my:</span><span class="mtk1"> </span><span class="mtk7">2</span><span class="mtk1"> }</span><span class="mtk4">}</span><span class="mtk17">&gt;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk17">&lt;</span><span class="mtk4">img</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">style</span><span class="mtk1">=</span><span class="mtk4">{</span><span class="mtk1">{ </span><span class="mtk12">width:</span><span class="mtk1"> </span><span class="mtk7">210</span><span class="mtk1">, </span><span class="mtk12">height:</span><span class="mtk1"> </span><span class="mtk7">118</span><span class="mtk1"> }</span><span class="mtk4">}</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">alt</span><span class="mtk1">=</span><span class="mtk4">{</span><span class="mtk12">item</span><span class="mtk1">.</span><span class="mtk12">title</span><span class="mtk4">}</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">src</span><span class="mtk1">=</span><span class="mtk4">{</span><span class="mtk12">item</span><span class="mtk1">.</span><span class="mtk12">src</span><span class="mtk4">}</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk17">/&gt;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk17">&lt;</span><span class="mtk10">Box</span><span class="mtk1"> </span><span class="mtk12">sx</span><span class="mtk1">=</span><span class="mtk4">{</span><span class="mtk1">{ </span><span class="mtk12">pr:</span><span class="mtk1"> </span><span class="mtk7">2</span><span class="mtk1"> }</span><span class="mtk4">}</span><span class="mtk17">&gt;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk17">&lt;</span><span class="mtk10">Typography</span><span class="mtk1"> </span><span class="mtk12">gutterBottom</span><span class="mtk1"> </span><span class="mtk12">variant</span><span class="mtk1">=</span><span class="mtk8">&quot;body2&quot;</span><span class="mtk17">&gt;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk4">{</span><span class="mtk12">item</span><span class="mtk1">.</span><span class="mtk12">title</span><span class="mtk4">}</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk17">&lt;/</span><span class="mtk10">Typography</span><span class="mtk17">&gt;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk17">&lt;</span><span class="mtk10">Typography</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">display</span><span class="mtk1">=</span><span class="mtk8">&quot;block&quot;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">variant</span><span class="mtk1">=</span><span class="mtk8">&quot;caption&quot;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">color</span><span class="mtk1">=</span><span class="mtk8">&quot;text.secondary&quot;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk17">&gt;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk4">{</span><span class="mtk12">item</span><span class="mtk1">.</span><span class="mtk12">channel</span><span class="mtk4">}</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk17">&lt;/</span><span class="mtk10">Typography</span><span class="mtk17">&gt;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk17">&lt;/</span><span class="mtk10">Box</span><span class="mtk17">&gt;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk17">&lt;/</span><span class="mtk10">Box</span><span class="mtk17">&gt;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> ))</span><span class="mtk4">}</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk17">&lt;/</span><span class="mtk10">Grid</span><span class="mtk17">&gt;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk17">&lt;/</span><span class="mtk10">Box</span><span class="mtk17">&gt;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1">);</span></span></span></code></pre> <p><span class="gatsby-resp-image-wrapper" style="position: relative; display: block; margin-left: auto; margin-right: auto; max-width: 720px; " > <a class="gatsby-resp-image-link" href="/static/158810cab6f61d1b6810d366bd647603/01dae/image-1.png" style="display: block" target="_blank" rel="noopener" > <span class="gatsby-resp-image-background-image" style="padding-bottom: 42.22222222222223%; position: relative; bottom: 0; left: 0; background-image: url('data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABQAAAAICAIAAAB2/0i6AAAACXBIWXMAAAsTAAALEwEAmpwYAAABiklEQVR42mO4f//BxfPnH96/+/DB3etXLt2/ffP371//iQMMf/79ffnn7+Wvf86/+n764/9Dz39MmTa9vLysq7u7vaW5vLSkrq727r1Xx49eO7TnzPOnXw7vOHX57L1/f8Gal+88MWHx5tlNPa2p9aG9W/zyJpmZm7MyMRhqyMmL8rMxMwgK8u3bfn5i8ZRZtTOvH37UU9+9fsGuPz//gTRXxDRnO8UmS3AHKmqluqSluCZYW1uwsDEbaqtqKkiJ8XIKS4ktKp3VqBrba1s4Y+nUrgMVk7b3f/r0DaR5/dTlvcUd1UmpVXExS4omL6pur64pT0lOTs/OTk9JyEqKT8/J2jpn3er6xXNSumevn7j+wsLNl1Z8+fEZpPnDh3dv3r/+8v3bl+/fP3z78uvP708w8PXbt79/QZ778OnD67dvPn398vkTUNV3RID9/PXn+4/fv//8A6Kfv////fcfqOH379//wNog4N+/f3/+/AGS6KH97effj1//fPjy+93n3x++/QEa8Z9oAAA/Vm4T+gaeuwAAAABJRU5ErkJggg=='); background-size: cover; display: block;" ></span> <img class="gatsby-resp-image-image" alt="Button Circular Loading" title="" src="/static/158810cab6f61d1b6810d366bd647603/37523/image-1.png" srcset="/static/158810cab6f61d1b6810d366bd647603/e9ff0/image-1.png 180w, /static/158810cab6f61d1b6810d366bd647603/f21e7/image-1.png 360w, /static/158810cab6f61d1b6810d366bd647603/37523/image-1.png 720w, /static/158810cab6f61d1b6810d366bd647603/01dae/image-1.png 721w" sizes="(max-width: 720px) 100vw, 720px" style="width:100%;height:100%;margin:0;vertical-align:middle;position:absolute;top:0;left:0;" loading="lazy" decoding="async" /> </a> </span></p> <h2 id="page-circular-loading" style="position:relative;"><a href="#page-circular-loading" aria-label="page circular loading permalink" class="anchor before"><svg aria-hidden="true" focusable="false" height="16" version="1.1" viewBox="0 0 16 16" width="16"><path fill-rule="evenodd" d="M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z"></path></svg></a>Page Circular Loading</h2> <p>In this example, we’re going to use the same <code>CircularProgress</code> component but position it in the center of the page. Additionally, we’re adding a layer that greys out the background and disable any interactions with the page:</p> <pre class="grvsc-container grvsc-has-line-highlighting default-dark" data-language="jsx" data-index="3"><code class="grvsc-code"><span class="grvsc-line"><span class="grvsc-source"><span class="mtk15">import</span><span class="mtk1"> </span><span class="mtk8">&quot;./styles.css&quot;</span><span class="mtk1">;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk15">import</span><span class="mtk1"> </span><span class="mtk12">Grid</span><span class="mtk1"> </span><span class="mtk15">from</span><span class="mtk1"> </span><span class="mtk8">&quot;@mui/material/Grid&quot;</span><span class="mtk1">;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk15">import</span><span class="mtk1"> </span><span class="mtk12">Box</span><span class="mtk1"> </span><span class="mtk15">from</span><span class="mtk1"> </span><span class="mtk8">&quot;@mui/material/Box&quot;</span><span class="mtk1">;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk15">import</span><span class="mtk1"> </span><span class="mtk12">Typography</span><span class="mtk1"> </span><span class="mtk15">from</span><span class="mtk1"> </span><span class="mtk8">&quot;@mui/material/Typography&quot;</span><span class="mtk1">;</span></span></span> <span class="grvsc-line grvsc-line-highlighted"><span class="grvsc-source"><span class="mtk15">import</span><span class="mtk1"> </span><span class="mtk12">CircularProgress</span><span class="mtk1"> </span><span class="mtk15">from</span><span class="mtk1"> </span><span class="mtk8">&quot;@mui/material/CircularProgress&quot;</span><span class="mtk1">;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk15">import</span><span class="mtk1"> { </span><span class="mtk12">styled</span><span class="mtk1"> } </span><span class="mtk15">from</span><span class="mtk1"> </span><span class="mtk8">&quot;@mui/system&quot;</span><span class="mtk1">;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk4">const</span><span class="mtk1"> </span><span class="mtk12">data</span><span class="mtk1"> = [...];</span></span></span> <span class="grvsc-line"><span class="grvsc-source"></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk15">export</span><span class="mtk1"> </span><span class="mtk15">default</span><span class="mtk1"> </span><span class="mtk4">function</span><span class="mtk1"> </span><span class="mtk11">App</span><span class="mtk1">() {</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk15">return</span><span class="mtk1"> (</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk17">&lt;</span><span class="mtk10">Box</span><span class="mtk17">&gt;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk17">&lt;</span><span class="mtk10">CircularLoading</span><span class="mtk1"> </span><span class="mtk17">/&gt;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk17">&lt;</span><span class="mtk10">Content</span><span class="mtk1"> </span><span class="mtk17">/&gt;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk17">&lt;/</span><span class="mtk10">Box</span><span class="mtk17">&gt;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> );</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1">}</span></span></span> <span class="grvsc-line"><span class="grvsc-source"></span></span> <span class="grvsc-line grvsc-line-highlighted"><span class="grvsc-source"><span class="mtk4">const</span><span class="mtk1"> </span><span class="mtk12">DisabledBackground</span><span class="mtk1"> = </span><span class="mtk11">styled</span><span class="mtk1">(</span><span class="mtk12">Box</span><span class="mtk1">)({</span></span></span> <span class="grvsc-line grvsc-line-highlighted"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">width:</span><span class="mtk1"> </span><span class="mtk8">&quot;100%&quot;</span><span class="mtk1">,</span></span></span> <span class="grvsc-line grvsc-line-highlighted"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">height:</span><span class="mtk1"> </span><span class="mtk8">&quot;100%&quot;</span><span class="mtk1">,</span></span></span> <span class="grvsc-line grvsc-line-highlighted"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">position:</span><span class="mtk1"> </span><span class="mtk8">&quot;fixed&quot;</span><span class="mtk1">,</span></span></span> <span class="grvsc-line grvsc-line-highlighted"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">background:</span><span class="mtk1"> </span><span class="mtk8">&quot;#ccc&quot;</span><span class="mtk1">,</span></span></span> <span class="grvsc-line grvsc-line-highlighted"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">opacity:</span><span class="mtk1"> </span><span class="mtk7">0.5</span><span class="mtk1">,</span></span></span> <span class="grvsc-line grvsc-line-highlighted"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">zIndex:</span><span class="mtk1"> </span><span class="mtk7">1</span></span></span> <span class="grvsc-line grvsc-line-highlighted"><span class="grvsc-source"><span class="mtk1">});</span></span></span> <span class="grvsc-line"><span class="grvsc-source"></span></span> <span class="grvsc-line grvsc-line-highlighted"><span class="grvsc-source"><span class="mtk4">const</span><span class="mtk1"> </span><span class="mtk11">CircularLoading</span><span class="mtk1"> = () </span><span class="mtk4">=&gt;</span><span class="mtk1"> (</span></span></span> <span class="grvsc-line grvsc-line-highlighted"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk17">&lt;&gt;</span></span></span> <span class="grvsc-line grvsc-line-highlighted"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk17">&lt;</span><span class="mtk10">CircularProgress</span></span></span> <span class="grvsc-line grvsc-line-highlighted"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">size</span><span class="mtk1">=</span><span class="mtk4">{</span><span class="mtk7">70</span><span class="mtk4">}</span></span></span> <span class="grvsc-line grvsc-line-highlighted"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">sx</span><span class="mtk1">=</span><span class="mtk4">{</span><span class="mtk1">{</span></span></span> <span class="grvsc-line grvsc-line-highlighted"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">position:</span><span class="mtk1"> </span><span class="mtk8">&quot;fixed&quot;</span><span class="mtk1">,</span></span></span> <span class="grvsc-line grvsc-line-highlighted"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">left:</span><span class="mtk1"> </span><span class="mtk8">&quot;50%&quot;</span><span class="mtk1">,</span></span></span> <span class="grvsc-line grvsc-line-highlighted"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">top:</span><span class="mtk1"> </span><span class="mtk8">&quot;50%&quot;</span><span class="mtk1">,</span></span></span> <span class="grvsc-line grvsc-line-highlighted"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">transform:</span><span class="mtk1"> </span><span class="mtk8">&quot;translate(-50%, -50%)&quot;</span><span class="mtk1">,</span></span></span> <span class="grvsc-line grvsc-line-highlighted"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">zIndex:</span><span class="mtk1"> </span><span class="mtk7">2</span></span></span> <span class="grvsc-line grvsc-line-highlighted"><span class="grvsc-source"><span class="mtk1"> }</span><span class="mtk4">}</span></span></span> <span class="grvsc-line grvsc-line-highlighted"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk17">/&gt;</span></span></span> <span class="grvsc-line grvsc-line-highlighted"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk17">&lt;</span><span class="mtk10">DisabledBackground</span><span class="mtk1"> </span><span class="mtk17">/&gt;</span></span></span> <span class="grvsc-line grvsc-line-highlighted"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk17">&lt;/&gt;</span></span></span> <span class="grvsc-line grvsc-line-highlighted"><span class="grvsc-source"><span class="mtk1">);</span></span></span> <span class="grvsc-line"><span class="grvsc-source"></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk4">const</span><span class="mtk1"> </span><span class="mtk11">Content</span><span class="mtk1"> = () </span><span class="mtk4">=&gt;</span><span class="mtk1"> (</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk17">&lt;</span><span class="mtk10">Box</span><span class="mtk1"> </span><span class="mtk12">sx</span><span class="mtk1">=</span><span class="mtk4">{</span><span class="mtk1">{ </span><span class="mtk12">p:</span><span class="mtk1"> </span><span class="mtk7">1</span><span class="mtk1"> }</span><span class="mtk4">}</span><span class="mtk17">&gt;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk17">&lt;</span><span class="mtk10">Typography</span><span class="mtk1"> </span><span class="mtk12">variant</span><span class="mtk1">=</span><span class="mtk8">&quot;h4&quot;</span><span class="mtk17">&gt;</span><span class="mtk1">Latest Videos:</span><span class="mtk17">&lt;/</span><span class="mtk10">Typography</span><span class="mtk17">&gt;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk17">&lt;</span><span class="mtk10">Grid</span><span class="mtk1"> </span><span class="mtk12">container</span><span class="mtk1"> </span><span class="mtk12">wrap</span><span class="mtk1">=</span><span class="mtk8">&quot;nowrap&quot;</span><span class="mtk17">&gt;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk4">{</span><span class="mtk12">data</span><span class="mtk1">.</span><span class="mtk11">map</span><span class="mtk1">((</span><span class="mtk12">item</span><span class="mtk1">, </span><span class="mtk12">index</span><span class="mtk1">) </span><span class="mtk4">=&gt;</span><span class="mtk1"> (</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk17">&lt;</span><span class="mtk10">Box</span><span class="mtk1"> </span><span class="mtk12">key</span><span class="mtk1">=</span><span class="mtk4">{</span><span class="mtk12">index</span><span class="mtk4">}</span><span class="mtk1"> </span><span class="mtk12">sx</span><span class="mtk1">=</span><span class="mtk4">{</span><span class="mtk1">{ </span><span class="mtk12">width:</span><span class="mtk1"> </span><span class="mtk7">210</span><span class="mtk1">, </span><span class="mtk12">marginRight:</span><span class="mtk1"> </span><span class="mtk7">1</span><span class="mtk1">, </span><span class="mtk12">my:</span><span class="mtk1"> </span><span class="mtk7">2</span><span class="mtk1"> }</span><span class="mtk4">}</span><span class="mtk17">&gt;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk17">&lt;</span><span class="mtk4">img</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">style</span><span class="mtk1">=</span><span class="mtk4">{</span><span class="mtk1">{ </span><span class="mtk12">width:</span><span class="mtk1"> </span><span class="mtk7">210</span><span class="mtk1">, </span><span class="mtk12">height:</span><span class="mtk1"> </span><span class="mtk7">118</span><span class="mtk1"> }</span><span class="mtk4">}</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">alt</span><span class="mtk1">=</span><span class="mtk4">{</span><span class="mtk12">item</span><span class="mtk1">.</span><span class="mtk12">title</span><span class="mtk4">}</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">src</span><span class="mtk1">=</span><span class="mtk4">{</span><span class="mtk12">item</span><span class="mtk1">.</span><span class="mtk12">src</span><span class="mtk4">}</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk17">/&gt;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk17">&lt;</span><span class="mtk10">Box</span><span class="mtk1"> </span><span class="mtk12">sx</span><span class="mtk1">=</span><span class="mtk4">{</span><span class="mtk1">{ </span><span class="mtk12">pr:</span><span class="mtk1"> </span><span class="mtk7">2</span><span class="mtk1"> }</span><span class="mtk4">}</span><span class="mtk17">&gt;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk17">&lt;</span><span class="mtk10">Typography</span><span class="mtk1"> </span><span class="mtk12">gutterBottom</span><span class="mtk1"> </span><span class="mtk12">variant</span><span class="mtk1">=</span><span class="mtk8">&quot;body2&quot;</span><span class="mtk17">&gt;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk4">{</span><span class="mtk12">item</span><span class="mtk1">.</span><span class="mtk12">title</span><span class="mtk4">}</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk17">&lt;/</span><span class="mtk10">Typography</span><span class="mtk17">&gt;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk17">&lt;</span><span class="mtk10">Typography</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">display</span><span class="mtk1">=</span><span class="mtk8">&quot;block&quot;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">variant</span><span class="mtk1">=</span><span class="mtk8">&quot;caption&quot;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">color</span><span class="mtk1">=</span><span class="mtk8">&quot;text.secondary&quot;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk17">&gt;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk4">{</span><span class="mtk12">item</span><span class="mtk1">.</span><span class="mtk12">channel</span><span class="mtk4">}</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk17">&lt;/</span><span class="mtk10">Typography</span><span class="mtk17">&gt;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk17">&lt;/</span><span class="mtk10">Box</span><span class="mtk17">&gt;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk17">&lt;/</span><span class="mtk10">Box</span><span class="mtk17">&gt;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> ))</span><span class="mtk4">}</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk17">&lt;/</span><span class="mtk10">Grid</span><span class="mtk17">&gt;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk17">&lt;/</span><span class="mtk10">Box</span><span class="mtk17">&gt;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1">);</span></span></span></code></pre> <p>Notice that we created <code>DisabledBackground</code> as a separate component as it will be re-used in the next section.</p> <p><span class="gatsby-resp-image-wrapper" style="position: relative; display: block; margin-left: auto; margin-right: auto; max-width: 694px; " > <a class="gatsby-resp-image-link" href="/static/daa43f6207372be5b6756a04c6d96848/31198/image-2.png" style="display: block" target="_blank" rel="noopener" > <span class="gatsby-resp-image-background-image" style="padding-bottom: 50.55555555555556%; position: relative; bottom: 0; left: 0; background-image: url('data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABQAAAAKCAIAAAA7N+mxAAAACXBIWXMAAAsTAAALEwEAmpwYAAABwElEQVR42oVR70/aUBTtP7tplLi5JQLCGAvLSKaocyYTZmQVB1HYEme2xMZlrFIsbV9/FyjSAsW+vlf9I/aKflvczrtf7nvn3JtzHtXt9mQgG7rWt0wZAE1VPM8LwxuMEcY4JAeHCKEAQhQQQFKkIy0B5biuPXS67tgaT7WBY7oeULWLC5bnOzzPcxzHsqyuG64zMY3e1dXIccaW1R+NJpFYtwe/FZNpgR9fmWrLKDNS4f3uwvzjTCr5Ihl//nRpbu4R/akiCoPDUq3dBGJTOd5raEIPBpCi6W/7xUo9/6qUzm3sHG5v0oX1rVhs8XU2lU0l0omVhcX5g4MqUzw9yhebjV/nrfP6Wa3dEaAfUCcfj8tvPrxLxDfjK9X8bn19b2ersPxsOZN9mUmv5tLJpSex/VL55G3lKEfX1kqN9ucv7QojfifeKVXVBEEEErjkOElSDM2UZUDsSpLIcpc/W6JlGoZhqrKqSroiSoop28OeOxlGniH0CTDJ9/Y2ivYmyhbCIMTBcBp2bKQ5oT0hOV/7EBIaDqJ/QAGaiX1yORvwFwLo64Mp6HvX95wZDd7X3eZ/ASMYogdf/yO+2/IQ/gDTsN5ltkkteAAAAABJRU5ErkJggg=='); background-size: cover; display: block;" ></span> <img class="gatsby-resp-image-image" alt="Page Circular Loading" title="" src="/static/daa43f6207372be5b6756a04c6d96848/31198/image-2.png" srcset="/static/daa43f6207372be5b6756a04c6d96848/e9ff0/image-2.png 180w, /static/daa43f6207372be5b6756a04c6d96848/f21e7/image-2.png 360w, /static/daa43f6207372be5b6756a04c6d96848/31198/image-2.png 694w" sizes="(max-width: 694px) 100vw, 694px" style="width:100%;height:100%;margin:0;vertical-align:middle;position:absolute;top:0;left:0;" loading="lazy" decoding="async" /> </a> </span></p> <h2 id="page-linear-progress-loading" style="position:relative;"><a href="#page-linear-progress-loading" aria-label="page linear progress loading permalink" class="anchor before"><svg aria-hidden="true" focusable="false" height="16" version="1.1" viewBox="0 0 16 16" width="16"><path fill-rule="evenodd" d="M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z"></path></svg></a>Page Linear Progress Loading</h2> <p>This is very similar to the previous example except we are using the <code>LinearProgress</code> component without any custom positioning:</p> <pre class="grvsc-container grvsc-has-line-highlighting default-dark" data-language="jsx" data-index="4"><code class="grvsc-code"><span class="grvsc-line"><span class="grvsc-source"><span class="mtk15">import</span><span class="mtk1"> </span><span class="mtk8">&quot;./styles.css&quot;</span><span class="mtk1">;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk15">import</span><span class="mtk1"> </span><span class="mtk12">Grid</span><span class="mtk1"> </span><span class="mtk15">from</span><span class="mtk1"> </span><span class="mtk8">&quot;@mui/material/Grid&quot;</span><span class="mtk1">;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk15">import</span><span class="mtk1"> </span><span class="mtk12">Box</span><span class="mtk1"> </span><span class="mtk15">from</span><span class="mtk1"> </span><span class="mtk8">&quot;@mui/material/Box&quot;</span><span class="mtk1">;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk15">import</span><span class="mtk1"> </span><span class="mtk12">Typography</span><span class="mtk1"> </span><span class="mtk15">from</span><span class="mtk1"> </span><span class="mtk8">&quot;@mui/material/Typography&quot;</span><span class="mtk1">;</span></span></span> <span class="grvsc-line grvsc-line-highlighted"><span class="grvsc-source"><span class="mtk15">import</span><span class="mtk1"> </span><span class="mtk12">LinearProgress</span><span class="mtk1"> </span><span class="mtk15">from</span><span class="mtk1"> </span><span class="mtk8">&quot;@mui/material/LinearProgress&quot;</span><span class="mtk1">;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk15">import</span><span class="mtk1"> { </span><span class="mtk12">styled</span><span class="mtk1"> } </span><span class="mtk15">from</span><span class="mtk1"> </span><span class="mtk8">&quot;@mui/system&quot;</span><span class="mtk1">;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk4">const</span><span class="mtk1"> </span><span class="mtk12">data</span><span class="mtk1"> = [...];</span></span></span> <span class="grvsc-line"><span class="grvsc-source"></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk15">export</span><span class="mtk1"> </span><span class="mtk15">default</span><span class="mtk1"> </span><span class="mtk4">function</span><span class="mtk1"> </span><span class="mtk11">App</span><span class="mtk1">() {</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk15">return</span><span class="mtk1"> (</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk17">&lt;</span><span class="mtk10">Box</span><span class="mtk17">&gt;</span></span></span> <span class="grvsc-line grvsc-line-highlighted"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk17">&lt;</span><span class="mtk10">LinearLoading</span><span class="mtk1"> </span><span class="mtk17">/&gt;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk17">&lt;</span><span class="mtk10">Content</span><span class="mtk1"> </span><span class="mtk17">/&gt;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk17">&lt;/</span><span class="mtk10">Box</span><span class="mtk17">&gt;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> );</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1">}</span></span></span> <span class="grvsc-line"><span class="grvsc-source"></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk4">const</span><span class="mtk1"> </span><span class="mtk12">DisabledBackground</span><span class="mtk1"> = </span><span class="mtk11">styled</span><span class="mtk1">(</span><span class="mtk12">Box</span><span class="mtk1">)({</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">width:</span><span class="mtk1"> </span><span class="mtk8">&quot;100%&quot;</span><span class="mtk1">,</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">height:</span><span class="mtk1"> </span><span class="mtk8">&quot;100%&quot;</span><span class="mtk1">,</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">position:</span><span class="mtk1"> </span><span class="mtk8">&quot;fixed&quot;</span><span class="mtk1">,</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">background:</span><span class="mtk1"> </span><span class="mtk8">&quot;#ccc&quot;</span><span class="mtk1">,</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">opacity:</span><span class="mtk1"> </span><span class="mtk7">0.5</span><span class="mtk1">,</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">zIndex:</span><span class="mtk1"> </span><span class="mtk7">1</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1">});</span></span></span> <span class="grvsc-line"><span class="grvsc-source"></span></span> <span class="grvsc-line grvsc-line-highlighted"><span class="grvsc-source"><span class="mtk4">const</span><span class="mtk1"> </span><span class="mtk11">LinearLoading</span><span class="mtk1"> = () </span><span class="mtk4">=&gt;</span><span class="mtk1"> (</span></span></span> <span class="grvsc-line grvsc-line-highlighted"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk17">&lt;&gt;</span></span></span> <span class="grvsc-line grvsc-line-highlighted"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk17">&lt;</span><span class="mtk10">LinearProgress</span><span class="mtk1"> </span><span class="mtk12">sx</span><span class="mtk1">=</span><span class="mtk4">{</span><span class="mtk1">{ </span><span class="mtk12">zIndex:</span><span class="mtk1"> </span><span class="mtk7">2</span><span class="mtk1"> }</span><span class="mtk4">}</span><span class="mtk1"> </span><span class="mtk17">/&gt;</span></span></span> <span class="grvsc-line grvsc-line-highlighted"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk17">&lt;</span><span class="mtk10">DisabledBackground</span><span class="mtk1"> </span><span class="mtk17">/&gt;</span></span></span> <span class="grvsc-line grvsc-line-highlighted"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk17">&lt;/&gt;</span></span></span> <span class="grvsc-line grvsc-line-highlighted"><span class="grvsc-source"><span class="mtk1">);</span></span></span> <span class="grvsc-line"><span class="grvsc-source"></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk4">const</span><span class="mtk1"> </span><span class="mtk11">Content</span><span class="mtk1"> = () </span><span class="mtk4">=&gt;</span><span class="mtk1"> (</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk17">&lt;</span><span class="mtk10">Box</span><span class="mtk1"> </span><span class="mtk12">sx</span><span class="mtk1">=</span><span class="mtk4">{</span><span class="mtk1">{ </span><span class="mtk12">p:</span><span class="mtk1"> </span><span class="mtk7">1</span><span class="mtk1"> }</span><span class="mtk4">}</span><span class="mtk17">&gt;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk17">&lt;</span><span class="mtk10">Typography</span><span class="mtk1"> </span><span class="mtk12">variant</span><span class="mtk1">=</span><span class="mtk8">&quot;h4&quot;</span><span class="mtk17">&gt;</span><span class="mtk1">Latest Videos:</span><span class="mtk17">&lt;/</span><span class="mtk10">Typography</span><span class="mtk17">&gt;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk17">&lt;</span><span class="mtk10">Grid</span><span class="mtk1"> </span><span class="mtk12">container</span><span class="mtk1"> </span><span class="mtk12">wrap</span><span class="mtk1">=</span><span class="mtk8">&quot;nowrap&quot;</span><span class="mtk17">&gt;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk4">{</span><span class="mtk12">data</span><span class="mtk1">.</span><span class="mtk11">map</span><span class="mtk1">((</span><span class="mtk12">item</span><span class="mtk1">, </span><span class="mtk12">index</span><span class="mtk1">) </span><span class="mtk4">=&gt;</span><span class="mtk1"> (</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk17">&lt;</span><span class="mtk10">Box</span><span class="mtk1"> </span><span class="mtk12">key</span><span class="mtk1">=</span><span class="mtk4">{</span><span class="mtk12">index</span><span class="mtk4">}</span><span class="mtk1"> </span><span class="mtk12">sx</span><span class="mtk1">=</span><span class="mtk4">{</span><span class="mtk1">{ </span><span class="mtk12">width:</span><span class="mtk1"> </span><span class="mtk7">210</span><span class="mtk1">, </span><span class="mtk12">marginRight:</span><span class="mtk1"> </span><span class="mtk7">1</span><span class="mtk1">, </span><span class="mtk12">my:</span><span class="mtk1"> </span><span class="mtk7">2</span><span class="mtk1"> }</span><span class="mtk4">}</span><span class="mtk17">&gt;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk17">&lt;</span><span class="mtk4">img</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">style</span><span class="mtk1">=</span><span class="mtk4">{</span><span class="mtk1">{ </span><span class="mtk12">width:</span><span class="mtk1"> </span><span class="mtk7">210</span><span class="mtk1">, </span><span class="mtk12">height:</span><span class="mtk1"> </span><span class="mtk7">118</span><span class="mtk1"> }</span><span class="mtk4">}</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">alt</span><span class="mtk1">=</span><span class="mtk4">{</span><span class="mtk12">item</span><span class="mtk1">.</span><span class="mtk12">title</span><span class="mtk4">}</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">src</span><span class="mtk1">=</span><span class="mtk4">{</span><span class="mtk12">item</span><span class="mtk1">.</span><span class="mtk12">src</span><span class="mtk4">}</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk17">/&gt;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk17">&lt;</span><span class="mtk10">Box</span><span class="mtk1"> </span><span class="mtk12">sx</span><span class="mtk1">=</span><span class="mtk4">{</span><span class="mtk1">{ </span><span class="mtk12">pr:</span><span class="mtk1"> </span><span class="mtk7">2</span><span class="mtk1"> }</span><span class="mtk4">}</span><span class="mtk17">&gt;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk17">&lt;</span><span class="mtk10">Typography</span><span class="mtk1"> </span><span class="mtk12">gutterBottom</span><span class="mtk1"> </span><span class="mtk12">variant</span><span class="mtk1">=</span><span class="mtk8">&quot;body2&quot;</span><span class="mtk17">&gt;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk4">{</span><span class="mtk12">item</span><span class="mtk1">.</span><span class="mtk12">title</span><span class="mtk4">}</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk17">&lt;/</span><span class="mtk10">Typography</span><span class="mtk17">&gt;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk17">&lt;</span><span class="mtk10">Typography</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">display</span><span class="mtk1">=</span><span class="mtk8">&quot;block&quot;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">variant</span><span class="mtk1">=</span><span class="mtk8">&quot;caption&quot;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">color</span><span class="mtk1">=</span><span class="mtk8">&quot;text.secondary&quot;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk17">&gt;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk4">{</span><span class="mtk12">item</span><span class="mtk1">.</span><span class="mtk12">channel</span><span class="mtk4">}</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk17">&lt;/</span><span class="mtk10">Typography</span><span class="mtk17">&gt;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk17">&lt;/</span><span class="mtk10">Box</span><span class="mtk17">&gt;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk17">&lt;/</span><span class="mtk10">Box</span><span class="mtk17">&gt;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> ))</span><span class="mtk4">}</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk17">&lt;/</span><span class="mtk10">Grid</span><span class="mtk17">&gt;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk17">&lt;/</span><span class="mtk10">Box</span><span class="mtk17">&gt;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1">);</span></span></span></code></pre> <p><span class="gatsby-resp-image-wrapper" style="position: relative; display: block; margin-left: auto; margin-right: auto; max-width: 697px; " > <a class="gatsby-resp-image-link" href="/static/485c003fc80e4a5fb1f994e624526881/7422e/image-3.png" style="display: block" target="_blank" rel="noopener" > <span class="gatsby-resp-image-background-image" style="padding-bottom: 37.77777777777778%; position: relative; bottom: 0; left: 0; background-image: url('data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABQAAAAICAIAAAB2/0i6AAAACXBIWXMAAAsTAAALEwEAmpwYAAABpElEQVR42lVQi04aQRTdr62vKEUMCE2jIanyyJIFFUWUrA2bCgs+aBRFgkixQlXISnnXnZ3dnQf7FQ6oiT05uWdybubOncOVH7qVRv9Xc1C679w2+wNgQGxpaPQfTfqRENEeII99xLWU5qDXUdVh56/SbT9pAFij0YhSRkrJ64EQTAkmTFklZNyh2KKY65n4j4ruWsPbIaoMyHn5d8Dv24pGd2Ox6GaE53lBEBqNdu2udZErPinDx5pS+FlizyGMudRpISel5NBOOF0M7p9EthNTU588rqVVj9PtsM/NTttsC9Wb+3zqKhWTmtX29WU5nUwrD13MLot8THTbBadnL7QX98UT2/GZuZlll3Plq3v1i2vRNv/ZYb/8kT9c3sp8S5xJpyd1OVOVyvUKxZSTIuJukA97V7KbB9mNpJwUvV4vW9UfDIb864H1NV/AXzzK53ayR4Kc+S7manK+flxRSuzv3D9N1XQIdf0ZahCZpomACiCEQNMMw2DZWZYFdfisqSpgHgQAYDRObby2oetMyFuQBCGTObrxZuIJ2EhmsrlkAvyOF7u0bsCmXrz/AAAAAElFTkSuQmCC'); background-size: cover; display: block;" ></span> <img class="gatsby-resp-image-image" alt="Page Linear Loading" title="" src="/static/485c003fc80e4a5fb1f994e624526881/7422e/image-3.png" srcset="/static/485c003fc80e4a5fb1f994e624526881/e9ff0/image-3.png 180w, /static/485c003fc80e4a5fb1f994e624526881/f21e7/image-3.png 360w, /static/485c003fc80e4a5fb1f994e624526881/7422e/image-3.png 697w" sizes="(max-width: 697px) 100vw, 697px" style="width:100%;height:100%;margin:0;vertical-align:middle;position:absolute;top:0;left:0;" loading="lazy" decoding="async" /> </a> </span></p> <h2 id="skeleton-loading" style="position:relative;"><a href="#skeleton-loading" aria-label="skeleton loading permalink" class="anchor before"><svg aria-hidden="true" focusable="false" height="16" version="1.1" viewBox="0 0 16 16" width="16"><path fill-rule="evenodd" d="M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z"></path></svg></a>Skeleton Loading</h2> <p>Skeleton loading is a technique used to provide a better user experience while waiting for content to be loaded, especially when a bunch of different components is being loaded in parallel.</p> <p>Luckily, MUI provides a dedicated <a href="https://mui.com/components/skeleton/">component API</a> for creating any skeleton styles we need. In our case, we’re going to mimic the title and cards from the <code>Content</code> component as follows:</p> <pre class="grvsc-container grvsc-has-line-highlighting default-dark" data-language="jsx" data-index="5"><code class="grvsc-code"><span class="grvsc-line"><span class="grvsc-source"><span class="mtk15">import</span><span class="mtk1"> </span><span class="mtk8">&quot;./styles.css&quot;</span><span class="mtk1">;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk15">import</span><span class="mtk1"> </span><span class="mtk12">Grid</span><span class="mtk1"> </span><span class="mtk15">from</span><span class="mtk1"> </span><span class="mtk8">&quot;@mui/material/Grid&quot;</span><span class="mtk1">;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk15">import</span><span class="mtk1"> </span><span class="mtk12">Box</span><span class="mtk1"> </span><span class="mtk15">from</span><span class="mtk1"> </span><span class="mtk8">&quot;@mui/material/Box&quot;</span><span class="mtk1">;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk15">import</span><span class="mtk1"> </span><span class="mtk12">Typography</span><span class="mtk1"> </span><span class="mtk15">from</span><span class="mtk1"> </span><span class="mtk8">&quot;@mui/material/Typography&quot;</span><span class="mtk1">;</span></span></span> <span class="grvsc-line grvsc-line-highlighted"><span class="grvsc-source"><span class="mtk15">import</span><span class="mtk1"> </span><span class="mtk12">Skeleton</span><span class="mtk1"> </span><span class="mtk15">from</span><span class="mtk1"> </span><span class="mtk8">&quot;@mui/material/Skeleton&quot;</span><span class="mtk1">;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk15">export</span><span class="mtk1"> </span><span class="mtk15">default</span><span class="mtk1"> </span><span class="mtk4">function</span><span class="mtk1"> </span><span class="mtk11">App</span><span class="mtk1">() {</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk15">return</span><span class="mtk1"> (</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk17">&lt;</span><span class="mtk10">Box</span><span class="mtk17">&gt;</span></span></span> <span class="grvsc-line grvsc-line-highlighted"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk17">&lt;</span><span class="mtk10">SkeletonLoading</span><span class="mtk1"> </span><span class="mtk17">/&gt;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk17">&lt;/</span><span class="mtk10">Box</span><span class="mtk17">&gt;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> );</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1">}</span></span></span> <span class="grvsc-line"><span class="grvsc-source"></span></span> <span class="grvsc-line grvsc-line-highlighted"><span class="grvsc-source"><span class="mtk4">const</span><span class="mtk1"> </span><span class="mtk11">SkeletonLoading</span><span class="mtk1"> = () </span><span class="mtk4">=&gt;</span><span class="mtk1"> (</span></span></span> <span class="grvsc-line grvsc-line-highlighted"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk17">&lt;</span><span class="mtk10">Box</span><span class="mtk1"> </span><span class="mtk12">sx</span><span class="mtk1">=</span><span class="mtk4">{</span><span class="mtk1">{ </span><span class="mtk12">p:</span><span class="mtk1"> </span><span class="mtk7">1</span><span class="mtk1"> }</span><span class="mtk4">}</span><span class="mtk17">&gt;</span></span></span> <span class="grvsc-line grvsc-line-highlighted"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk17">&lt;</span><span class="mtk10">Typography</span><span class="mtk1"> </span><span class="mtk12">variant</span><span class="mtk1">=</span><span class="mtk8">&quot;h4&quot;</span><span class="mtk17">&gt;</span></span></span> <span class="grvsc-line grvsc-line-highlighted"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk17">&lt;</span><span class="mtk10">Skeleton</span><span class="mtk1"> </span><span class="mtk12">width</span><span class="mtk1">=</span><span class="mtk8">&quot;30%&quot;</span><span class="mtk1"> </span><span class="mtk17">/&gt;</span></span></span> <span class="grvsc-line grvsc-line-highlighted"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk17">&lt;/</span><span class="mtk10">Typography</span><span class="mtk17">&gt;</span></span></span> <span class="grvsc-line grvsc-line-highlighted"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk17">&lt;</span><span class="mtk10">Grid</span><span class="mtk1"> </span><span class="mtk12">container</span><span class="mtk1"> </span><span class="mtk12">wrap</span><span class="mtk1">=</span><span class="mtk8">&quot;nowrap&quot;</span><span class="mtk17">&gt;</span></span></span> <span class="grvsc-line grvsc-line-highlighted"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk4">{</span><span class="mtk10">Array</span><span class="mtk1">.</span><span class="mtk11">from</span><span class="mtk1">(</span><span class="mtk4">new</span><span class="mtk1"> </span><span class="mtk10">Array</span><span class="mtk1">(</span><span class="mtk7">3</span><span class="mtk1">)).</span><span class="mtk11">map</span><span class="mtk1">((</span><span class="mtk12">item</span><span class="mtk1">, </span><span class="mtk12">index</span><span class="mtk1">) </span><span class="mtk4">=&gt;</span><span class="mtk1"> (</span></span></span> <span class="grvsc-line grvsc-line-highlighted"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk17">&lt;</span><span class="mtk10">Box</span><span class="mtk1"> </span><span class="mtk12">key</span><span class="mtk1">=</span><span class="mtk4">{</span><span class="mtk12">index</span><span class="mtk4">}</span><span class="mtk1"> </span><span class="mtk12">sx</span><span class="mtk1">=</span><span class="mtk4">{</span><span class="mtk1">{ </span><span class="mtk12">width:</span><span class="mtk1"> </span><span class="mtk7">210</span><span class="mtk1">, </span><span class="mtk12">marginRight:</span><span class="mtk1"> </span><span class="mtk7">1</span><span class="mtk1">, </span><span class="mtk12">my:</span><span class="mtk1"> </span><span class="mtk7">2</span><span class="mtk1"> }</span><span class="mtk4">}</span><span class="mtk17">&gt;</span></span></span> <span class="grvsc-line grvsc-line-highlighted"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk17">&lt;</span><span class="mtk10">Skeleton</span><span class="mtk1"> </span><span class="mtk12">variant</span><span class="mtk1">=</span><span class="mtk8">&quot;rectangular&quot;</span><span class="mtk1"> </span><span class="mtk12">width</span><span class="mtk1">=</span><span class="mtk4">{</span><span class="mtk7">210</span><span class="mtk4">}</span><span class="mtk1"> </span><span class="mtk12">height</span><span class="mtk1">=</span><span class="mtk4">{</span><span class="mtk7">118</span><span class="mtk4">}</span><span class="mtk1"> </span><span class="mtk17">/&gt;</span></span></span> <span class="grvsc-line grvsc-line-highlighted"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk17">&lt;</span><span class="mtk10">Box</span><span class="mtk1"> </span><span class="mtk12">sx</span><span class="mtk1">=</span><span class="mtk4">{</span><span class="mtk1">{ </span><span class="mtk12">pt:</span><span class="mtk1"> </span><span class="mtk7">0.5</span><span class="mtk1"> }</span><span class="mtk4">}</span><span class="mtk17">&gt;</span></span></span> <span class="grvsc-line grvsc-line-highlighted"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk17">&lt;</span><span class="mtk10">Skeleton</span><span class="mtk1"> </span><span class="mtk17">/&gt;</span></span></span> <span class="grvsc-line grvsc-line-highlighted"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk17">&lt;</span><span class="mtk10">Skeleton</span><span class="mtk1"> </span><span class="mtk12">width</span><span class="mtk1">=</span><span class="mtk8">&quot;60%&quot;</span><span class="mtk1"> </span><span class="mtk17">/&gt;</span></span></span> <span class="grvsc-line grvsc-line-highlighted"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk17">&lt;/</span><span class="mtk10">Box</span><span class="mtk17">&gt;</span></span></span> <span class="grvsc-line grvsc-line-highlighted"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk17">&lt;/</span><span class="mtk10">Box</span><span class="mtk17">&gt;</span></span></span> <span class="grvsc-line grvsc-line-highlighted"><span class="grvsc-source"><span class="mtk1"> ))</span><span class="mtk4">}</span></span></span> <span class="grvsc-line grvsc-line-highlighted"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk17">&lt;/</span><span class="mtk10">Grid</span><span class="mtk17">&gt;</span></span></span> <span class="grvsc-line grvsc-line-highlighted"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk17">&lt;/</span><span class="mtk10">Box</span><span class="mtk17">&gt;</span></span></span> <span class="grvsc-line grvsc-line-highlighted"><span class="grvsc-source"><span class="mtk1">);</span></span></span></code></pre> <p>We used the same HTML structure and layout but with <code>Skeleton</code> components instead of images and titles.</p> <p><span class="gatsby-resp-image-wrapper" style="position: relative; display: block; margin-left: auto; margin-right: auto; max-width: 670px; " > <a class="gatsby-resp-image-link" href="/static/9727fb6e385b5cf7cdef57750efdf5a4/d67fd/image-4.png" style="display: block" target="_blank" rel="noopener" > <span class="gatsby-resp-image-background-image" style="padding-bottom: 37.77777777777778%; position: relative; bottom: 0; left: 0; background-image: url('data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABQAAAAICAIAAAB2/0i6AAAACXBIWXMAAAsTAAALEwEAmpwYAAAAgklEQVR42r2Q3QoCIRhEff/nVPM/WVQ0zW1YcdnyJgg6Fx/DYQQZ4py7T5BjjPvXkBBCnCDnnGutj3dWU0pprRHO+W2CbIwRQjDG+ARZay2lvEpK6bZtZO3967FSSh/gw7jee2vth8SWq8RG5FwLAzwPUkrDIAyJe9YgR633TvYfeAFAk8TsbPgzQwAAAABJRU5ErkJggg=='); background-size: cover; display: block;" ></span> <img class="gatsby-resp-image-image" alt="Skeleton Loading" title="" src="/static/9727fb6e385b5cf7cdef57750efdf5a4/d67fd/image-4.png" srcset="/static/9727fb6e385b5cf7cdef57750efdf5a4/e9ff0/image-4.png 180w, /static/9727fb6e385b5cf7cdef57750efdf5a4/f21e7/image-4.png 360w, /static/9727fb6e385b5cf7cdef57750efdf5a4/d67fd/image-4.png 670w" sizes="(max-width: 670px) 100vw, 670px" style="width:100%;height:100%;margin:0;vertical-align:middle;position:absolute;top:0;left:0;" loading="lazy" decoding="async" /> </a> </span></p> <h2 id="take-a-way" style="position:relative;"><a href="#take-a-way" aria-label="take a way permalink" class="anchor before"><svg aria-hidden="true" focusable="false" height="16" version="1.1" viewBox="0 0 16 16" width="16"><path fill-rule="evenodd" d="M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z"></path></svg></a>Take a way</h2> <p>Those examples are just some of the many amazing loading techniques that can be used from MUI. I highly suggest going through the <a href="https://mui.com/components/progress/">documentation</a> to explore other options that might be useful for your application.</p> <p>Bye for now 👋</p> <style class="grvsc-styles"> .grvsc-container { overflow: auto; position: relative; -webkit-overflow-scrolling: touch; padding-top: 1rem; padding-top: var(--grvsc-padding-top, var(--grvsc-padding-v, 1rem)); padding-bottom: 1rem; padding-bottom: var(--grvsc-padding-bottom, var(--grvsc-padding-v, 1rem)); border-radius: 8px; border-radius: var(--grvsc-border-radius, 8px); font-feature-settings: normal; line-height: 1.4; } .grvsc-code { display: table; } .grvsc-line { display: table-row; box-sizing: border-box; width: 100%; position: relative; } .grvsc-line > * { position: relative; } .grvsc-gutter-pad { display: table-cell; padding-left: 0.75rem; padding-left: calc(var(--grvsc-padding-left, var(--grvsc-padding-h, 1.5rem)) / 2); } .grvsc-gutter { display: table-cell; -webkit-user-select: none; -moz-user-select: none; user-select: none; } .grvsc-gutter::before { content: attr(data-content); } .grvsc-source { display: table-cell; padding-left: 1.5rem; padding-left: var(--grvsc-padding-left, var(--grvsc-padding-h, 1.5rem)); padding-right: 1.5rem; padding-right: var(--grvsc-padding-right, var(--grvsc-padding-h, 1.5rem)); } .grvsc-source:empty::after { content: ' '; -webkit-user-select: none; -moz-user-select: none; user-select: none; } .grvsc-gutter + .grvsc-source { padding-left: 0.75rem; padding-left: calc(var(--grvsc-padding-left, var(--grvsc-padding-h, 1.5rem)) / 2); } /* Line transformer styles */ .grvsc-has-line-highlighting > .grvsc-code > .grvsc-line::before { content: ' '; position: absolute; width: 100%; } .grvsc-line-diff-add::before { background-color: var(--grvsc-line-diff-add-background-color, rgba(0, 255, 60, 0.2)); } .grvsc-line-diff-del::before { background-color: var(--grvsc-line-diff-del-background-color, rgba(255, 0, 20, 0.2)); } .grvsc-line-number { padding: 0 2px; text-align: right; opacity: 0.7; } .default-dark { background-color: #1E1E1E; color: #D4D4D4; } .default-dark .mtk15 { color: #C586C0; } .default-dark .mtk1 { color: #D4D4D4; } .default-dark .mtk8 { color: #CE9178; } .default-dark .mtk12 { color: #9CDCFE; } .default-dark .mtk4 { color: #569CD6; } .default-dark .mtk11 { color: #DCDCAA; } .default-dark .mtk17 { color: #808080; } .default-dark .mtk10 { color: #4EC9B0; } .default-dark .mtk7 { color: #B5CEA8; } .default-dark .grvsc-line-highlighted::before { background-color: var(--grvsc-line-highlighted-background-color, rgba(255, 255, 255, 0.1)); box-shadow: inset var(--grvsc-line-highlighted-border-width, 4px) 0 0 0 var(--grvsc-line-highlighted-border-color, rgba(255, 255, 255, 0.5)); } </style><![CDATA[[Part 4] Load, Add, Update and Delete Table Rows using API Services]]>https://muhimasri.compart-4-load-add-update-and-delete-table-rows-using-api-serviceshttps://muhimasri.compart-4-load-add-update-and-delete-table-rows-using-api-services<p>In this part of the Bootstrap Vue Table series, we are taking all features we built in previous parts and connecting them to API services.</p> <p>We won’t be building or using any custom backend solution as this is not the objective of this series. Instead, we are utilizing <a href="https://jsonplaceholder.typicode.com/">{JSON} Placeholder</a>, which is a free fake API for testing and prototyping.</p> <p>At the end of this tutorial, we should have the following results (all video demos will have the network panel open to show API calls):</p> <div data-youtube="0WbXWJvrZWw"> <button>Play Example</button> </div> <p>Before we start, below is the full code from the <a href="https://muhimasri.com/blogs/part-3-add-and-remove-table-rows-with-bootstrap-vue/">previous part</a>:</p> <h4 id="editabletable-component" style="position:relative;"><a href="#editabletable-component" aria-label="editabletable component permalink" class="anchor before"><svg aria-hidden="true" focusable="false" height="16" version="1.1" viewBox="0 0 16 16" width="16"><path fill-rule="evenodd" d="M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z"></path></svg></a>EditableTable Component</h4> <pre class="grvsc-container default-dark" data-language="html" data-index="0"><code class="grvsc-code"><span class="grvsc-line"><span class="grvsc-source"><span class="mtk17">&lt;</span><span class="mtk4">template</span><span class="mtk17">&gt;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk17">&lt;</span><span class="mtk4">article</span><span class="mtk17">&gt;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk17">&lt;</span><span class="mtk4">b-modal</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">id</span><span class="mtk1">=</span><span class="mtk8">&quot;modal-1&quot;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">title</span><span class="mtk1">=</span><span class="mtk8">&quot;Confirm&quot;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">v-model</span><span class="mtk1">=</span><span class="mtk8">&quot;openDialog&quot;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">ok-title</span><span class="mtk1">=</span><span class="mtk8">&quot;Remove&quot;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">@ok</span><span class="mtk1">=</span><span class="mtk8">&quot;removeRowsHandler&quot;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk17">&gt;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk17">&lt;</span><span class="mtk4">p</span><span class="mtk1"> </span><span class="mtk12">class</span><span class="mtk1">=</span><span class="mtk8">&quot;my-4&quot;</span><span class="mtk17">&gt;</span><span class="mtk1">Are you sure you want to remove the selected rows?</span><span class="mtk17">&lt;/</span><span class="mtk4">p</span><span class="mtk17">&gt;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk17">&lt;/</span><span class="mtk4">b-modal</span><span class="mtk17">&gt;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk17">&lt;</span><span class="mtk4">div</span><span class="mtk1"> </span><span class="mtk12">class</span><span class="mtk1">=</span><span class="mtk8">&quot;action-container&quot;</span><span class="mtk17">&gt;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk17">&lt;</span><span class="mtk4">b-button</span><span class="mtk1"> </span><span class="mtk12">class</span><span class="mtk1">=</span><span class="mtk8">&quot;add-button&quot;</span><span class="mtk1"> </span><span class="mtk12">variant</span><span class="mtk1">=</span><span class="mtk8">&quot;success&quot;</span><span class="mtk1"> </span><span class="mtk12">@click</span><span class="mtk1">=</span><span class="mtk8">&quot;addRowHandler&quot;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk17">&gt;</span><span class="mtk1">Add Row</span><span class="mtk17">&lt;/</span><span class="mtk4">b-button</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk17">&gt;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk17">&lt;</span><span class="mtk4">b-button</span><span class="mtk1"> </span><span class="mtk12">variant</span><span class="mtk1">=</span><span class="mtk8">&quot;danger&quot;</span><span class="mtk1"> </span><span class="mtk12">@click</span><span class="mtk1">=</span><span class="mtk8">&quot;openDialog = true&quot;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk17">&gt;</span><span class="mtk1">Remove Rows</span><span class="mtk17">&lt;/</span><span class="mtk4">b-button</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk17">&gt;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk17">&lt;/</span><span class="mtk4">div</span><span class="mtk17">&gt;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk17">&lt;</span><span class="mtk4">b-table</span><span class="mtk1"> </span><span class="mtk12">class</span><span class="mtk1">=</span><span class="mtk8">&quot;b-table&quot;</span><span class="mtk1"> </span><span class="mtk12">:items</span><span class="mtk1">=</span><span class="mtk8">&quot;tableItems&quot;</span><span class="mtk1"> </span><span class="mtk12">:fields</span><span class="mtk1">=</span><span class="mtk8">&quot;fields&quot;</span><span class="mtk1"> </span><span class="mtk12">fixed</span><span class="mtk17">&gt;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk17">&lt;</span><span class="mtk4">template</span><span class="mtk1"> </span><span class="mtk12">v-for</span><span class="mtk1">=</span><span class="mtk8">&quot;(field, index) in fields&quot;</span><span class="mtk1"> </span><span class="mtk12">#[`cell(${field.key})`]</span><span class="mtk1">=</span><span class="mtk8">&quot;data&quot;</span><span class="mtk17">&gt;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk17">&lt;</span><span class="mtk4">b-form-datepicker</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">v-if</span><span class="mtk1">=</span><span class="mtk8">&quot;field.type === &#39;date&#39; &amp;&amp; tableItems[data.index].isEdit&quot;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">:key</span><span class="mtk1">=</span><span class="mtk8">&quot;index&quot;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">:type</span><span class="mtk1">=</span><span class="mtk8">&quot;field.type&quot;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">:value</span><span class="mtk1">=</span><span class="mtk8">&quot;tableItems[data.index][field.key]&quot;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">@input</span><span class="mtk1">=</span><span class="mtk8">&quot;(value) =&gt; inputHandler(value, data.index, field.key)&quot;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk17">&gt;&lt;/</span><span class="mtk4">b-form-datepicker</span><span class="mtk17">&gt;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk17">&lt;</span><span class="mtk4">b-form-select</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">v-else-if</span><span class="mtk1">=</span><span class="mtk8">&quot;field.type === &#39;select&#39; &amp;&amp; tableItems[data.index].isEdit&quot;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">:key</span><span class="mtk1">=</span><span class="mtk8">&quot;index&quot;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">:value</span><span class="mtk1">=</span><span class="mtk8">&quot;tableItems[data.index][field.key]&quot;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">@input</span><span class="mtk1">=</span><span class="mtk8">&quot;(value) =&gt; inputHandler(value, data.index, field.key)&quot;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">:options</span><span class="mtk1">=</span><span class="mtk8">&quot;field.options&quot;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk17">&gt;&lt;/</span><span class="mtk4">b-form-select</span><span class="mtk17">&gt;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk17">&lt;</span><span class="mtk4">b-checkbox</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">v-else-if</span><span class="mtk1">=</span><span class="mtk8">&quot;field.key === &#39;selectRow&#39;&quot;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">:checked</span><span class="mtk1">=</span><span class="mtk8">&quot;tableItems[data.index].isSelected&quot;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">:key</span><span class="mtk1">=</span><span class="mtk8">&quot;index&quot;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">@change</span><span class="mtk1">=</span><span class="mtk8">&quot;selectRowHandler(data)&quot;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk17">&gt;&lt;/</span><span class="mtk4">b-checkbox</span><span class="mtk17">&gt;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk17">&lt;</span><span class="mtk4">div</span><span class="mtk1"> </span><span class="mtk12">:key</span><span class="mtk1">=</span><span class="mtk8">&quot;index&quot;</span><span class="mtk1"> </span><span class="mtk12">v-else-if</span><span class="mtk1">=</span><span class="mtk8">&quot;field.type === &#39;edit&#39;&quot;</span><span class="mtk17">&gt;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk17">&lt;</span><span class="mtk4">b-button</span><span class="mtk1"> </span><span class="mtk12">@click</span><span class="mtk1">=</span><span class="mtk8">&quot;editRowHandler(data)&quot;</span><span class="mtk17">&gt;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk17">&lt;</span><span class="mtk4">span</span><span class="mtk1"> </span><span class="mtk12">v-if</span><span class="mtk1">=</span><span class="mtk8">&quot;!tableItems[data.index].isEdit&quot;</span><span class="mtk17">&gt;</span><span class="mtk1">Edit</span><span class="mtk17">&lt;/</span><span class="mtk4">span</span><span class="mtk17">&gt;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk17">&lt;</span><span class="mtk4">span</span><span class="mtk1"> </span><span class="mtk12">v-else</span><span class="mtk17">&gt;</span><span class="mtk1">Done</span><span class="mtk17">&lt;/</span><span class="mtk4">span</span><span class="mtk17">&gt;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk17">&lt;/</span><span class="mtk4">b-button</span><span class="mtk17">&gt;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk17">&lt;</span><span class="mtk4">b-button</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">class</span><span class="mtk1">=</span><span class="mtk8">&quot;delete-button&quot;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">variant</span><span class="mtk1">=</span><span class="mtk8">&quot;danger&quot;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">@click</span><span class="mtk1">=</span><span class="mtk8">&quot;removeRowHandler(data.index)&quot;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk17">&gt;</span><span class="mtk1">Remove</span><span class="mtk17">&lt;/</span><span class="mtk4">b-button</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk17">&gt;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk17">&lt;/</span><span class="mtk4">div</span><span class="mtk17">&gt;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk17">&lt;</span><span class="mtk4">b-form-input</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">v-else-if</span><span class="mtk1">=</span><span class="mtk8">&quot;field.type &amp;&amp; tableItems[data.index].isEdit&quot;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">:key</span><span class="mtk1">=</span><span class="mtk8">&quot;index&quot;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">:type</span><span class="mtk1">=</span><span class="mtk8">&quot;field.type&quot;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">:value</span><span class="mtk1">=</span><span class="mtk8">&quot;tableItems[data.index][field.key]&quot;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">@blur</span><span class="mtk1">=</span><span class="mtk8">&quot;(e) =&gt; inputHandler(e.target.value, data.index, field.key)&quot;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk17">&gt;&lt;/</span><span class="mtk4">b-form-input</span><span class="mtk17">&gt;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk17">&lt;</span><span class="mtk4">span</span><span class="mtk1"> </span><span class="mtk12">:key</span><span class="mtk1">=</span><span class="mtk8">&quot;index&quot;</span><span class="mtk1"> </span><span class="mtk12">v-else</span><span class="mtk17">&gt;</span><span class="mtk1">{{ data.value }}</span><span class="mtk17">&lt;/</span><span class="mtk4">span</span><span class="mtk17">&gt;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk17">&lt;/</span><span class="mtk4">template</span><span class="mtk17">&gt;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk17">&lt;/</span><span class="mtk4">b-table</span><span class="mtk17">&gt;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk17">&lt;/</span><span class="mtk4">article</span><span class="mtk17">&gt;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk17">&lt;/</span><span class="mtk4">template</span><span class="mtk17">&gt;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk17">&lt;</span><span class="mtk4">script</span><span class="mtk17">&gt;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk15">export</span><span class="mtk1"> </span><span class="mtk15">default</span><span class="mtk1"> {</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">name:</span><span class="mtk1"> </span><span class="mtk8">&quot;EditableTable&quot;</span><span class="mtk1">,</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">components:</span><span class="mtk1"> {},</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">props:</span><span class="mtk1"> {</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">value:</span><span class="mtk1"> </span><span class="mtk10">Array</span><span class="mtk1">,</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">fields:</span><span class="mtk1"> </span><span class="mtk10">Array</span><span class="mtk1">,</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> },</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk11">data</span><span class="mtk1">() {</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk15">return</span><span class="mtk1"> {</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">tableItems:</span><span class="mtk1"> </span><span class="mtk4">this</span><span class="mtk1">.</span><span class="mtk12">value</span><span class="mtk1">.</span><span class="mtk11">map</span><span class="mtk1">((</span><span class="mtk12">item</span><span class="mtk1">) </span><span class="mtk4">=&gt;</span><span class="mtk1"> ({</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> ...</span><span class="mtk12">item</span><span class="mtk1">,</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">isEdit:</span><span class="mtk1"> </span><span class="mtk4">false</span><span class="mtk1">,</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">isSelected:</span><span class="mtk1"> </span><span class="mtk4">false</span><span class="mtk1">,</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> })),</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">openDialog:</span><span class="mtk1"> </span><span class="mtk4">false</span><span class="mtk1">,</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> };</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> },</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">methods:</span><span class="mtk1"> {</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk11">editRowHandler</span><span class="mtk1">(</span><span class="mtk12">data</span><span class="mtk1">) {</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk4">this</span><span class="mtk1">.</span><span class="mtk12">tableItems</span><span class="mtk1">[</span><span class="mtk12">data</span><span class="mtk1">.</span><span class="mtk12">index</span><span class="mtk1">].</span><span class="mtk12">isEdit</span><span class="mtk1"> = !</span><span class="mtk4">this</span><span class="mtk1">.</span><span class="mtk12">tableItems</span><span class="mtk1">[</span><span class="mtk12">data</span><span class="mtk1">.</span><span class="mtk12">index</span><span class="mtk1">].</span><span class="mtk12">isEdit</span><span class="mtk1">;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> },</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk11">inputHandler</span><span class="mtk1">(</span><span class="mtk12">value</span><span class="mtk1">, </span><span class="mtk12">index</span><span class="mtk1">, </span><span class="mtk12">key</span><span class="mtk1">) {</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk4">this</span><span class="mtk1">.</span><span class="mtk12">tableItems</span><span class="mtk1">[</span><span class="mtk12">index</span><span class="mtk1">][</span><span class="mtk12">key</span><span class="mtk1">] = </span><span class="mtk12">value</span><span class="mtk1">;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk4">this</span><span class="mtk1">.</span><span class="mtk11">$set</span><span class="mtk1">(</span><span class="mtk4">this</span><span class="mtk1">.</span><span class="mtk12">tableItems</span><span class="mtk1">, </span><span class="mtk12">index</span><span class="mtk1">, </span><span class="mtk4">this</span><span class="mtk1">.</span><span class="mtk12">tableItems</span><span class="mtk1">[</span><span class="mtk12">index</span><span class="mtk1">]);</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk4">this</span><span class="mtk1">.</span><span class="mtk11">$emit</span><span class="mtk1">(</span><span class="mtk8">&quot;input&quot;</span><span class="mtk1">, </span><span class="mtk4">this</span><span class="mtk1">.</span><span class="mtk12">tableItems</span><span class="mtk1">);</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> },</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk11">addRowHandler</span><span class="mtk1">() {</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk4">const</span><span class="mtk1"> </span><span class="mtk12">newRow</span><span class="mtk1"> = </span><span class="mtk4">this</span><span class="mtk1">.</span><span class="mtk12">fields</span><span class="mtk1">.</span><span class="mtk11">reduce</span><span class="mtk1">(</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> (</span><span class="mtk12">a</span><span class="mtk1">, </span><span class="mtk12">c</span><span class="mtk1">) </span><span class="mtk4">=&gt;</span><span class="mtk1"> ({ ...</span><span class="mtk12">a</span><span class="mtk1">, </span><span class="mtk12">[c.key]:</span><span class="mtk1"> </span><span class="mtk4">null</span><span class="mtk1"> }),</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> {}</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> );</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">newRow</span><span class="mtk1">.</span><span class="mtk12">isEdit</span><span class="mtk1"> = </span><span class="mtk4">true</span><span class="mtk1">;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk4">this</span><span class="mtk1">.</span><span class="mtk12">tableItems</span><span class="mtk1">.</span><span class="mtk11">unshift</span><span class="mtk1">(</span><span class="mtk12">newRow</span><span class="mtk1">);</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk4">this</span><span class="mtk1">.</span><span class="mtk11">$emit</span><span class="mtk1">(</span><span class="mtk8">&quot;input&quot;</span><span class="mtk1">, </span><span class="mtk4">this</span><span class="mtk1">.</span><span class="mtk12">tableItems</span><span class="mtk1">);</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> },</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk11">removeRowHandler</span><span class="mtk1">(</span><span class="mtk12">index</span><span class="mtk1">) {</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk4">this</span><span class="mtk1">.</span><span class="mtk12">tableItems</span><span class="mtk1"> = </span><span class="mtk4">this</span><span class="mtk1">.</span><span class="mtk12">tableItems</span><span class="mtk1">.</span><span class="mtk11">filter</span><span class="mtk1">((</span><span class="mtk12">item</span><span class="mtk1">, </span><span class="mtk12">i</span><span class="mtk1">) </span><span class="mtk4">=&gt;</span><span class="mtk1"> </span><span class="mtk12">i</span><span class="mtk1"> !== </span><span class="mtk12">index</span><span class="mtk1">);</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk4">this</span><span class="mtk1">.</span><span class="mtk11">$emit</span><span class="mtk1">(</span><span class="mtk8">&quot;input&quot;</span><span class="mtk1">, </span><span class="mtk4">this</span><span class="mtk1">.</span><span class="mtk12">tableItems</span><span class="mtk1">);</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> },</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk11">removeRowsHandler</span><span class="mtk1">() {</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk4">this</span><span class="mtk1">.</span><span class="mtk12">tableItems</span><span class="mtk1"> = </span><span class="mtk4">this</span><span class="mtk1">.</span><span class="mtk12">tableItems</span><span class="mtk1">.</span><span class="mtk11">filter</span><span class="mtk1">((</span><span class="mtk12">item</span><span class="mtk1">) </span><span class="mtk4">=&gt;</span><span class="mtk1"> !</span><span class="mtk12">item</span><span class="mtk1">.</span><span class="mtk12">isSelected</span><span class="mtk1">);</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk4">this</span><span class="mtk1">.</span><span class="mtk11">$emit</span><span class="mtk1">(</span><span class="mtk8">&quot;input&quot;</span><span class="mtk1">, </span><span class="mtk4">this</span><span class="mtk1">.</span><span class="mtk12">tableItems</span><span class="mtk1">);</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> },</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk11">selectRowHandler</span><span class="mtk1">(</span><span class="mtk12">data</span><span class="mtk1">) {</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk4">this</span><span class="mtk1">.</span><span class="mtk12">tableItems</span><span class="mtk1">[</span><span class="mtk12">data</span><span class="mtk1">.</span><span class="mtk12">index</span><span class="mtk1">].</span><span class="mtk12">isSelected</span><span class="mtk1"> =</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> !</span><span class="mtk4">this</span><span class="mtk1">.</span><span class="mtk12">tableItems</span><span class="mtk1">[</span><span class="mtk12">data</span><span class="mtk1">.</span><span class="mtk12">index</span><span class="mtk1">].</span><span class="mtk12">isSelected</span><span class="mtk1">;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> },</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> },</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1">};</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk17">&lt;/</span><span class="mtk4">script</span><span class="mtk17">&gt;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk17">&lt;</span><span class="mtk4">style</span><span class="mtk17">&gt;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk6">.action-container</span><span class="mtk1"> {</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">margin-bottom</span><span class="mtk1">: </span><span class="mtk7">10px</span><span class="mtk1">;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1">}</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk6">.action-container</span><span class="mtk1"> </span><span class="mtk6">button</span><span class="mtk1"> {</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">margin-right</span><span class="mtk1">: </span><span class="mtk7">5px</span><span class="mtk1">;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1">}</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk6">.delete-button</span><span class="mtk1"> {</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">margin-left</span><span class="mtk1">: </span><span class="mtk7">5px</span><span class="mtk1">;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1">}</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk17">&lt;/</span><span class="mtk4">style</span><span class="mtk17">&gt;</span></span></span></code></pre> <h4 id="app-component" style="position:relative;"><a href="#app-component" aria-label="app component permalink" class="anchor before"><svg aria-hidden="true" focusable="false" height="16" version="1.1" viewBox="0 0 16 16" width="16"><path fill-rule="evenodd" d="M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z"></path></svg></a>App component</h4> <pre class="grvsc-container default-dark" data-language="html" data-index="1"><code class="grvsc-code"><span class="grvsc-line"><span class="grvsc-source"><span class="mtk17">&lt;</span><span class="mtk4">template</span><span class="mtk17">&gt;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk17">&lt;</span><span class="mtk4">div</span><span class="mtk1"> </span><span class="mtk12">id</span><span class="mtk1">=</span><span class="mtk8">&quot;app&quot;</span><span class="mtk17">&gt;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk17">&lt;</span><span class="mtk4">EditableTable</span><span class="mtk1"> </span><span class="mtk12">v-model</span><span class="mtk1">=</span><span class="mtk8">&quot;items&quot;</span><span class="mtk1"> </span><span class="mtk12">:fields</span><span class="mtk1">=</span><span class="mtk8">&quot;fields&quot;</span><span class="mtk17">&gt;&lt;/</span><span class="mtk4">EditableTable</span><span class="mtk17">&gt;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk17">&lt;/</span><span class="mtk4">div</span><span class="mtk17">&gt;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk17">&lt;/</span><span class="mtk4">template</span><span class="mtk17">&gt;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk17">&lt;</span><span class="mtk4">script</span><span class="mtk17">&gt;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk15">import</span><span class="mtk1"> </span><span class="mtk12">EditableTable</span><span class="mtk1"> </span><span class="mtk15">from</span><span class="mtk1"> </span><span class="mtk8">&#39;./components/EditableTable.vue&#39;</span><span class="mtk1">;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk15">export</span><span class="mtk1"> </span><span class="mtk15">default</span><span class="mtk1"> {</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">name:</span><span class="mtk1"> </span><span class="mtk8">&quot;App&quot;</span><span class="mtk1">,</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">components:</span><span class="mtk1"> {</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">EditableTable</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> },</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk11">data</span><span class="mtk1">() {</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk15">return</span><span class="mtk1"> {</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">fields:</span><span class="mtk1"> [</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> { </span><span class="mtk12">key:</span><span class="mtk1"> </span><span class="mtk8">&quot;selectRow&quot;</span><span class="mtk1">, </span><span class="mtk12">label:</span><span class="mtk1"> </span><span class="mtk8">&quot;&quot;</span><span class="mtk1"> },</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> { </span><span class="mtk12">key:</span><span class="mtk1"> </span><span class="mtk8">&quot;name&quot;</span><span class="mtk1">, </span><span class="mtk12">label:</span><span class="mtk1"> </span><span class="mtk8">&quot;Name&quot;</span><span class="mtk1">, </span><span class="mtk12">type:</span><span class="mtk1"> </span><span class="mtk8">&quot;text&quot;</span><span class="mtk1"> },</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> { </span><span class="mtk12">key:</span><span class="mtk1"> </span><span class="mtk8">&quot;department&quot;</span><span class="mtk1">, </span><span class="mtk12">label:</span><span class="mtk1"> </span><span class="mtk8">&quot;Department&quot;</span><span class="mtk1">, </span><span class="mtk12">type:</span><span class="mtk1"> </span><span class="mtk8">&quot;select&quot;</span><span class="mtk1">, </span><span class="mtk12">options:</span><span class="mtk1"> [</span><span class="mtk8">&#39;Development&#39;</span><span class="mtk1">, </span><span class="mtk8">&#39;Marketing&#39;</span><span class="mtk1">, </span><span class="mtk8">&#39;HR&#39;</span><span class="mtk1">, </span><span class="mtk8">&#39;Accounting&#39;</span><span class="mtk1">] },</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> { </span><span class="mtk12">key:</span><span class="mtk1"> </span><span class="mtk8">&quot;age&quot;</span><span class="mtk1">, </span><span class="mtk12">label:</span><span class="mtk1"> </span><span class="mtk8">&quot;Age&quot;</span><span class="mtk1">, </span><span class="mtk12">type:</span><span class="mtk1"> </span><span class="mtk8">&quot;number&quot;</span><span class="mtk1"> },</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> { </span><span class="mtk12">key:</span><span class="mtk1"> </span><span class="mtk8">&quot;dateOfBirth&quot;</span><span class="mtk1">, </span><span class="mtk12">label:</span><span class="mtk1"> </span><span class="mtk8">&quot;Date Of Birth&quot;</span><span class="mtk1">, </span><span class="mtk12">type:</span><span class="mtk1"> </span><span class="mtk8">&quot;date&quot;</span><span class="mtk1"> },</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> { </span><span class="mtk12">key:</span><span class="mtk1"> </span><span class="mtk8">&quot;edit&quot;</span><span class="mtk1">, </span><span class="mtk12">label:</span><span class="mtk1"> </span><span class="mtk8">&quot;&quot;</span><span class="mtk1">, </span><span class="mtk12">type:</span><span class="mtk1"> </span><span class="mtk8">&quot;edit&quot;</span><span class="mtk1"> }</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> ],</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">items:</span><span class="mtk1"> [</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> { </span><span class="mtk12">age:</span><span class="mtk1"> </span><span class="mtk7">40</span><span class="mtk1">, </span><span class="mtk12">name:</span><span class="mtk1"> </span><span class="mtk8">&#39;Dickerson&#39;</span><span class="mtk1">, </span><span class="mtk12">department:</span><span class="mtk1"> </span><span class="mtk8">&#39;Development&#39;</span><span class="mtk1">, </span><span class="mtk12">dateOfBirth:</span><span class="mtk1"> </span><span class="mtk8">&#39;1984-05-20&#39;</span><span class="mtk1"> },</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> { </span><span class="mtk12">age:</span><span class="mtk1"> </span><span class="mtk7">21</span><span class="mtk1">, </span><span class="mtk12">name:</span><span class="mtk1"> </span><span class="mtk8">&#39;Larsen&#39;</span><span class="mtk1">, </span><span class="mtk12">department:</span><span class="mtk1"> </span><span class="mtk8">&#39;Marketing&#39;</span><span class="mtk1">, </span><span class="mtk12">dateOfBirth:</span><span class="mtk1"> </span><span class="mtk8">&#39;1984-05-20&#39;</span><span class="mtk1"> },</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> { </span><span class="mtk12">age:</span><span class="mtk1"> </span><span class="mtk7">89</span><span class="mtk1">, </span><span class="mtk12">name:</span><span class="mtk1"> </span><span class="mtk8">&#39;Geneva&#39;</span><span class="mtk1">, </span><span class="mtk12">department:</span><span class="mtk1"> </span><span class="mtk8">&#39;HR&#39;</span><span class="mtk1">, </span><span class="mtk12">dateOfBirth:</span><span class="mtk1"> </span><span class="mtk8">&#39;1984-05-20&#39;</span><span class="mtk1"> },</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> { </span><span class="mtk12">age:</span><span class="mtk1"> </span><span class="mtk7">38</span><span class="mtk1">, </span><span class="mtk12">name:</span><span class="mtk1"> </span><span class="mtk8">&#39;Jami&#39;</span><span class="mtk1">, </span><span class="mtk12">department:</span><span class="mtk1"> </span><span class="mtk8">&#39;Accounting&#39;</span><span class="mtk1">, </span><span class="mtk12">dateOfBirth:</span><span class="mtk1"> </span><span class="mtk8">&#39;1984-05-20&#39;</span><span class="mtk1"> }</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> ]</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> };</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> }</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1">};</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk17">&lt;/</span><span class="mtk4">script</span><span class="mtk17">&gt;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk17">&lt;</span><span class="mtk4">style</span><span class="mtk17">&gt;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk6">#app</span><span class="mtk1"> {</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">margin</span><span class="mtk1">: </span><span class="mtk7">20px</span><span class="mtk1">;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1">}</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk17">&lt;/</span><span class="mtk4">style</span><span class="mtk17">&gt;</span></span></span></code></pre> <p><em>As we continue building upon the same code from previous parts in this series, it’s recommended that you go through these tutorials from the beginning to understand how the code structure works as we will not be explaining it here. You can navigate to any part using the table of contents.</em></p> <h2 id="load-data-with-rest-api" style="position:relative;"><a href="#load-data-with-rest-api" aria-label="load data with rest api permalink" class="anchor before"><svg aria-hidden="true" focusable="false" height="16" version="1.1" viewBox="0 0 16 16" width="16"><path fill-rule="evenodd" d="M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z"></path></svg></a>Load data with REST API</h2> <p>Since we already built a re-usable table with a dynamic schema in the <a href="https://muhimasri.com/blogs/part-2-create-a-dynamic-table-with-bootstrap-vue/">second part</a>, all we need to do is update the <code>fields</code> and <code>items</code> object with the new data source.</p> <p>Let’s go through the required steps:</p> <ol> <li>Create a new service folder with a <code>user.js</code> file, this will take care of all the API calls. We’ll add the first <code>GET</code> call using <code>fetch</code> in an <code>async</code> function:</li> </ol> <pre class="grvsc-container default-dark" data-language="javascript" data-index="2"><code class="grvsc-code"><span class="grvsc-line"><span class="grvsc-source"><span class="mtk15">export</span><span class="mtk1"> </span><span class="mtk4">const</span><span class="mtk1"> </span><span class="mtk11">getUsers</span><span class="mtk1"> = </span><span class="mtk4">async</span><span class="mtk1"> () </span><span class="mtk4">=&gt;</span><span class="mtk1"> {</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk4">const</span><span class="mtk1"> </span><span class="mtk12">response</span><span class="mtk1"> = </span><span class="mtk15">await</span><span class="mtk1"> </span><span class="mtk11">fetch</span><span class="mtk1">(</span><span class="mtk8">&#39;https://jsonplaceholder.typicode.com/users&#39;</span><span class="mtk1">);</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk4">const</span><span class="mtk1"> </span><span class="mtk12">users</span><span class="mtk1"> = </span><span class="mtk15">await</span><span class="mtk1"> </span><span class="mtk12">response</span><span class="mtk1">.</span><span class="mtk11">json</span><span class="mtk1">();</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk15">return</span><span class="mtk1"> </span><span class="mtk12">users</span><span class="mtk1">;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1">}</span></span></span></code></pre> <ol start="2"> <li>In <code>App.vue</code>, update the <code>fields</code> object with the new schema:</li> </ol> <pre class="grvsc-container default-dark" data-language="javascript" data-index="3"><code class="grvsc-code"><span class="grvsc-line"><span class="grvsc-source"><span class="mtk1">fields: [</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> { </span><span class="mtk12">key:</span><span class="mtk1"> </span><span class="mtk8">&quot;selectRow&quot;</span><span class="mtk1">, </span><span class="mtk12">label:</span><span class="mtk1"> </span><span class="mtk8">&quot;&quot;</span><span class="mtk1"> },</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> { </span><span class="mtk12">key:</span><span class="mtk1"> </span><span class="mtk8">&quot;name&quot;</span><span class="mtk1">, </span><span class="mtk12">label:</span><span class="mtk1"> </span><span class="mtk8">&quot;Name&quot;</span><span class="mtk1">, </span><span class="mtk12">type:</span><span class="mtk1"> </span><span class="mtk8">&quot;text&quot;</span><span class="mtk1"> },</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> { </span><span class="mtk12">key:</span><span class="mtk1"> </span><span class="mtk8">&quot;email&quot;</span><span class="mtk1">, </span><span class="mtk12">label:</span><span class="mtk1"> </span><span class="mtk8">&quot;Email&quot;</span><span class="mtk1">, </span><span class="mtk12">type:</span><span class="mtk1"> </span><span class="mtk8">&quot;email&quot;</span><span class="mtk1"> },</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> { </span><span class="mtk12">key:</span><span class="mtk1"> </span><span class="mtk8">&quot;phone&quot;</span><span class="mtk1">, </span><span class="mtk12">label:</span><span class="mtk1"> </span><span class="mtk8">&quot;Phone&quot;</span><span class="mtk1">, </span><span class="mtk12">type:</span><span class="mtk1"> </span><span class="mtk8">&quot;text&quot;</span><span class="mtk1"> },</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> { </span><span class="mtk12">key:</span><span class="mtk1"> </span><span class="mtk8">&quot;edit&quot;</span><span class="mtk1">, </span><span class="mtk12">label:</span><span class="mtk1"> </span><span class="mtk8">&quot;&quot;</span><span class="mtk1">, </span><span class="mtk12">type:</span><span class="mtk1"> </span><span class="mtk8">&quot;edit&quot;</span><span class="mtk1"> },</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> ]</span></span></span></code></pre> <ol start="3"> <li>In <code>App.vue</code>, call the <code>getUsers</code> function as soon as the component is rendered:</li> </ol> <pre class="grvsc-container default-dark" data-language="javascript" data-index="4"><code class="grvsc-code"><span class="grvsc-line"><span class="grvsc-source"><span class="mtk12">async</span><span class="mtk1"> </span><span class="mtk11">mounted</span><span class="mtk1">() {</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk4">this</span><span class="mtk1">.</span><span class="mtk12">users</span><span class="mtk1"> = </span><span class="mtk15">await</span><span class="mtk1"> </span><span class="mtk11">getUsers</span><span class="mtk1">();</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> }</span></span></span></code></pre> <p>Here is the full code:</p> <pre class="grvsc-container default-dark" data-language="html" data-index="5"><code class="grvsc-code"><span class="grvsc-line"><span class="grvsc-source"><span class="mtk17">&lt;</span><span class="mtk4">template</span><span class="mtk17">&gt;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk17">&lt;</span><span class="mtk4">div</span><span class="mtk1"> </span><span class="mtk12">id</span><span class="mtk1">=</span><span class="mtk8">&quot;app&quot;</span><span class="mtk17">&gt;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk17">&lt;</span><span class="mtk4">EditableTable</span><span class="mtk1"> </span><span class="mtk12">v-model</span><span class="mtk1">=</span><span class="mtk8">&quot;users&quot;</span><span class="mtk1"> </span><span class="mtk12">:fields</span><span class="mtk1">=</span><span class="mtk8">&quot;fields&quot;</span><span class="mtk17">&gt;&lt;/</span><span class="mtk4">EditableTable</span><span class="mtk17">&gt;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk17">&lt;/</span><span class="mtk4">div</span><span class="mtk17">&gt;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk17">&lt;/</span><span class="mtk4">template</span><span class="mtk17">&gt;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk17">&lt;</span><span class="mtk4">script</span><span class="mtk17">&gt;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk15">import</span><span class="mtk1"> </span><span class="mtk12">EditableTable</span><span class="mtk1"> </span><span class="mtk15">from</span><span class="mtk1"> </span><span class="mtk8">&quot;./components/EditableTable.vue&quot;</span><span class="mtk1">;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk15">import</span><span class="mtk1"> { </span><span class="mtk12">getUsers</span><span class="mtk1"> } </span><span class="mtk15">from</span><span class="mtk1"> </span><span class="mtk8">&quot;./services/user&quot;</span><span class="mtk1">;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk15">export</span><span class="mtk1"> </span><span class="mtk15">default</span><span class="mtk1"> {</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">name:</span><span class="mtk1"> </span><span class="mtk8">&quot;App&quot;</span><span class="mtk1">,</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">components:</span><span class="mtk1"> {</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">EditableTable</span><span class="mtk1">,</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> },</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk11">data</span><span class="mtk1">() {</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk15">return</span><span class="mtk1"> {</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">fields:</span><span class="mtk1"> [</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> { </span><span class="mtk12">key:</span><span class="mtk1"> </span><span class="mtk8">&quot;selectRow&quot;</span><span class="mtk1">, </span><span class="mtk12">label:</span><span class="mtk1"> </span><span class="mtk8">&quot;&quot;</span><span class="mtk1"> },</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> { </span><span class="mtk12">key:</span><span class="mtk1"> </span><span class="mtk8">&quot;name&quot;</span><span class="mtk1">, </span><span class="mtk12">label:</span><span class="mtk1"> </span><span class="mtk8">&quot;Name&quot;</span><span class="mtk1">, </span><span class="mtk12">type:</span><span class="mtk1"> </span><span class="mtk8">&quot;text&quot;</span><span class="mtk1"> },</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> { </span><span class="mtk12">key:</span><span class="mtk1"> </span><span class="mtk8">&quot;email&quot;</span><span class="mtk1">, </span><span class="mtk12">label:</span><span class="mtk1"> </span><span class="mtk8">&quot;Email&quot;</span><span class="mtk1">, </span><span class="mtk12">type:</span><span class="mtk1"> </span><span class="mtk8">&quot;email&quot;</span><span class="mtk1"> },</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> { </span><span class="mtk12">key:</span><span class="mtk1"> </span><span class="mtk8">&quot;phone&quot;</span><span class="mtk1">, </span><span class="mtk12">label:</span><span class="mtk1"> </span><span class="mtk8">&quot;Phone&quot;</span><span class="mtk1">, </span><span class="mtk12">type:</span><span class="mtk1"> </span><span class="mtk8">&quot;text&quot;</span><span class="mtk1"> },</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> { </span><span class="mtk12">key:</span><span class="mtk1"> </span><span class="mtk8">&quot;edit&quot;</span><span class="mtk1">, </span><span class="mtk12">label:</span><span class="mtk1"> </span><span class="mtk8">&quot;&quot;</span><span class="mtk1">, </span><span class="mtk12">type:</span><span class="mtk1"> </span><span class="mtk8">&quot;edit&quot;</span><span class="mtk1"> },</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> ],</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">users:</span><span class="mtk1"> [],</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> };</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> },</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk4">async</span><span class="mtk1"> </span><span class="mtk11">mounted</span><span class="mtk1">() {</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk4">this</span><span class="mtk1">.</span><span class="mtk12">users</span><span class="mtk1"> = </span><span class="mtk15">await</span><span class="mtk1"> </span><span class="mtk11">getUsers</span><span class="mtk1">();</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> }</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1">};</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk17">&lt;/</span><span class="mtk4">script</span><span class="mtk17">&gt;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk17">&lt;</span><span class="mtk4">style</span><span class="mtk17">&gt;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk6">#app</span><span class="mtk1"> {</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">margin</span><span class="mtk1">: </span><span class="mtk7">20px</span><span class="mtk1">;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1">}</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk17">&lt;/</span><span class="mtk4">style</span><span class="mtk17">&gt;</span></span></span></code></pre> <h2 id="watch-and-update-data" style="position:relative;"><a href="#watch-and-update-data" aria-label="watch and update data permalink" class="anchor before"><svg aria-hidden="true" focusable="false" height="16" version="1.1" viewBox="0 0 16 16" width="16"><path fill-rule="evenodd" d="M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z"></path></svg></a>Watch and update data</h2> <p>After running the code in the previous step, we’ll notice that the table is empty. Recall from previous parts that we created a reusable table component that has its’ own internal copy of the data, this was necessary in order to edit and select rows. Because of that, when updating the <code>items</code> object, the table will not update the internal copy of the data automatically.</p> <p>This can be easily fixed by adding a watcher in <code>EditableTable.vue</code> and updating <code>tableItems</code> when change is detected:</p> <pre class="grvsc-container default-dark" data-language="javascript" data-index="6"><code class="grvsc-code"><span class="grvsc-line"><span class="grvsc-source"><span class="mtk1">watch: {</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk11">value</span><span class="mtk1">(</span><span class="mtk12">newVal</span><span class="mtk1">) {</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk4">this</span><span class="mtk1">.</span><span class="mtk12">tableItems</span><span class="mtk1"> = </span><span class="mtk4">this</span><span class="mtk1">.</span><span class="mtk11">mapItems</span><span class="mtk1">(</span><span class="mtk12">newVal</span><span class="mtk1">);</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> },</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> },</span></span></span></code></pre> <p><code>mapItems()</code> is a shared method used to add and maintain additional properties such as <code>isEdit</code> and <code>isSelected</code></p> <pre class="grvsc-container default-dark" data-language="javascript" data-index="7"><code class="grvsc-code"><span class="grvsc-line"><span class="grvsc-source"><span class="mtk11">mapItems</span><span class="mtk1">(</span><span class="mtk12">data</span><span class="mtk1">) {</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk15">return</span><span class="mtk1"> </span><span class="mtk12">data</span><span class="mtk1">.</span><span class="mtk11">map</span><span class="mtk1">((</span><span class="mtk12">item</span><span class="mtk1">, </span><span class="mtk12">index</span><span class="mtk1">) </span><span class="mtk4">=&gt;</span><span class="mtk1"> ({</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> ...</span><span class="mtk12">item</span><span class="mtk1">,</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">isEdit:</span><span class="mtk1"> </span><span class="mtk4">this</span><span class="mtk1">.</span><span class="mtk12">tableItems</span><span class="mtk1">[</span><span class="mtk12">index</span><span class="mtk1">] ? </span><span class="mtk4">this</span><span class="mtk1">.</span><span class="mtk12">tableItems</span><span class="mtk1">[</span><span class="mtk12">index</span><span class="mtk1">].</span><span class="mtk12">isEdit</span><span class="mtk1"> : </span><span class="mtk4">false</span><span class="mtk1">,</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">isSelected:</span><span class="mtk1"> </span><span class="mtk4">this</span><span class="mtk1">.</span><span class="mtk12">tableItems</span><span class="mtk1">[</span><span class="mtk12">index</span><span class="mtk1">] ? </span><span class="mtk4">this</span><span class="mtk1">.</span><span class="mtk12">tableItems</span><span class="mtk1">[</span><span class="mtk12">index</span><span class="mtk1">].</span><span class="mtk12">isSelected</span><span class="mtk1"> : </span><span class="mtk4">false</span><span class="mtk1">,</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> }))</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> }</span></span></span></code></pre> <p>Since the watcher will be triggered when the user is changing the input field, line 4 and 5 ensures that existing rows will remain editable and/or selected.</p> <p>Here is the full update to the <code>EditableTable.vue</code> component:</p> <pre class="grvsc-container default-dark" data-language="html" data-index="8"><code class="grvsc-code"><span class="grvsc-line"><span class="grvsc-source"><span class="mtk17">&lt;</span><span class="mtk4">template</span><span class="mtk17">&gt;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk17">&lt;</span><span class="mtk4">article</span><span class="mtk17">&gt;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk17">&lt;</span><span class="mtk4">b-modal</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">id</span><span class="mtk1">=</span><span class="mtk8">&quot;modal-1&quot;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">title</span><span class="mtk1">=</span><span class="mtk8">&quot;Confirm&quot;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">v-model</span><span class="mtk1">=</span><span class="mtk8">&quot;openDialog&quot;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">ok-title</span><span class="mtk1">=</span><span class="mtk8">&quot;Remove&quot;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">@ok</span><span class="mtk1">=</span><span class="mtk8">&quot;removeRowsHandler&quot;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk17">&gt;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk17">&lt;</span><span class="mtk4">p</span><span class="mtk1"> </span><span class="mtk12">class</span><span class="mtk1">=</span><span class="mtk8">&quot;my-4&quot;</span><span class="mtk17">&gt;</span><span class="mtk1">Are you sure you want to remove the selected rows?</span><span class="mtk17">&lt;/</span><span class="mtk4">p</span><span class="mtk17">&gt;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk17">&lt;/</span><span class="mtk4">b-modal</span><span class="mtk17">&gt;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk17">&lt;</span><span class="mtk4">div</span><span class="mtk1"> </span><span class="mtk12">class</span><span class="mtk1">=</span><span class="mtk8">&quot;action-container&quot;</span><span class="mtk17">&gt;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk17">&lt;</span><span class="mtk4">b-button</span><span class="mtk1"> </span><span class="mtk12">class</span><span class="mtk1">=</span><span class="mtk8">&quot;add-button&quot;</span><span class="mtk1"> </span><span class="mtk12">variant</span><span class="mtk1">=</span><span class="mtk8">&quot;success&quot;</span><span class="mtk1"> </span><span class="mtk12">@click</span><span class="mtk1">=</span><span class="mtk8">&quot;addRowHandler&quot;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk17">&gt;</span><span class="mtk1">Add Row</span><span class="mtk17">&lt;/</span><span class="mtk4">b-button</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk17">&gt;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk17">&lt;</span><span class="mtk4">b-button</span><span class="mtk1"> </span><span class="mtk12">variant</span><span class="mtk1">=</span><span class="mtk8">&quot;danger&quot;</span><span class="mtk1"> </span><span class="mtk12">@click</span><span class="mtk1">=</span><span class="mtk8">&quot;openDialog = true&quot;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk17">&gt;</span><span class="mtk1">Remove Rows</span><span class="mtk17">&lt;/</span><span class="mtk4">b-button</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk17">&gt;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk17">&lt;/</span><span class="mtk4">div</span><span class="mtk17">&gt;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk17">&lt;</span><span class="mtk4">b-table</span><span class="mtk1"> </span><span class="mtk12">class</span><span class="mtk1">=</span><span class="mtk8">&quot;b-table&quot;</span><span class="mtk1"> </span><span class="mtk12">:items</span><span class="mtk1">=</span><span class="mtk8">&quot;tableItems&quot;</span><span class="mtk1"> </span><span class="mtk12">:fields</span><span class="mtk1">=</span><span class="mtk8">&quot;fields&quot;</span><span class="mtk1"> </span><span class="mtk12">fixed</span><span class="mtk17">&gt;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk17">&lt;</span><span class="mtk4">template</span><span class="mtk1"> </span><span class="mtk12">v-for</span><span class="mtk1">=</span><span class="mtk8">&quot;(field, index) in fields&quot;</span><span class="mtk1"> </span><span class="mtk12">#[`cell(${field.key})`]</span><span class="mtk1">=</span><span class="mtk8">&quot;data&quot;</span><span class="mtk17">&gt;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk17">&lt;</span><span class="mtk4">b-form-datepicker</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">v-if</span><span class="mtk1">=</span><span class="mtk8">&quot;field.type === &#39;date&#39; &amp;&amp; tableItems[data.index].isEdit&quot;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">:key</span><span class="mtk1">=</span><span class="mtk8">&quot;index&quot;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">:type</span><span class="mtk1">=</span><span class="mtk8">&quot;field.type&quot;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">:value</span><span class="mtk1">=</span><span class="mtk8">&quot;tableItems[data.index][field.key]&quot;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">@input</span><span class="mtk1">=</span><span class="mtk8">&quot;(value) =&gt; inputHandler(value, data.index, field.key)&quot;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk17">&gt;&lt;/</span><span class="mtk4">b-form-datepicker</span><span class="mtk17">&gt;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk17">&lt;</span><span class="mtk4">b-form-select</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">v-else-if</span><span class="mtk1">=</span><span class="mtk8">&quot;field.type === &#39;select&#39; &amp;&amp; tableItems[data.index].isEdit&quot;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">:key</span><span class="mtk1">=</span><span class="mtk8">&quot;index&quot;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">:value</span><span class="mtk1">=</span><span class="mtk8">&quot;tableItems[data.index][field.key]&quot;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">@input</span><span class="mtk1">=</span><span class="mtk8">&quot;(value) =&gt; inputHandler(value, data.index, field.key)&quot;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">:options</span><span class="mtk1">=</span><span class="mtk8">&quot;field.options&quot;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk17">&gt;&lt;/</span><span class="mtk4">b-form-select</span><span class="mtk17">&gt;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk17">&lt;</span><span class="mtk4">b-checkbox</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">v-else-if</span><span class="mtk1">=</span><span class="mtk8">&quot;field.key === &#39;selectRow&#39;&quot;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">:checked</span><span class="mtk1">=</span><span class="mtk8">&quot;tableItems[data.index].isSelected&quot;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">:key</span><span class="mtk1">=</span><span class="mtk8">&quot;index&quot;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">@change</span><span class="mtk1">=</span><span class="mtk8">&quot;selectRowHandler(data)&quot;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk17">&gt;&lt;/</span><span class="mtk4">b-checkbox</span><span class="mtk17">&gt;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk17">&lt;</span><span class="mtk4">div</span><span class="mtk1"> </span><span class="mtk12">:key</span><span class="mtk1">=</span><span class="mtk8">&quot;index&quot;</span><span class="mtk1"> </span><span class="mtk12">v-else-if</span><span class="mtk1">=</span><span class="mtk8">&quot;field.type === &#39;edit&#39;&quot;</span><span class="mtk17">&gt;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk17">&lt;</span><span class="mtk4">b-button</span><span class="mtk1"> </span><span class="mtk12">@click</span><span class="mtk1">=</span><span class="mtk8">&quot;editRowHandler(data)&quot;</span><span class="mtk17">&gt;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk17">&lt;</span><span class="mtk4">span</span><span class="mtk1"> </span><span class="mtk12">v-if</span><span class="mtk1">=</span><span class="mtk8">&quot;!tableItems[data.index].isEdit&quot;</span><span class="mtk17">&gt;</span><span class="mtk1">Edit</span><span class="mtk17">&lt;/</span><span class="mtk4">span</span><span class="mtk17">&gt;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk17">&lt;</span><span class="mtk4">span</span><span class="mtk1"> </span><span class="mtk12">v-else</span><span class="mtk17">&gt;</span><span class="mtk1">Done</span><span class="mtk17">&lt;/</span><span class="mtk4">span</span><span class="mtk17">&gt;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk17">&lt;/</span><span class="mtk4">b-button</span><span class="mtk17">&gt;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk17">&lt;</span><span class="mtk4">b-button</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">class</span><span class="mtk1">=</span><span class="mtk8">&quot;delete-button&quot;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">variant</span><span class="mtk1">=</span><span class="mtk8">&quot;danger&quot;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">@click</span><span class="mtk1">=</span><span class="mtk8">&quot;removeRowHandler(data.index)&quot;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk17">&gt;</span><span class="mtk1">Remove</span><span class="mtk17">&lt;/</span><span class="mtk4">b-button</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk17">&gt;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk17">&lt;/</span><span class="mtk4">div</span><span class="mtk17">&gt;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk17">&lt;</span><span class="mtk4">b-form-input</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">v-else-if</span><span class="mtk1">=</span><span class="mtk8">&quot;field.type &amp;&amp; tableItems[data.index].isEdit&quot;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">:key</span><span class="mtk1">=</span><span class="mtk8">&quot;index&quot;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">:type</span><span class="mtk1">=</span><span class="mtk8">&quot;field.type&quot;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">:value</span><span class="mtk1">=</span><span class="mtk8">&quot;tableItems[data.index][field.key]&quot;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">@blur</span><span class="mtk1">=</span><span class="mtk8">&quot;(e) =&gt; inputHandler(e.target.value, data.index, field.key)&quot;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk17">&gt;&lt;/</span><span class="mtk4">b-form-input</span><span class="mtk17">&gt;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk17">&lt;</span><span class="mtk4">span</span><span class="mtk1"> </span><span class="mtk12">:key</span><span class="mtk1">=</span><span class="mtk8">&quot;index&quot;</span><span class="mtk1"> </span><span class="mtk12">v-else</span><span class="mtk17">&gt;</span><span class="mtk1">{{ data.value }}</span><span class="mtk17">&lt;/</span><span class="mtk4">span</span><span class="mtk17">&gt;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk17">&lt;/</span><span class="mtk4">template</span><span class="mtk17">&gt;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk17">&lt;/</span><span class="mtk4">b-table</span><span class="mtk17">&gt;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk17">&lt;/</span><span class="mtk4">article</span><span class="mtk17">&gt;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk17">&lt;/</span><span class="mtk4">template</span><span class="mtk17">&gt;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk17">&lt;</span><span class="mtk4">script</span><span class="mtk17">&gt;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk15">export</span><span class="mtk1"> </span><span class="mtk15">default</span><span class="mtk1"> {</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">name:</span><span class="mtk1"> </span><span class="mtk8">&quot;EditableTable&quot;</span><span class="mtk1">,</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">components:</span><span class="mtk1"> {},</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">props:</span><span class="mtk1"> {</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">value:</span><span class="mtk1"> </span><span class="mtk10">Array</span><span class="mtk1">,</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">fields:</span><span class="mtk1"> </span><span class="mtk10">Array</span><span class="mtk1">,</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> },</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk11">data</span><span class="mtk1">() {</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk15">return</span><span class="mtk1"> {</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">tableItems:</span><span class="mtk1"> </span><span class="mtk4">this</span><span class="mtk1">.</span><span class="mtk11">mapItems</span><span class="mtk1">(</span><span class="mtk4">this</span><span class="mtk1">.</span><span class="mtk12">value</span><span class="mtk1">),</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">openDialog:</span><span class="mtk1"> </span><span class="mtk4">false</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> };</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> },</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">watch:</span><span class="mtk1"> {</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk11">value</span><span class="mtk1">(</span><span class="mtk12">newVal</span><span class="mtk1">) {</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk4">this</span><span class="mtk1">.</span><span class="mtk12">tableItems</span><span class="mtk1"> = </span><span class="mtk4">this</span><span class="mtk1">.</span><span class="mtk11">mapItems</span><span class="mtk1">(</span><span class="mtk12">newVal</span><span class="mtk1">);</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> },</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> },</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">methods:</span><span class="mtk1"> {</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk11">editRowHandler</span><span class="mtk1">(</span><span class="mtk12">data</span><span class="mtk1">) {</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk4">this</span><span class="mtk1">.</span><span class="mtk12">tableItems</span><span class="mtk1">[</span><span class="mtk12">data</span><span class="mtk1">.</span><span class="mtk12">index</span><span class="mtk1">].</span><span class="mtk12">isEdit</span><span class="mtk1"> = !</span><span class="mtk4">this</span><span class="mtk1">.</span><span class="mtk12">tableItems</span><span class="mtk1">[</span><span class="mtk12">data</span><span class="mtk1">.</span><span class="mtk12">index</span><span class="mtk1">].</span><span class="mtk12">isEdit</span><span class="mtk1">;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> },</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk11">inputHandler</span><span class="mtk1">(</span><span class="mtk12">value</span><span class="mtk1">, </span><span class="mtk12">index</span><span class="mtk1">, </span><span class="mtk12">key</span><span class="mtk1">) {</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk4">this</span><span class="mtk1">.</span><span class="mtk12">tableItems</span><span class="mtk1">[</span><span class="mtk12">index</span><span class="mtk1">][</span><span class="mtk12">key</span><span class="mtk1">] = </span><span class="mtk12">value</span><span class="mtk1">;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk4">this</span><span class="mtk1">.</span><span class="mtk11">$set</span><span class="mtk1">(</span><span class="mtk4">this</span><span class="mtk1">.</span><span class="mtk12">tableItems</span><span class="mtk1">, </span><span class="mtk12">index</span><span class="mtk1">, </span><span class="mtk4">this</span><span class="mtk1">.</span><span class="mtk12">tableItems</span><span class="mtk1">[</span><span class="mtk12">index</span><span class="mtk1">]);</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk4">this</span><span class="mtk1">.</span><span class="mtk11">$emit</span><span class="mtk1">(</span><span class="mtk8">&quot;input&quot;</span><span class="mtk1">, </span><span class="mtk4">this</span><span class="mtk1">.</span><span class="mtk12">tableItems</span><span class="mtk1">);</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> },</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk11">addRowHandler</span><span class="mtk1">() {</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk4">const</span><span class="mtk1"> </span><span class="mtk12">newRow</span><span class="mtk1"> = </span><span class="mtk4">this</span><span class="mtk1">.</span><span class="mtk12">fields</span><span class="mtk1">.</span><span class="mtk11">reduce</span><span class="mtk1">(</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> (</span><span class="mtk12">a</span><span class="mtk1">, </span><span class="mtk12">c</span><span class="mtk1">) </span><span class="mtk4">=&gt;</span><span class="mtk1"> ({ ...</span><span class="mtk12">a</span><span class="mtk1">, </span><span class="mtk12">[c.key]:</span><span class="mtk1"> </span><span class="mtk4">null</span><span class="mtk1"> }),</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> {}</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> );</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">newRow</span><span class="mtk1">.</span><span class="mtk12">isEdit</span><span class="mtk1"> = </span><span class="mtk4">true</span><span class="mtk1">;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk4">this</span><span class="mtk1">.</span><span class="mtk12">tableItems</span><span class="mtk1">.</span><span class="mtk11">unshift</span><span class="mtk1">(</span><span class="mtk12">newRow</span><span class="mtk1">);</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk4">this</span><span class="mtk1">.</span><span class="mtk11">$emit</span><span class="mtk1">(</span><span class="mtk8">&quot;input&quot;</span><span class="mtk1">, </span><span class="mtk4">this</span><span class="mtk1">.</span><span class="mtk12">tableItems</span><span class="mtk1">);</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> },</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk11">removeRowHandler</span><span class="mtk1">(</span><span class="mtk12">index</span><span class="mtk1">) {</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk4">this</span><span class="mtk1">.</span><span class="mtk12">tableItems</span><span class="mtk1"> = </span><span class="mtk4">this</span><span class="mtk1">.</span><span class="mtk12">tableItems</span><span class="mtk1">.</span><span class="mtk11">filter</span><span class="mtk1">((</span><span class="mtk12">item</span><span class="mtk1">, </span><span class="mtk12">i</span><span class="mtk1">) </span><span class="mtk4">=&gt;</span><span class="mtk1"> </span><span class="mtk12">i</span><span class="mtk1"> !== </span><span class="mtk12">index</span><span class="mtk1">);</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk4">this</span><span class="mtk1">.</span><span class="mtk11">$emit</span><span class="mtk1">(</span><span class="mtk8">&quot;input&quot;</span><span class="mtk1">, </span><span class="mtk4">this</span><span class="mtk1">.</span><span class="mtk12">tableItems</span><span class="mtk1">);</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> },</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk11">removeRowsHandler</span><span class="mtk1">() {</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk4">this</span><span class="mtk1">.</span><span class="mtk12">tableItems</span><span class="mtk1"> = </span><span class="mtk4">this</span><span class="mtk1">.</span><span class="mtk12">tableItems</span><span class="mtk1">.</span><span class="mtk11">filter</span><span class="mtk1">((</span><span class="mtk12">item</span><span class="mtk1">) </span><span class="mtk4">=&gt;</span><span class="mtk1"> !</span><span class="mtk12">item</span><span class="mtk1">.</span><span class="mtk12">isSelected</span><span class="mtk1">);</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk4">this</span><span class="mtk1">.</span><span class="mtk11">$emit</span><span class="mtk1">(</span><span class="mtk8">&quot;input&quot;</span><span class="mtk1">, </span><span class="mtk4">this</span><span class="mtk1">.</span><span class="mtk12">tableItems</span><span class="mtk1">);</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> },</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk11">selectRowHandler</span><span class="mtk1">(</span><span class="mtk12">data</span><span class="mtk1">) {</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk4">this</span><span class="mtk1">.</span><span class="mtk12">tableItems</span><span class="mtk1">[</span><span class="mtk12">data</span><span class="mtk1">.</span><span class="mtk12">index</span><span class="mtk1">].</span><span class="mtk12">isSelected</span><span class="mtk1"> =</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> !</span><span class="mtk4">this</span><span class="mtk1">.</span><span class="mtk12">tableItems</span><span class="mtk1">[</span><span class="mtk12">data</span><span class="mtk1">.</span><span class="mtk12">index</span><span class="mtk1">].</span><span class="mtk12">isSelected</span><span class="mtk1">;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> },</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk11">mapItems</span><span class="mtk1">(</span><span class="mtk12">data</span><span class="mtk1">) {</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk15">return</span><span class="mtk1"> </span><span class="mtk12">data</span><span class="mtk1">.</span><span class="mtk11">map</span><span class="mtk1">((</span><span class="mtk12">item</span><span class="mtk1">, </span><span class="mtk12">index</span><span class="mtk1">) </span><span class="mtk4">=&gt;</span><span class="mtk1"> ({</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> ...</span><span class="mtk12">item</span><span class="mtk1">,</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">isEdit:</span><span class="mtk1"> </span><span class="mtk4">this</span><span class="mtk1">.</span><span class="mtk12">tableItems</span><span class="mtk1">[</span><span class="mtk12">index</span><span class="mtk1">] ? </span><span class="mtk4">this</span><span class="mtk1">.</span><span class="mtk12">tableItems</span><span class="mtk1">[</span><span class="mtk12">index</span><span class="mtk1">].</span><span class="mtk12">isEdit</span><span class="mtk1"> : </span><span class="mtk4">false</span><span class="mtk1">,</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">isSelected:</span><span class="mtk1"> </span><span class="mtk4">this</span><span class="mtk1">.</span><span class="mtk12">tableItems</span><span class="mtk1">[</span><span class="mtk12">index</span><span class="mtk1">] ? </span><span class="mtk4">this</span><span class="mtk1">.</span><span class="mtk12">tableItems</span><span class="mtk1">[</span><span class="mtk12">index</span><span class="mtk1">].</span><span class="mtk12">isSelected</span><span class="mtk1"> : </span><span class="mtk4">false</span><span class="mtk1">,</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> }))</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> }</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> },</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1">};</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk17">&lt;/</span><span class="mtk4">script</span><span class="mtk17">&gt;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk17">&lt;</span><span class="mtk4">style</span><span class="mtk17">&gt;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk6">.action-container</span><span class="mtk1"> {</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">margin-bottom</span><span class="mtk1">: </span><span class="mtk7">10px</span><span class="mtk1">;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1">}</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk6">.action-container</span><span class="mtk1"> </span><span class="mtk6">button</span><span class="mtk1"> {</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">margin-right</span><span class="mtk1">: </span><span class="mtk7">5px</span><span class="mtk1">;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1">}</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk6">.delete-button</span><span class="mtk1"> {</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">margin-left</span><span class="mtk1">: </span><span class="mtk7">5px</span><span class="mtk1">;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1">}</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk17">&lt;/</span><span class="mtk4">style</span><span class="mtk17">&gt;</span></span></span></code></pre> <h2 id="update-a-row-with-rest-api" style="position:relative;"><a href="#update-a-row-with-rest-api" aria-label="update a row with rest api permalink" class="anchor before"><svg aria-hidden="true" focusable="false" height="16" version="1.1" viewBox="0 0 16 16" width="16"><path fill-rule="evenodd" d="M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z"></path></svg></a>Update a row with REST API</h2> <p>A <code>PATCH</code> API service is usually the most suitable operation for updating data. Let’s add a new <code>updateUser</code> function in the <code>user.js</code> service that does the following:</p> <ul> <li>Attach the user id to the service URL</li> <li>Pass the user object as a parameter</li> <li>Return updated results</li> </ul> <pre class="grvsc-container default-dark" data-language="javascript" data-index="9"><code class="grvsc-code"><span class="grvsc-line"><span class="grvsc-source"><span class="mtk15">export</span><span class="mtk1"> </span><span class="mtk4">const</span><span class="mtk1"> </span><span class="mtk11">updateUser</span><span class="mtk1"> = </span><span class="mtk4">async</span><span class="mtk1"> (</span><span class="mtk12">user</span><span class="mtk1">) </span><span class="mtk4">=&gt;</span><span class="mtk1"> {</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk4">const</span><span class="mtk1"> </span><span class="mtk12">response</span><span class="mtk1"> = </span><span class="mtk15">await</span><span class="mtk1"> </span><span class="mtk11">fetch</span><span class="mtk1">(</span><span class="mtk8">`https://jsonplaceholder.typicode.com/users/</span><span class="mtk4">${</span><span class="mtk12">user</span><span class="mtk1">.</span><span class="mtk12">id</span><span class="mtk4">}</span><span class="mtk8">`</span><span class="mtk1">, {</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">method:</span><span class="mtk1"> </span><span class="mtk8">&#39;PATCH&#39;</span><span class="mtk1">,</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">body:</span><span class="mtk1"> </span><span class="mtk10">JSON</span><span class="mtk1">.</span><span class="mtk11">stringify</span><span class="mtk1">(</span><span class="mtk12">user</span><span class="mtk1">)</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> });</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk4">const</span><span class="mtk1"> </span><span class="mtk12">result</span><span class="mtk1"> = </span><span class="mtk15">await</span><span class="mtk1"> </span><span class="mtk12">response</span><span class="mtk1">.</span><span class="mtk11">json</span><span class="mtk1">();</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk15">return</span><span class="mtk1"> </span><span class="mtk12">result</span><span class="mtk1">;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1">}</span></span></span></code></pre> <p>Now, to consume the function and update the edited user, we have to make two modifications:</p> <ol> <li>In <code>EditableTable.vue</code> emit an event when the “done” button is clicked, this can be added to the <code>editRowHandler</code> function. Also, we have to emit only when the row is on edit mode so that we don’t save on “cancel” or “edit” click:</li> </ol> <pre class="grvsc-container grvsc-has-line-highlighting default-dark" data-language="javascript" data-index="10"><code class="grvsc-code"><span class="grvsc-line"><span class="grvsc-source"><span class="mtk11">editRowHandler</span><span class="mtk1">(</span><span class="mtk12">data</span><span class="mtk1">) {</span></span></span> <span class="grvsc-line grvsc-line-highlighted"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk15">if</span><span class="mtk1"> (</span><span class="mtk4">this</span><span class="mtk1">.</span><span class="mtk12">tableItems</span><span class="mtk1">[</span><span class="mtk12">data</span><span class="mtk1">.</span><span class="mtk12">index</span><span class="mtk1">].</span><span class="mtk12">isEdit</span><span class="mtk1">) {</span></span></span> <span class="grvsc-line grvsc-line-highlighted"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk4">this</span><span class="mtk1">.</span><span class="mtk11">$emit</span><span class="mtk1">(</span><span class="mtk8">&quot;submit&quot;</span><span class="mtk1">, </span><span class="mtk4">this</span><span class="mtk1">.</span><span class="mtk12">tableItems</span><span class="mtk1">[</span><span class="mtk12">data</span><span class="mtk1">.</span><span class="mtk12">index</span><span class="mtk1">]);</span></span></span> <span class="grvsc-line grvsc-line-highlighted"><span class="grvsc-source"><span class="mtk1"> }</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk4">this</span><span class="mtk1">.</span><span class="mtk12">tableItems</span><span class="mtk1">[</span><span class="mtk12">data</span><span class="mtk1">.</span><span class="mtk12">index</span><span class="mtk1">].</span><span class="mtk12">isEdit</span><span class="mtk1"> = !</span><span class="mtk4">this</span><span class="mtk1">.</span><span class="mtk12">tableItems</span><span class="mtk1">[</span><span class="mtk12">data</span><span class="mtk1">.</span><span class="mtk12">index</span><span class="mtk1">].</span><span class="mtk12">isEdit</span><span class="mtk1">;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1">}</span></span></span></code></pre> <ol start="2"> <li>In <code>App.vue</code> add an event handler to trigger the update user service:</li> </ol> <pre class="grvsc-container grvsc-has-line-highlighting default-dark" data-language="html" data-index="11"><code class="grvsc-code"><span class="grvsc-line"><span class="grvsc-source"><span class="mtk17">&lt;</span><span class="mtk4">template</span><span class="mtk17">&gt;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk17">&lt;</span><span class="mtk4">div</span><span class="mtk1"> </span><span class="mtk12">id</span><span class="mtk1">=</span><span class="mtk8">&quot;app&quot;</span><span class="mtk17">&gt;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk17">&lt;</span><span class="mtk4">EditableTable</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">v-model</span><span class="mtk1">=</span><span class="mtk8">&quot;users&quot;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">:fields</span><span class="mtk1">=</span><span class="mtk8">&quot;fields&quot;</span></span></span> <span class="grvsc-line grvsc-line-highlighted"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">@submit</span><span class="mtk1">=</span><span class="mtk8">&quot;handleUpdateUser($event)&quot;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk17">&gt;&lt;/</span><span class="mtk4">EditableTable</span><span class="mtk17">&gt;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk17">&lt;</span><span class="mtk4">pre</span><span class="mtk17">&gt;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> {{ users }}</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk17">&lt;/</span><span class="mtk4">pre</span><span class="mtk17">&gt;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk17">&lt;/</span><span class="mtk4">div</span><span class="mtk17">&gt;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk17">&lt;/</span><span class="mtk4">template</span><span class="mtk17">&gt;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk17">&lt;</span><span class="mtk4">script</span><span class="mtk17">&gt;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk15">import</span><span class="mtk1"> </span><span class="mtk12">EditableTable</span><span class="mtk1"> </span><span class="mtk15">from</span><span class="mtk1"> </span><span class="mtk8">&quot;./components/EditableTable.vue&quot;</span><span class="mtk1">;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk15">import</span><span class="mtk1"> { </span><span class="mtk12">getUsers</span><span class="mtk1">, </span><span class="mtk12">updateUser</span><span class="mtk1"> } </span><span class="mtk15">from</span><span class="mtk1"> </span><span class="mtk8">&quot;./services/user&quot;</span><span class="mtk1">;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk15">export</span><span class="mtk1"> </span><span class="mtk15">default</span><span class="mtk1"> {</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">name:</span><span class="mtk1"> </span><span class="mtk8">&quot;App&quot;</span><span class="mtk1">,</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">components:</span><span class="mtk1"> {</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">EditableTable</span><span class="mtk1">,</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> },</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk11">data</span><span class="mtk1">() {</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk15">return</span><span class="mtk1"> {</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">fields:</span><span class="mtk1"> [</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> { </span><span class="mtk12">key:</span><span class="mtk1"> </span><span class="mtk8">&quot;selectRow&quot;</span><span class="mtk1">, </span><span class="mtk12">label:</span><span class="mtk1"> </span><span class="mtk8">&quot;&quot;</span><span class="mtk1"> },</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> { </span><span class="mtk12">key:</span><span class="mtk1"> </span><span class="mtk8">&quot;name&quot;</span><span class="mtk1">, </span><span class="mtk12">label:</span><span class="mtk1"> </span><span class="mtk8">&quot;Name&quot;</span><span class="mtk1">, </span><span class="mtk12">type:</span><span class="mtk1"> </span><span class="mtk8">&quot;text&quot;</span><span class="mtk1"> },</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> { </span><span class="mtk12">key:</span><span class="mtk1"> </span><span class="mtk8">&quot;email&quot;</span><span class="mtk1">, </span><span class="mtk12">label:</span><span class="mtk1"> </span><span class="mtk8">&quot;Email&quot;</span><span class="mtk1">, </span><span class="mtk12">type:</span><span class="mtk1"> </span><span class="mtk8">&quot;email&quot;</span><span class="mtk1"> },</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> { </span><span class="mtk12">key:</span><span class="mtk1"> </span><span class="mtk8">&quot;phone&quot;</span><span class="mtk1">, </span><span class="mtk12">label:</span><span class="mtk1"> </span><span class="mtk8">&quot;Phone&quot;</span><span class="mtk1">, </span><span class="mtk12">type:</span><span class="mtk1"> </span><span class="mtk8">&quot;text&quot;</span><span class="mtk1"> },</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> { </span><span class="mtk12">key:</span><span class="mtk1"> </span><span class="mtk8">&quot;edit&quot;</span><span class="mtk1">, </span><span class="mtk12">label:</span><span class="mtk1"> </span><span class="mtk8">&quot;&quot;</span><span class="mtk1">, </span><span class="mtk12">type:</span><span class="mtk1"> </span><span class="mtk8">&quot;edit&quot;</span><span class="mtk1"> },</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> ],</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">users:</span><span class="mtk1"> [],</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> };</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> },</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk4">async</span><span class="mtk1"> </span><span class="mtk11">mounted</span><span class="mtk1">() {</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk4">this</span><span class="mtk1">.</span><span class="mtk12">users</span><span class="mtk1"> = </span><span class="mtk15">await</span><span class="mtk1"> </span><span class="mtk11">getUsers</span><span class="mtk1">();</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> },</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">methods:</span><span class="mtk1"> {</span></span></span> <span class="grvsc-line grvsc-line-highlighted"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk4">async</span><span class="mtk1"> </span><span class="mtk11">handleUpdateUser</span><span class="mtk1">(</span><span class="mtk12">user</span><span class="mtk1">) {</span></span></span> <span class="grvsc-line grvsc-line-highlighted"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk15">await</span><span class="mtk1"> </span><span class="mtk11">updateUser</span><span class="mtk1">(</span><span class="mtk12">user</span><span class="mtk1">);</span></span></span> <span class="grvsc-line grvsc-line-highlighted"><span class="grvsc-source"><span class="mtk1"> },</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> },</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1">};</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk17">&lt;/</span><span class="mtk4">script</span><span class="mtk17">&gt;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk17">&lt;</span><span class="mtk4">style</span><span class="mtk17">&gt;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk6">#app</span><span class="mtk1"> {</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">margin</span><span class="mtk1">: </span><span class="mtk7">20px</span><span class="mtk1">;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1">}</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk17">&lt;/</span><span class="mtk4">style</span><span class="mtk17">&gt;</span></span></span></code></pre> <h4 id="demo" style="position:relative;"><a href="#demo" aria-label="demo permalink" class="anchor before"><svg aria-hidden="true" focusable="false" height="16" version="1.1" viewBox="0 0 16 16" width="16"><path fill-rule="evenodd" d="M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z"></path></svg></a>Demo</h4> <div data-youtube="GqUJk52HpRU"> <button>Play Example</button> </div> <h2 id="add-a-row-with-rest-api" style="position:relative;"><a href="#add-a-row-with-rest-api" aria-label="add a row with rest api permalink" class="anchor before"><svg aria-hidden="true" focusable="false" height="16" version="1.1" viewBox="0 0 16 16" width="16"><path fill-rule="evenodd" d="M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z"></path></svg></a>Add a row with REST API</h2> <p>Adding a new row requires a <code>post</code> API service with the user object passed as a parameter. Let’s add a new <code>addUser</code> function in the <code>user.js</code> service:</p> <pre class="grvsc-container default-dark" data-language="javascript" data-index="12"><code class="grvsc-code"><span class="grvsc-line"><span class="grvsc-source"><span class="mtk15">export</span><span class="mtk1"> </span><span class="mtk4">const</span><span class="mtk1"> </span><span class="mtk11">addUser</span><span class="mtk1"> = </span><span class="mtk4">async</span><span class="mtk1"> (</span><span class="mtk12">user</span><span class="mtk1">) </span><span class="mtk4">=&gt;</span><span class="mtk1"> {</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk4">const</span><span class="mtk1"> </span><span class="mtk12">response</span><span class="mtk1"> = </span><span class="mtk15">await</span><span class="mtk1"> </span><span class="mtk11">fetch</span><span class="mtk1">(</span><span class="mtk8">&#39;https://jsonplaceholder.typicode.com/users&#39;</span><span class="mtk1">, {</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">method:</span><span class="mtk1"> </span><span class="mtk8">&#39;POST&#39;</span><span class="mtk1">,</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">body:</span><span class="mtk1"> </span><span class="mtk10">JSON</span><span class="mtk1">.</span><span class="mtk11">stringify</span><span class="mtk1">(</span><span class="mtk12">user</span><span class="mtk1">)</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> });</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk4">const</span><span class="mtk1"> </span><span class="mtk12">result</span><span class="mtk1"> = </span><span class="mtk15">await</span><span class="mtk1"> </span><span class="mtk12">response</span><span class="mtk1">.</span><span class="mtk11">json</span><span class="mtk1">();</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk15">return</span><span class="mtk1"> </span><span class="mtk12">result</span><span class="mtk1">;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1">}</span></span></span></code></pre> <p>Using the same event handler we had in the previous step, we can check if the user id is <code>undefined</code> to know whether it’s a new row or not:</p> <pre class="grvsc-container grvsc-has-line-highlighting default-dark" data-language="javascript" data-index="13"><code class="grvsc-code"><span class="grvsc-line"><span class="grvsc-source"><span class="mtk12">async</span><span class="mtk1"> </span><span class="mtk11">handleUpdateUser</span><span class="mtk1">(</span><span class="mtk12">user</span><span class="mtk1">) {</span></span></span> <span class="grvsc-line grvsc-line-highlighted"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk15">if</span><span class="mtk1"> (</span><span class="mtk12">user</span><span class="mtk1">.</span><span class="mtk12">id</span><span class="mtk1">) {</span></span></span> <span class="grvsc-line grvsc-line-highlighted"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk15">await</span><span class="mtk1"> </span><span class="mtk11">updateUser</span><span class="mtk1">(</span><span class="mtk12">user</span><span class="mtk1">);</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> } </span><span class="mtk15">else</span><span class="mtk1"> {</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk15">await</span><span class="mtk1"> </span><span class="mtk11">addUser</span><span class="mtk1">(</span><span class="mtk12">user</span><span class="mtk1">);</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> }</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1">}</span></span></span></code></pre> <h4 id="demo-1" style="position:relative;"><a href="#demo-1" aria-label="demo 1 permalink" class="anchor before"><svg aria-hidden="true" focusable="false" height="16" version="1.1" viewBox="0 0 16 16" width="16"><path fill-rule="evenodd" d="M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z"></path></svg></a>Demo</h4> <div data-youtube="Xi_kigguYQ8"> <button>Play Example</button> </div> <h2 id="delete-rows-with-rest-api" style="position:relative;"><a href="#delete-rows-with-rest-api" aria-label="delete rows with rest api permalink" class="anchor before"><svg aria-hidden="true" focusable="false" height="16" version="1.1" viewBox="0 0 16 16" width="16"><path fill-rule="evenodd" d="M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z"></path></svg></a>Delete rows with REST API:</h2> <p>Deleting a row requires a <code>delete</code> API service with only the id attached to the URL. Let’s add a new <code>deleteUser</code> function in the <code>user.js</code> service:</p> <pre class="grvsc-container default-dark" data-language="javascript" data-index="14"><code class="grvsc-code"><span class="grvsc-line"><span class="grvsc-source"><span class="mtk15">export</span><span class="mtk1"> </span><span class="mtk4">const</span><span class="mtk1"> </span><span class="mtk11">deleteUser</span><span class="mtk1"> = </span><span class="mtk4">async</span><span class="mtk1"> (</span><span class="mtk12">id</span><span class="mtk1">) </span><span class="mtk4">=&gt;</span><span class="mtk1"> {</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk4">const</span><span class="mtk1"> </span><span class="mtk12">response</span><span class="mtk1"> = </span><span class="mtk15">await</span><span class="mtk1"> </span><span class="mtk11">fetch</span><span class="mtk1">(</span><span class="mtk8">`https://jsonplaceholder.typicode.com/users/</span><span class="mtk4">${</span><span class="mtk12">id</span><span class="mtk4">}</span><span class="mtk8">`</span><span class="mtk1">, {</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">method:</span><span class="mtk1"> </span><span class="mtk8">&#39;DELETE&#39;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> });</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk4">const</span><span class="mtk1"> </span><span class="mtk12">result</span><span class="mtk1"> = </span><span class="mtk15">await</span><span class="mtk1"> </span><span class="mtk12">response</span><span class="mtk1">.</span><span class="mtk11">json</span><span class="mtk1">();</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk15">return</span><span class="mtk1"> </span><span class="mtk12">result</span><span class="mtk1">;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1">}</span></span></span></code></pre> <p>Similar to updating a user, we need to emit an event from the <code>EditableTable.vue</code> component upon removing a row:</p> <pre class="grvsc-container grvsc-has-line-highlighting default-dark" data-language="javascript" data-index="15"><code class="grvsc-code"><span class="grvsc-line"><span class="grvsc-source"><span class="mtk11">removeRowHandler</span><span class="mtk1">(</span><span class="mtk12">index</span><span class="mtk1">) {</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk4">this</span><span class="mtk1">.</span><span class="mtk12">tableItems</span><span class="mtk1"> = </span><span class="mtk4">this</span><span class="mtk1">.</span><span class="mtk12">tableItems</span><span class="mtk1">.</span><span class="mtk11">filter</span><span class="mtk1">((</span><span class="mtk12">item</span><span class="mtk1">, </span><span class="mtk12">i</span><span class="mtk1">) </span><span class="mtk4">=&gt;</span><span class="mtk1"> </span><span class="mtk12">i</span><span class="mtk1"> !== </span><span class="mtk12">index</span><span class="mtk1">);</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk4">this</span><span class="mtk1">.</span><span class="mtk11">$emit</span><span class="mtk1">(</span><span class="mtk8">&quot;input&quot;</span><span class="mtk1">, </span><span class="mtk4">this</span><span class="mtk1">.</span><span class="mtk12">tableItems</span><span class="mtk1">);</span></span></span> <span class="grvsc-line grvsc-line-highlighted"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk4">this</span><span class="mtk1">.</span><span class="mtk11">$emit</span><span class="mtk1">(</span><span class="mtk8">&quot;remove&quot;</span><span class="mtk1">, </span><span class="mtk4">this</span><span class="mtk1">.</span><span class="mtk12">tableItems</span><span class="mtk1">[</span><span class="mtk12">index</span><span class="mtk1">]);</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> },</span></span></span></code></pre> <p>Then, we can create a remove event handler in <code>App.vue</code> to trigger the delete API call:</p> <pre class="grvsc-container grvsc-has-line-highlighting default-dark" data-language="html" data-index="16"><code class="grvsc-code"><span class="grvsc-line"><span class="grvsc-source"><span class="mtk17">&lt;</span><span class="mtk4">template</span><span class="mtk17">&gt;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk17">&lt;</span><span class="mtk4">div</span><span class="mtk1"> </span><span class="mtk12">id</span><span class="mtk1">=</span><span class="mtk8">&quot;app&quot;</span><span class="mtk17">&gt;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk17">&lt;</span><span class="mtk4">EditableTable</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">v-model</span><span class="mtk1">=</span><span class="mtk8">&quot;users&quot;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">:fields</span><span class="mtk1">=</span><span class="mtk8">&quot;fields&quot;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">@submit</span><span class="mtk1">=</span><span class="mtk8">&quot;handleUpdateUser($event)&quot;</span></span></span> <span class="grvsc-line grvsc-line-highlighted"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">@remove</span><span class="mtk1">=</span><span class="mtk8">&quot;handleRemoveUser($event)&quot;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk17">&gt;&lt;/</span><span class="mtk4">EditableTable</span><span class="mtk17">&gt;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk17">&lt;</span><span class="mtk4">pre</span><span class="mtk17">&gt;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> {{ users }}</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk17">&lt;/</span><span class="mtk4">pre</span><span class="mtk17">&gt;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk17">&lt;/</span><span class="mtk4">div</span><span class="mtk17">&gt;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk17">&lt;/</span><span class="mtk4">template</span><span class="mtk17">&gt;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk17">&lt;</span><span class="mtk4">script</span><span class="mtk17">&gt;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk15">import</span><span class="mtk1"> </span><span class="mtk12">EditableTable</span><span class="mtk1"> </span><span class="mtk15">from</span><span class="mtk1"> </span><span class="mtk8">&quot;./components/EditableTable.vue&quot;</span><span class="mtk1">;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk15">import</span><span class="mtk1"> { </span><span class="mtk12">addUser</span><span class="mtk1">, </span><span class="mtk12">deleteUser</span><span class="mtk1">, </span><span class="mtk12">getUsers</span><span class="mtk1">, </span><span class="mtk12">updateUser</span><span class="mtk1"> } </span><span class="mtk15">from</span><span class="mtk1"> </span><span class="mtk8">&quot;./services/user&quot;</span><span class="mtk1">;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk15">export</span><span class="mtk1"> </span><span class="mtk15">default</span><span class="mtk1"> {</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">name:</span><span class="mtk1"> </span><span class="mtk8">&quot;App&quot;</span><span class="mtk1">,</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">components:</span><span class="mtk1"> {</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">EditableTable</span><span class="mtk1">,</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> },</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk11">data</span><span class="mtk1">() {</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk15">return</span><span class="mtk1"> {</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">fields:</span><span class="mtk1"> [</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> { </span><span class="mtk12">key:</span><span class="mtk1"> </span><span class="mtk8">&quot;selectRow&quot;</span><span class="mtk1">, </span><span class="mtk12">label:</span><span class="mtk1"> </span><span class="mtk8">&quot;&quot;</span><span class="mtk1"> },</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> { </span><span class="mtk12">key:</span><span class="mtk1"> </span><span class="mtk8">&quot;name&quot;</span><span class="mtk1">, </span><span class="mtk12">label:</span><span class="mtk1"> </span><span class="mtk8">&quot;Name&quot;</span><span class="mtk1">, </span><span class="mtk12">type:</span><span class="mtk1"> </span><span class="mtk8">&quot;text&quot;</span><span class="mtk1"> },</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> { </span><span class="mtk12">key:</span><span class="mtk1"> </span><span class="mtk8">&quot;email&quot;</span><span class="mtk1">, </span><span class="mtk12">label:</span><span class="mtk1"> </span><span class="mtk8">&quot;Email&quot;</span><span class="mtk1">, </span><span class="mtk12">type:</span><span class="mtk1"> </span><span class="mtk8">&quot;email&quot;</span><span class="mtk1"> },</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> { </span><span class="mtk12">key:</span><span class="mtk1"> </span><span class="mtk8">&quot;phone&quot;</span><span class="mtk1">, </span><span class="mtk12">label:</span><span class="mtk1"> </span><span class="mtk8">&quot;Phone&quot;</span><span class="mtk1">, </span><span class="mtk12">type:</span><span class="mtk1"> </span><span class="mtk8">&quot;text&quot;</span><span class="mtk1"> },</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> { </span><span class="mtk12">key:</span><span class="mtk1"> </span><span class="mtk8">&quot;edit&quot;</span><span class="mtk1">, </span><span class="mtk12">label:</span><span class="mtk1"> </span><span class="mtk8">&quot;&quot;</span><span class="mtk1">, </span><span class="mtk12">type:</span><span class="mtk1"> </span><span class="mtk8">&quot;edit&quot;</span><span class="mtk1"> },</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> ],</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">users:</span><span class="mtk1"> [],</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> };</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> },</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk4">async</span><span class="mtk1"> </span><span class="mtk11">mounted</span><span class="mtk1">() {</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk4">this</span><span class="mtk1">.</span><span class="mtk12">users</span><span class="mtk1"> = </span><span class="mtk15">await</span><span class="mtk1"> </span><span class="mtk11">getUsers</span><span class="mtk1">();</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> },</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">methods:</span><span class="mtk1"> {</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk4">async</span><span class="mtk1"> </span><span class="mtk11">handleUpdateUser</span><span class="mtk1">(</span><span class="mtk12">user</span><span class="mtk1">) {</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk15">if</span><span class="mtk1"> (</span><span class="mtk12">user</span><span class="mtk1">.</span><span class="mtk12">id</span><span class="mtk1">) {</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk15">await</span><span class="mtk1"> </span><span class="mtk11">updateUser</span><span class="mtk1">(</span><span class="mtk12">user</span><span class="mtk1">);</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> } </span><span class="mtk15">else</span><span class="mtk1"> {</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk15">await</span><span class="mtk1"> </span><span class="mtk11">addUser</span><span class="mtk1">(</span><span class="mtk12">user</span><span class="mtk1">);</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> }</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> },</span></span></span> <span class="grvsc-line grvsc-line-highlighted"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk4">async</span><span class="mtk1"> </span><span class="mtk11">handleRemoveUser</span><span class="mtk1">(</span><span class="mtk12">user</span><span class="mtk1">) {</span></span></span> <span class="grvsc-line grvsc-line-highlighted"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk15">await</span><span class="mtk1"> </span><span class="mtk11">deleteUser</span><span class="mtk1">(</span><span class="mtk12">user</span><span class="mtk1">.</span><span class="mtk12">id</span><span class="mtk1">);</span></span></span> <span class="grvsc-line grvsc-line-highlighted"><span class="grvsc-source"><span class="mtk1"> }</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> },</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1">};</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk17">&lt;/</span><span class="mtk4">script</span><span class="mtk17">&gt;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk17">&lt;</span><span class="mtk4">style</span><span class="mtk17">&gt;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk6">#app</span><span class="mtk1"> {</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">margin</span><span class="mtk1">: </span><span class="mtk7">20px</span><span class="mtk1">;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1">}</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk17">&lt;/</span><span class="mtk4">style</span><span class="mtk17">&gt;</span></span></span></code></pre> <h4 id="demo-2" style="position:relative;"><a href="#demo-2" aria-label="demo 2 permalink" class="anchor before"><svg aria-hidden="true" focusable="false" height="16" version="1.1" viewBox="0 0 16 16" width="16"><path fill-rule="evenodd" d="M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z"></path></svg></a>Demo:</h4> <div data-youtube="bsNqLkFLsjk"> <button>Play Example</button> </div> <p><a href="https://muhimasri.com/blogs/part-3-add-and-remove-table-rows-with-bootstrap-vue/">In the previous part</a>, we added a feature to remove multiple rows with a confirmation dialog. Let’s modify it to make it work with an API call.</p> <p>Since <a href="https://jsonplaceholder.typicode.com/">{JSON} Placeholder</a> doesn’t support multiple deletes (at least as far I know), we can use <code>map</code> to trigger multiple API calls.</p> <p>First, we need to emit the selected rows in the <code>EditableTable.vue</code> component:</p> <pre class="grvsc-container grvsc-has-line-highlighting default-dark" data-language="javascript" data-index="17"><code class="grvsc-code"><span class="grvsc-line"><span class="grvsc-source"><span class="mtk11">removeRowsHandler</span><span class="mtk1">() {</span></span></span> <span class="grvsc-line grvsc-line-highlighted"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk4">const</span><span class="mtk1"> </span><span class="mtk12">selectedItems</span><span class="mtk1"> = </span><span class="mtk4">this</span><span class="mtk1">.</span><span class="mtk12">tableItems</span><span class="mtk1">.</span><span class="mtk11">filter</span><span class="mtk1">(</span><span class="mtk12">item</span><span class="mtk1"> </span><span class="mtk4">=&gt;</span><span class="mtk1"> </span><span class="mtk12">item</span><span class="mtk1">.</span><span class="mtk12">isSelected</span><span class="mtk1">);</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk4">this</span><span class="mtk1">.</span><span class="mtk12">tableItems</span><span class="mtk1"> = </span><span class="mtk4">this</span><span class="mtk1">.</span><span class="mtk12">tableItems</span><span class="mtk1">.</span><span class="mtk11">filter</span><span class="mtk1">(</span><span class="mtk12">item</span><span class="mtk1"> </span><span class="mtk4">=&gt;</span><span class="mtk1"> !</span><span class="mtk12">item</span><span class="mtk1">.</span><span class="mtk12">isSelected</span><span class="mtk1">);</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk4">this</span><span class="mtk1">.</span><span class="mtk11">$emit</span><span class="mtk1">(</span><span class="mtk8">&quot;input&quot;</span><span class="mtk1">, </span><span class="mtk4">this</span><span class="mtk1">.</span><span class="mtk12">tableItems</span><span class="mtk1">);</span></span></span> <span class="grvsc-line grvsc-line-highlighted"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk4">this</span><span class="mtk1">.</span><span class="mtk11">$emit</span><span class="mtk1">(</span><span class="mtk8">&quot;remove&quot;</span><span class="mtk1">, </span><span class="mtk12">selectedItems</span><span class="mtk1">);</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> }</span></span></span></code></pre> <p>Then, in <code>App.vue</code> using the same event handler, we can check if the <code>user</code> object is a list and trigger multiple delete calls:</p> <pre class="grvsc-container grvsc-has-line-highlighting default-dark" data-language="javascript" data-index="18"><code class="grvsc-code"><span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">async</span><span class="mtk1"> </span><span class="mtk11">handleRemoveUser</span><span class="mtk1">(</span><span class="mtk12">user</span><span class="mtk1">) {</span></span></span> <span class="grvsc-line grvsc-line-highlighted"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk15">if</span><span class="mtk1"> (</span><span class="mtk12">user</span><span class="mtk1">.</span><span class="mtk12">length</span><span class="mtk1"> &gt; </span><span class="mtk7">0</span><span class="mtk1">) {</span></span></span> <span class="grvsc-line grvsc-line-highlighted"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk15">await</span><span class="mtk1"> </span><span class="mtk12">user</span><span class="mtk1">.</span><span class="mtk11">map</span><span class="mtk1">(</span><span class="mtk4">async</span><span class="mtk1"> (</span><span class="mtk12">item</span><span class="mtk1">) </span><span class="mtk4">=&gt;</span><span class="mtk1"> {</span></span></span> <span class="grvsc-line grvsc-line-highlighted"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk15">await</span><span class="mtk1"> </span><span class="mtk11">deleteUser</span><span class="mtk1">(</span><span class="mtk12">item</span><span class="mtk1">.</span><span class="mtk12">id</span><span class="mtk1">); </span></span></span> <span class="grvsc-line grvsc-line-highlighted"><span class="grvsc-source"><span class="mtk1"> })</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> } </span><span class="mtk15">else</span><span class="mtk1"> {</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk15">await</span><span class="mtk1"> </span><span class="mtk11">deleteUser</span><span class="mtk1">(</span><span class="mtk12">user</span><span class="mtk1">.</span><span class="mtk12">id</span><span class="mtk1">);</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> }</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> }</span></span></span></code></pre> <h4 id="demo-3" style="position:relative;"><a href="#demo-3" aria-label="demo 3 permalink" class="anchor before"><svg aria-hidden="true" focusable="false" height="16" version="1.1" viewBox="0 0 16 16" width="16"><path fill-rule="evenodd" d="M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z"></path></svg></a>Demo</h4> <div data-youtube="M4LIc3HbhZ4"> <button>Play Example</button> </div> <h2 id="summary" style="position:relative;"><a href="#summary" aria-label="summary permalink" class="anchor before"><svg aria-hidden="true" focusable="false" height="16" version="1.1" viewBox="0 0 16 16" width="16"><path fill-rule="evenodd" d="M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z"></path></svg></a>Summary</h2> <p>If you made it to this section, pat yourself on the back! You just learned how to:</p> <ul> <li>Create a service layer with different API calls</li> <li>Enhance the editable table component by watching and emitting updated data</li> <li>Load, add, edit and delete rows using Bootstrap Vue table and API services</li> </ul> <p>You can access the <a href="https://github.com/muhimasri/vue-editable-table-example">complete repository here</a>.</p> <p>Bye for now 👋</p> <style class="grvsc-styles"> .grvsc-container { overflow: auto; position: relative; -webkit-overflow-scrolling: touch; padding-top: 1rem; padding-top: var(--grvsc-padding-top, var(--grvsc-padding-v, 1rem)); padding-bottom: 1rem; padding-bottom: var(--grvsc-padding-bottom, var(--grvsc-padding-v, 1rem)); border-radius: 8px; border-radius: var(--grvsc-border-radius, 8px); font-feature-settings: normal; line-height: 1.4; } .grvsc-code { display: table; } .grvsc-line { display: table-row; box-sizing: border-box; width: 100%; position: relative; } .grvsc-line > * { position: relative; } .grvsc-gutter-pad { display: table-cell; padding-left: 0.75rem; padding-left: calc(var(--grvsc-padding-left, var(--grvsc-padding-h, 1.5rem)) / 2); } .grvsc-gutter { display: table-cell; -webkit-user-select: none; -moz-user-select: none; user-select: none; } .grvsc-gutter::before { content: attr(data-content); } .grvsc-source { display: table-cell; padding-left: 1.5rem; padding-left: var(--grvsc-padding-left, var(--grvsc-padding-h, 1.5rem)); padding-right: 1.5rem; padding-right: var(--grvsc-padding-right, var(--grvsc-padding-h, 1.5rem)); } .grvsc-source:empty::after { content: ' '; -webkit-user-select: none; -moz-user-select: none; user-select: none; } .grvsc-gutter + .grvsc-source { padding-left: 0.75rem; padding-left: calc(var(--grvsc-padding-left, var(--grvsc-padding-h, 1.5rem)) / 2); } /* Line transformer styles */ .grvsc-has-line-highlighting > .grvsc-code > .grvsc-line::before { content: ' '; position: absolute; width: 100%; } .grvsc-line-diff-add::before { background-color: var(--grvsc-line-diff-add-background-color, rgba(0, 255, 60, 0.2)); } .grvsc-line-diff-del::before { background-color: var(--grvsc-line-diff-del-background-color, rgba(255, 0, 20, 0.2)); } .grvsc-line-number { padding: 0 2px; text-align: right; opacity: 0.7; } .default-dark { background-color: #1E1E1E; color: #D4D4D4; } .default-dark .mtk17 { color: #808080; } .default-dark .mtk4 { color: #569CD6; } .default-dark .mtk1 { color: #D4D4D4; } .default-dark .mtk12 { color: #9CDCFE; } .default-dark .mtk8 { color: #CE9178; } .default-dark .mtk15 { color: #C586C0; } .default-dark .mtk10 { color: #4EC9B0; } .default-dark .mtk11 { color: #DCDCAA; } .default-dark .mtk6 { color: #D7BA7D; } .default-dark .mtk7 { color: #B5CEA8; } .default-dark .grvsc-line-highlighted::before { background-color: var(--grvsc-line-highlighted-background-color, rgba(255, 255, 255, 0.1)); box-shadow: inset var(--grvsc-line-highlighted-border-width, 4px) 0 0 0 var(--grvsc-line-highlighted-border-color, rgba(255, 255, 255, 0.5)); } </style><![CDATA[How to Replace Multiple Words and Characters in JavaScript]]>https://muhimasri.comhow-to-replace-multiple-words-and-characters-in-javascripthttps://muhimasri.comhow-to-replace-multiple-words-and-characters-in-javascript<p>Using <code>replace()</code> function in JavaScript has many use cases such as removing unwanted or escape characters in a string. Also, education and languages apps benefit from this feature when auto-correcting multiple words in a paragraph. For example, let’s look at the sentence below:</p> <pre class="grvsc-container default-dark" data-language="" data-index="0"><code class="grvsc-code"><span class="grvsc-line"><span class="grvsc-source">Helo worLd! Im so glads to be alife in a beautiful worLd.</span></span></code></pre> <p>As you can see, there are a few spelling mistakes that we’d like to correct by replacing certain words with the proper ones.</p> <p>In this article, we’ll go through two different approaches to solving this problem with minimal code.</p> <h2 id="replace-vs-replaceall" style="position:relative;"><a href="#replace-vs-replaceall" aria-label="replace vs replaceall permalink" class="anchor before"><svg aria-hidden="true" focusable="false" height="16" version="1.1" viewBox="0 0 16 16" width="16"><path fill-rule="evenodd" d="M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z"></path></svg></a>replace vs replaceAll</h2> <p>Both functions are very common in JavaScript for replacing strings and characters. The main difference is that <code>replace()</code> replaces the first occurrence while <code>replaceAll()</code> replaces all occurrences of the search. For example:</p> <pre class="grvsc-container default-dark" data-language="javascript" data-index="1"><code class="grvsc-code"><span class="grvsc-line"><span class="grvsc-source"><span class="mtk4">const</span><span class="mtk1"> </span><span class="mtk12">p</span><span class="mtk1"> = </span><span class="mtk8">&#39;The quick brown fox jumps over the lazy dog. If the dog reacted, was it really lazy?&#39;</span><span class="mtk1">;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk10">console</span><span class="mtk1">.</span><span class="mtk11">log</span><span class="mtk1">(</span><span class="mtk12">p</span><span class="mtk1">.</span><span class="mtk11">replace</span><span class="mtk1">(</span><span class="mtk8">&#39;dog&#39;</span><span class="mtk1">, </span><span class="mtk8">&#39;monkey&#39;</span><span class="mtk1">));</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk3">// expected output: &quot;The quick brown fox jumps over the lazy monkey. If the dog reacted, was it really lazy?&quot;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk10">console</span><span class="mtk1">.</span><span class="mtk11">log</span><span class="mtk1">(</span><span class="mtk12">p</span><span class="mtk1">.</span><span class="mtk11">replaceAll</span><span class="mtk1">(</span><span class="mtk8">&#39;dog&#39;</span><span class="mtk1">, </span><span class="mtk8">&#39;monkey&#39;</span><span class="mtk1">));</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk3">// expected output: &quot;The quick brown fox jumps over the lazy monkey. If the monkey reacted, was it really?&quot;</span></span></span></code></pre> <p>However, we can still replace all occurrences using <code>replace()</code> function along with a regular expression as follows:</p> <pre class="grvsc-container default-dark" data-language="javascript" data-index="2"><code class="grvsc-code"><span class="grvsc-line"><span class="grvsc-source"><span class="mtk4">const</span><span class="mtk1"> </span><span class="mtk12">p</span><span class="mtk1"> = </span><span class="mtk8">&#39;The quick brown fox jumps over the lazy dog. If the dog reacted, was it really lazy?&#39;</span><span class="mtk1">;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk10">console</span><span class="mtk1">.</span><span class="mtk11">log</span><span class="mtk1">(</span><span class="mtk12">p</span><span class="mtk1">.</span><span class="mtk11">replace</span><span class="mtk1">(</span><span class="mtk5">/dog/</span><span class="mtk4">g</span><span class="mtk1">, </span><span class="mtk8">&#39;monkey&#39;</span><span class="mtk1">));</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk3">// expected output: &quot;The quick brown fox jumps over the lazy monkey. If the monkey reacted, was it really?&quot;</span></span></span></code></pre> <h2 id="solution-1-using-a-loop-with-a-replaceall-function" style="position:relative;"><a href="#solution-1-using-a-loop-with-a-replaceall-function" aria-label="solution 1 using a loop with a replaceall function permalink" class="anchor before"><svg aria-hidden="true" focusable="false" height="16" version="1.1" viewBox="0 0 16 16" width="16"><path fill-rule="evenodd" d="M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z"></path></svg></a>Solution 1: Using a loop with a replaceAll function</h2> <p>In this solution, we’ll simply loop through the words that need to be corrected then trigger <code>replaceAll()</code>.</p> <p>First, let’s create a dictionary with all the required corrections:</p> <pre class="grvsc-container default-dark" data-language="javascript" data-index="3"><code class="grvsc-code"><span class="grvsc-line"><span class="grvsc-source"><span class="mtk4">const</span><span class="mtk1"> </span><span class="mtk12">correction</span><span class="mtk1"> = {</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk8">&quot;Helo&quot;</span><span class="mtk12">:</span><span class="mtk1"> </span><span class="mtk8">&quot;Hello&quot;</span><span class="mtk1">,</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk8">&quot;worLd&quot;</span><span class="mtk12">:</span><span class="mtk1"> </span><span class="mtk8">&quot;world&quot;</span><span class="mtk1">,</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk8">&quot;glads&quot;</span><span class="mtk12">:</span><span class="mtk1"> </span><span class="mtk8">&quot;glad&quot;</span><span class="mtk1">,</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk8">&quot;alife&quot;</span><span class="mtk12">:</span><span class="mtk1"> </span><span class="mtk8">&quot;alive&quot;</span><span class="mtk1">,</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk8">&quot;Im&quot;</span><span class="mtk12">:</span><span class="mtk1"> </span><span class="mtk8">&quot;I&#39;m&quot;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1">};</span></span></span></code></pre> <p>Then, we can loop through the keys and replace all occurrences with the proper value:</p> <pre class="grvsc-container default-dark" data-language="javascript" data-index="4"><code class="grvsc-code"><span class="grvsc-line"><span class="grvsc-source"><span class="mtk4">let</span><span class="mtk1"> </span><span class="mtk12">str</span><span class="mtk1"> = </span><span class="mtk8">&quot;Helo worLd! Im so glads to be alife in a beautiful worLd.&quot;</span><span class="mtk1">;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk10">Object</span><span class="mtk1">.</span><span class="mtk11">keys</span><span class="mtk1">(</span><span class="mtk12">correction</span><span class="mtk1">).</span><span class="mtk11">forEach</span><span class="mtk1">((</span><span class="mtk12">key</span><span class="mtk1">) </span><span class="mtk4">=&gt;</span><span class="mtk1"> {</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">str</span><span class="mtk1"> = </span><span class="mtk12">str</span><span class="mtk1">.</span><span class="mtk11">replaceAll</span><span class="mtk1">(</span><span class="mtk12">key</span><span class="mtk1">, </span><span class="mtk12">correction</span><span class="mtk1">[</span><span class="mtk12">key</span><span class="mtk1">]);</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1">});</span></span></span> <span class="grvsc-line"><span class="grvsc-source"></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk10">console</span><span class="mtk1">.</span><span class="mtk11">log</span><span class="mtk1">(</span><span class="mtk12">str</span><span class="mtk1">);</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk3">// expected output: &quot;Hello world! I&#39;m so glad to be alive in a beautiful world.&quot;</span></span></span></code></pre> <h2 id="solution-2-using-regex-with-a-replace-function" style="position:relative;"><a href="#solution-2-using-regex-with-a-replace-function" aria-label="solution 2 using regex with a replace function permalink" class="anchor before"><svg aria-hidden="true" focusable="false" height="16" version="1.1" viewBox="0 0 16 16" width="16"><path fill-rule="evenodd" d="M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z"></path></svg></a>Solution 2: Using regex with a replace function</h2> <p>Instead of looping through all keys, we can create a regular expression to replace all the words we need. For example, the code below uses regex that can replace all occurrences of “worLd” and “Helo” with “word”:</p> <pre class="grvsc-container default-dark" data-language="javascript" data-index="5"><code class="grvsc-code"><span class="grvsc-line"><span class="grvsc-source"><span class="mtk4">let</span><span class="mtk1"> </span><span class="mtk12">str</span><span class="mtk1"> = </span><span class="mtk8">&quot;Helo worLd! Im so glads to be alife in a beautiful worLd.&quot;</span><span class="mtk1">;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk12">str</span><span class="mtk1"> = </span><span class="mtk12">str</span><span class="mtk1">.</span><span class="mtk11">replace</span><span class="mtk1">(</span><span class="mtk5">/worLd</span><span class="mtk11">|</span><span class="mtk5">Helo/</span><span class="mtk4">g</span><span class="mtk1">, </span><span class="mtk8">&#39;world&#39;</span><span class="mtk1">);</span></span></span> <span class="grvsc-line"><span class="grvsc-source"></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk10">console</span><span class="mtk1">.</span><span class="mtk11">log</span><span class="mtk1">(</span><span class="mtk12">str</span><span class="mtk1">);</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk3">// expected output: &quot;world world! Im so glad to be alife in a beautiful world.&quot;</span></span></span></code></pre> <p>But instead of replacing everything with the same word, we have to find the proper value from the <code>correction</code> dictionary we created earlier. <code>replace()</code> provides the option to pass a function instead of a string as a call back for every match. This way, we can use the current matched word to return the required value:</p> <pre class="grvsc-container default-dark" data-language="javascript" data-index="6"><code class="grvsc-code"><span class="grvsc-line"><span class="grvsc-source"><span class="mtk4">const</span><span class="mtk1"> </span><span class="mtk12">correction</span><span class="mtk1"> = {</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk8">&quot;Helo&quot;</span><span class="mtk12">:</span><span class="mtk1"> </span><span class="mtk8">&quot;Hello&quot;</span><span class="mtk1">,</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk8">&quot;worLd&quot;</span><span class="mtk12">:</span><span class="mtk1"> </span><span class="mtk8">&quot;world&quot;</span><span class="mtk1">,</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk8">&quot;glads&quot;</span><span class="mtk12">:</span><span class="mtk1"> </span><span class="mtk8">&quot;glad&quot;</span><span class="mtk1">,</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk8">&quot;alife&quot;</span><span class="mtk12">:</span><span class="mtk1"> </span><span class="mtk8">&quot;alive&quot;</span><span class="mtk1">,</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk8">&quot;Im&quot;</span><span class="mtk12">:</span><span class="mtk1"> </span><span class="mtk8">&quot;I&#39;m&quot;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1">};</span></span></span> <span class="grvsc-line"><span class="grvsc-source"></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk4">let</span><span class="mtk1"> </span><span class="mtk12">str</span><span class="mtk1"> = </span><span class="mtk8">&quot;Helo worLd! Im so glads to be alife in a beautiful worLd.&quot;</span><span class="mtk1">;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk12">str</span><span class="mtk1"> = </span><span class="mtk12">str</span><span class="mtk1">.</span><span class="mtk11">replace</span><span class="mtk1">(</span><span class="mtk5">/Helo</span><span class="mtk11">|</span><span class="mtk5">world</span><span class="mtk11">|</span><span class="mtk5">glads</span><span class="mtk11">|</span><span class="mtk5">alife</span><span class="mtk11">|</span><span class="mtk5">Im/</span><span class="mtk4">g</span><span class="mtk1">, </span><span class="mtk12">matched</span><span class="mtk1"> </span><span class="mtk4">=&gt;</span><span class="mtk1"> </span><span class="mtk12">correction</span><span class="mtk1">[</span><span class="mtk12">matched</span><span class="mtk1">]);</span></span></span> <span class="grvsc-line"><span class="grvsc-source"></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk10">console</span><span class="mtk1">.</span><span class="mtk11">log</span><span class="mtk1">(</span><span class="mtk12">str</span><span class="mtk1">);</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk3">// expected output: &quot;Hello world! I&#39;m so glad to be alive in a beautiful world.&quot;</span></span></span></code></pre> <p>We can further improve this by creating a list of words dynamically from the <code>correction</code> object as follows:</p> <pre class="grvsc-container default-dark" data-language="javascript" data-index="7"><code class="grvsc-code"><span class="grvsc-line"><span class="grvsc-source"><span class="mtk4">const</span><span class="mtk1"> </span><span class="mtk12">reg</span><span class="mtk1"> = </span><span class="mtk4">new</span><span class="mtk1"> </span><span class="mtk10">RegExp</span><span class="mtk1">(</span><span class="mtk10">Object</span><span class="mtk1">.</span><span class="mtk11">keys</span><span class="mtk1">(</span><span class="mtk12">correction</span><span class="mtk1">).</span><span class="mtk11">join</span><span class="mtk1">(</span><span class="mtk8">&quot;|&quot;</span><span class="mtk1">), </span><span class="mtk8">&quot;g&quot;</span><span class="mtk1">);</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk12">str</span><span class="mtk1"> = </span><span class="mtk12">str</span><span class="mtk1">.</span><span class="mtk11">replace</span><span class="mtk1">(</span><span class="mtk12">reg</span><span class="mtk1">, (</span><span class="mtk12">matched</span><span class="mtk1">) </span><span class="mtk4">=&gt;</span><span class="mtk1"> </span><span class="mtk12">correction</span><span class="mtk1">[</span><span class="mtk12">matched</span><span class="mtk1">]);</span></span></span></code></pre> <p>Finally, let’s put everything together in a reusable function and call it <code>autoCorrect()</code>:</p> <pre class="grvsc-container default-dark" data-language="javascript" data-index="8"><code class="grvsc-code"><span class="grvsc-line"><span class="grvsc-source"><span class="mtk4">function</span><span class="mtk1"> </span><span class="mtk11">autoCorrect</span><span class="mtk1">(</span><span class="mtk12">text</span><span class="mtk1">, </span><span class="mtk12">correction</span><span class="mtk1">) {</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk4">const</span><span class="mtk1"> </span><span class="mtk12">reg</span><span class="mtk1"> = </span><span class="mtk4">new</span><span class="mtk1"> </span><span class="mtk10">RegExp</span><span class="mtk1">(</span><span class="mtk10">Object</span><span class="mtk1">.</span><span class="mtk11">keys</span><span class="mtk1">(</span><span class="mtk12">correction</span><span class="mtk1">).</span><span class="mtk11">join</span><span class="mtk1">(</span><span class="mtk8">&quot;|&quot;</span><span class="mtk1">), </span><span class="mtk8">&quot;g&quot;</span><span class="mtk1">);</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk15">return</span><span class="mtk1"> </span><span class="mtk12">text</span><span class="mtk1">.</span><span class="mtk11">replace</span><span class="mtk1">(</span><span class="mtk12">reg</span><span class="mtk1">, (</span><span class="mtk12">matched</span><span class="mtk1">) </span><span class="mtk4">=&gt;</span><span class="mtk1"> </span><span class="mtk12">correction</span><span class="mtk1">[</span><span class="mtk12">matched</span><span class="mtk1">]);</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1">}</span></span></span> <span class="grvsc-line"><span class="grvsc-source"></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk3">// Consume the function as follows</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk4">let</span><span class="mtk1"> </span><span class="mtk12">str</span><span class="mtk1"> = </span><span class="mtk8">&quot;Helo worLd! Im so glads to be alife in a beautiful worLd.&quot;</span><span class="mtk1">;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk4">const</span><span class="mtk1"> </span><span class="mtk12">correction</span><span class="mtk1"> = {</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">Helo:</span><span class="mtk1"> </span><span class="mtk8">&quot;Hello&quot;</span><span class="mtk1">,</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">worLd:</span><span class="mtk1"> </span><span class="mtk8">&quot;world&quot;</span><span class="mtk1">,</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">glads:</span><span class="mtk1"> </span><span class="mtk8">&quot;glad&quot;</span><span class="mtk1">,</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">alife:</span><span class="mtk1"> </span><span class="mtk8">&quot;alive&quot;</span><span class="mtk1">,</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">Im:</span><span class="mtk1"> </span><span class="mtk8">&quot;I&#39;m&quot;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1">};</span></span></span> <span class="grvsc-line"><span class="grvsc-source"></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk4">const</span><span class="mtk1"> </span><span class="mtk12">correctedText</span><span class="mtk1"> = </span><span class="mtk11">autoCorrect</span><span class="mtk1">(</span><span class="mtk12">str</span><span class="mtk1">, </span><span class="mtk12">correction</span><span class="mtk1">);</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk10">console</span><span class="mtk1">.</span><span class="mtk11">log</span><span class="mtk1">(</span><span class="mtk12">correctedText</span><span class="mtk1">);</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk3">// expected output: &quot;Hello world! I&#39;m so glad to be alive in a beautiful world.&quot;</span></span></span></code></pre> <h2 id="take-a-way" style="position:relative;"><a href="#take-a-way" aria-label="take a way permalink" class="anchor before"><svg aria-hidden="true" focusable="false" height="16" version="1.1" viewBox="0 0 16 16" width="16"><path fill-rule="evenodd" d="M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z"></path></svg></a>Take a way</h2> <p>The first solution seems to be sufficient enough for a simple word match, but the second can handle more complex match patterns with less code because of the regular expression advantage.</p> <p>Bye for now 👋</p> <style class="grvsc-styles"> .grvsc-container { overflow: auto; position: relative; -webkit-overflow-scrolling: touch; padding-top: 1rem; padding-top: var(--grvsc-padding-top, var(--grvsc-padding-v, 1rem)); padding-bottom: 1rem; padding-bottom: var(--grvsc-padding-bottom, var(--grvsc-padding-v, 1rem)); border-radius: 8px; border-radius: var(--grvsc-border-radius, 8px); font-feature-settings: normal; line-height: 1.4; } .grvsc-code { display: table; } .grvsc-line { display: table-row; box-sizing: border-box; width: 100%; position: relative; } .grvsc-line > * { position: relative; } .grvsc-gutter-pad { display: table-cell; padding-left: 0.75rem; padding-left: calc(var(--grvsc-padding-left, var(--grvsc-padding-h, 1.5rem)) / 2); } .grvsc-gutter { display: table-cell; -webkit-user-select: none; -moz-user-select: none; user-select: none; } .grvsc-gutter::before { content: attr(data-content); } .grvsc-source { display: table-cell; padding-left: 1.5rem; padding-left: var(--grvsc-padding-left, var(--grvsc-padding-h, 1.5rem)); padding-right: 1.5rem; padding-right: var(--grvsc-padding-right, var(--grvsc-padding-h, 1.5rem)); } .grvsc-source:empty::after { content: ' '; -webkit-user-select: none; -moz-user-select: none; user-select: none; } .grvsc-gutter + .grvsc-source { padding-left: 0.75rem; padding-left: calc(var(--grvsc-padding-left, var(--grvsc-padding-h, 1.5rem)) / 2); } /* Line transformer styles */ .grvsc-has-line-highlighting > .grvsc-code > .grvsc-line::before { content: ' '; position: absolute; width: 100%; } .grvsc-line-diff-add::before { background-color: var(--grvsc-line-diff-add-background-color, rgba(0, 255, 60, 0.2)); } .grvsc-line-diff-del::before { background-color: var(--grvsc-line-diff-del-background-color, rgba(255, 0, 20, 0.2)); } .grvsc-line-number { padding: 0 2px; text-align: right; opacity: 0.7; } .default-dark { background-color: #1E1E1E; color: #D4D4D4; } .default-dark .mtk4 { color: #569CD6; } .default-dark .mtk1 { color: #D4D4D4; } .default-dark .mtk12 { color: #9CDCFE; } .default-dark .mtk8 { color: #CE9178; } .default-dark .mtk10 { color: #4EC9B0; } .default-dark .mtk11 { color: #DCDCAA; } .default-dark .mtk3 { color: #6A9955; } .default-dark .mtk5 { color: #D16969; } .default-dark .mtk15 { color: #C586C0; } .default-dark .grvsc-line-highlighted::before { background-color: var(--grvsc-line-highlighted-background-color, rgba(255, 255, 255, 0.1)); box-shadow: inset var(--grvsc-line-highlighted-border-width, 4px) 0 0 0 var(--grvsc-line-highlighted-border-color, rgba(255, 255, 255, 0.5)); } </style><![CDATA[How to Save and Download Files in JavaScript]]>https://muhimasri.comhow-to-save-files-in-javascripthttps://muhimasri.comhow-to-save-files-in-javascript<p>In the web world, “save file”, “save as”, or “download file” are used interchangeably and mean the same thing, which is to download and save a file to the client’s machine. There isn’t a built-in method in JavaScript that allows us to do so, but there are a few ways to achieve this. In this tutorial, we’ll explore different ways to save files in JavaScript programmatically, including how to download multiple files in one hit.</p> <h2 id="download-and-save-a-file-using-an-anchor-element" style="position:relative;"><a href="#download-and-save-a-file-using-an-anchor-element" aria-label="download and save a file using an anchor element permalink" class="anchor before"><svg aria-hidden="true" focusable="false" height="16" version="1.1" viewBox="0 0 16 16" width="16"><path fill-rule="evenodd" d="M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z"></path></svg></a>Download and save a file using an anchor element</h2> <p>The easiest way to download and save a file programmatically in JavaScript is to dynamically create an anchor element with a <code>download</code> attribute and invoke the click event. Let’s create a function called <code>saveFile</code> that takes a URL and a file name as parameters and does the following:</p> <ol> <li>Create an anchor element</li> <li>Set the <code>href</code> to the URL</li> <li>Set the <code>download</code> attribute to the file name</li> <li>Append the anchor to the body</li> <li>Invoke the click event</li> <li>Remove the anchor from the body</li> </ol> <pre class="grvsc-container default-dark" data-language="javascript" data-index="0"><code class="grvsc-code"><span class="grvsc-line"><span class="grvsc-source"><span class="mtk4">function</span><span class="mtk1"> </span><span class="mtk11">saveFile</span><span class="mtk1">(</span><span class="mtk12">url</span><span class="mtk1">, </span><span class="mtk12">filename</span><span class="mtk1">) {</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk4">const</span><span class="mtk1"> </span><span class="mtk12">a</span><span class="mtk1"> = </span><span class="mtk12">document</span><span class="mtk1">.</span><span class="mtk11">createElement</span><span class="mtk1">(</span><span class="mtk8">&quot;a&quot;</span><span class="mtk1">);</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">a</span><span class="mtk1">.</span><span class="mtk12">href</span><span class="mtk1"> = </span><span class="mtk12">url</span><span class="mtk1">;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">a</span><span class="mtk1">.</span><span class="mtk12">download</span><span class="mtk1"> = </span><span class="mtk12">filename</span><span class="mtk1"> || </span><span class="mtk8">&quot;file-name&quot;</span><span class="mtk1">;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">document</span><span class="mtk1">.</span><span class="mtk12">body</span><span class="mtk1">.</span><span class="mtk11">appendChild</span><span class="mtk1">(</span><span class="mtk12">a</span><span class="mtk1">);</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">a</span><span class="mtk1">.</span><span class="mtk11">click</span><span class="mtk1">();</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">document</span><span class="mtk1">.</span><span class="mtk12">body</span><span class="mtk1">.</span><span class="mtk11">removeChild</span><span class="mtk1">(</span><span class="mtk12">a</span><span class="mtk1">);</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1">}</span></span></span></code></pre> <p>Although appending the anchor to the body is not always necessary, it’s a good practice to do so to avoid any issues with the click event on some browsers with different configurations.</p> <p>We can consume the function as follows:</p> <pre class="grvsc-container default-dark" data-language="javascript" data-index="1"><code class="grvsc-code"><span class="grvsc-line"><span class="grvsc-source"><span class="mtk11">saveFile</span><span class="mtk1">(</span><span class="mtk8">&quot;/files/myFile.txt&quot;</span><span class="mtk1">, </span><span class="mtk8">&quot;myFile.txt&quot;</span><span class="mtk1">);</span></span></span></code></pre> <p>We are not limited to static files. We can also download files that are generated dynamically. For example, we can create a <code>Blob</code> object and convert it to a URL.</p> <pre class="grvsc-container default-dark" data-language="javascript" data-index="2"><code class="grvsc-code"><span class="grvsc-line"><span class="grvsc-source"><span class="mtk4">const</span><span class="mtk1"> </span><span class="mtk12">file</span><span class="mtk1"> = </span><span class="mtk4">new</span><span class="mtk1"> </span><span class="mtk10">Blob</span><span class="mtk1">([</span><span class="mtk8">&quot;Hello, file!&quot;</span><span class="mtk1">], { </span><span class="mtk12">type:</span><span class="mtk1"> </span><span class="mtk8">&quot;text/plain&quot;</span><span class="mtk1"> });</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk4">const</span><span class="mtk1"> </span><span class="mtk12">url</span><span class="mtk1"> = </span><span class="mtk12">window</span><span class="mtk1">.</span><span class="mtk12">URL</span><span class="mtk1">.</span><span class="mtk11">createObjectURL</span><span class="mtk1">(</span><span class="mtk12">file</span><span class="mtk1">);</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk11">saveFile</span><span class="mtk1">(</span><span class="mtk12">url</span><span class="mtk1">, </span><span class="mtk8">&quot;myFile.txt&quot;</span><span class="mtk1">);</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk12">window</span><span class="mtk1">.</span><span class="mtk12">URL</span><span class="mtk1">.</span><span class="mtk11">revokeObjectURL</span><span class="mtk1">(</span><span class="mtk12">url</span><span class="mtk1">);</span></span></span></code></pre> <p><code>createObjectURL</code> creates a URL for the <code>Blob</code> object, and it’s only valid for the duration of the page session unless we call <code>revokeObjectURL</code> to release the object.</p> <h2 id="download-and-save-a-file-using-the-fetch-api" style="position:relative;"><a href="#download-and-save-a-file-using-the-fetch-api" aria-label="download and save a file using the fetch api permalink" class="anchor before"><svg aria-hidden="true" focusable="false" height="16" version="1.1" viewBox="0 0 16 16" width="16"><path fill-rule="evenodd" d="M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z"></path></svg></a>Download and save a file using the fetch API</h2> <p>Another way to download and save a file is to use the <code>fetch</code> API to get the file content first and then use the <code>Blob</code> object to create a URL. This approach has has a couple of advantages:</p> <ul> <li>We can get the file content from a different domain, especially with cloud storage like AWS S3 or Azure Blob Storage. If we try to download a file from a different domain using the anchor element, it will redirect us to the file instead of downloading it.</li> <li><code>fetch</code> is designed to work with the Streams API, allowing it to process large amounts of data in chunks without loading the entire file into memory. This is particularly useful for downloading large files or working in environments with limited memory.</li> </ul> <p>Let’s create a function called <code>downloadFile</code> that takes a URL and a file name as parameters and does the following:</p> <ol> <li>Fetch the file content</li> <li>Convert the response to a blob</li> <li>Create a URL from the blob</li> <li>Use the <code>saveFile</code> function we did earlier to download the file</li> </ol> <pre class="grvsc-container default-dark" data-language="javascript" data-index="3"><code class="grvsc-code"><span class="grvsc-line"><span class="grvsc-source"><span class="mtk4">async</span><span class="mtk1"> </span><span class="mtk4">function</span><span class="mtk1"> </span><span class="mtk11">downloadFile</span><span class="mtk1">(</span><span class="mtk12">url</span><span class="mtk1">, </span><span class="mtk12">filename</span><span class="mtk1">) {</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk15">try</span><span class="mtk1"> {</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk4">const</span><span class="mtk1"> </span><span class="mtk12">response</span><span class="mtk1"> = </span><span class="mtk15">await</span><span class="mtk1"> </span><span class="mtk11">fetch</span><span class="mtk1">(</span><span class="mtk12">url</span><span class="mtk1">, {</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">headers:</span><span class="mtk1"> {</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">Accept:</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk8">&quot;application/json, text/plain,application/zip, image/png, image/jpeg, image/*&quot;</span><span class="mtk1">,</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> },</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> });</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk15">if</span><span class="mtk1"> (!</span><span class="mtk12">response</span><span class="mtk1">.</span><span class="mtk12">ok</span><span class="mtk1">) {</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk15">throw</span><span class="mtk1"> </span><span class="mtk4">new</span><span class="mtk1"> </span><span class="mtk10">Error</span><span class="mtk1">(</span><span class="mtk8">`HTTP error! status: </span><span class="mtk4">${</span><span class="mtk12">response</span><span class="mtk1">.</span><span class="mtk12">status</span><span class="mtk4">}</span><span class="mtk8">`</span><span class="mtk1">);</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> }</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk4">const</span><span class="mtk1"> </span><span class="mtk12">blob</span><span class="mtk1"> = </span><span class="mtk15">await</span><span class="mtk1"> </span><span class="mtk12">response</span><span class="mtk1">.</span><span class="mtk11">blob</span><span class="mtk1">();</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk4">const</span><span class="mtk1"> </span><span class="mtk12">blobUrl</span><span class="mtk1"> = </span><span class="mtk12">URL</span><span class="mtk1">.</span><span class="mtk11">createObjectURL</span><span class="mtk1">(</span><span class="mtk12">blob</span><span class="mtk1">);</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk11">saveFile</span><span class="mtk1">(</span><span class="mtk12">blobUrl</span><span class="mtk1">, </span><span class="mtk12">filename</span><span class="mtk1">);</span></span></span> <span class="grvsc-line"><span class="grvsc-source"></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">URL</span><span class="mtk1">.</span><span class="mtk11">revokeObjectURL</span><span class="mtk1">(</span><span class="mtk12">blobUrl</span><span class="mtk1">);</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> } </span><span class="mtk15">catch</span><span class="mtk1"> (</span><span class="mtk12">err</span><span class="mtk1">) {</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk10">console</span><span class="mtk1">.</span><span class="mtk11">error</span><span class="mtk1">(</span><span class="mtk8">&quot;Error in fetching and downloading file:&quot;</span><span class="mtk1">, </span><span class="mtk12">err</span><span class="mtk1">);</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> }</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1">}</span></span></span></code></pre> <p>Notice that we are passing the <code>Accept</code> header to the <code>fetch</code> function to specify the file type. This is important because the <code>fetch</code> function will try to guess the file type based on the response headers, and if it fails, it will throw an error.</p> <p>Now, we can consume the function with different file types and cross-domain URLs:</p> <pre class="grvsc-container default-dark" data-language="javascript" data-index="4"><code class="grvsc-code"><span class="grvsc-line"><span class="grvsc-source"><span class="mtk11">downloadFile</span><span class="mtk1">(</span><span class="mtk8">&quot;https://httpbin.org/robots.txt&quot;</span><span class="mtk1">, </span><span class="mtk8">&quot;textFile.txt&quot;</span><span class="mtk1">);</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk11">downloadFile</span><span class="mtk1">(</span><span class="mtk8">&quot;https://httpbin.org/image&quot;</span><span class="mtk1">, </span><span class="mtk8">&quot;imageFile.jpg&quot;</span><span class="mtk1">);</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk11">downloadFile</span><span class="mtk1">(</span><span class="mtk8">&quot;https://httpbin.org/json&quot;</span><span class="mtk1">, </span><span class="mtk8">&quot;jsonFile.json&quot;</span><span class="mtk1">);</span></span></span></code></pre> <h2 id="use-file-saver-library" style="position:relative;"><a href="#use-file-saver-library" aria-label="use file saver library permalink" class="anchor before"><svg aria-hidden="true" focusable="false" height="16" version="1.1" viewBox="0 0 16 16" width="16"><path fill-rule="evenodd" d="M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z"></path></svg></a>Use file-saver library</h2> <p><a href="https://github.com/eligrey/FileSaver.js/">FileSaver.js</a> is an excellent solution to saving files on the client-side without having to write our custom code.</p> <p>First, we need to install the library:</p> <pre class="grvsc-container default-dark" data-language="" data-index="5"><code class="grvsc-code"><span class="grvsc-line"><span class="grvsc-source">npm i file-saver</span></span></code></pre> <p>Then, use it as follows:</p> <pre class="grvsc-container default-dark" data-language="javascript" data-index="6"><code class="grvsc-code"><span class="grvsc-line"><span class="grvsc-source"><span class="mtk4">const</span><span class="mtk1"> </span><span class="mtk12">FileSaver</span><span class="mtk1"> = </span><span class="mtk11">require</span><span class="mtk1">(</span><span class="mtk8">&quot;file-saver&quot;</span><span class="mtk1">);</span></span></span> <span class="grvsc-line"><span class="grvsc-source"></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk3">// Save Blob file</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk4">const</span><span class="mtk1"> </span><span class="mtk12">file</span><span class="mtk1"> = </span><span class="mtk11">createBlob</span><span class="mtk1">(</span><span class="mtk8">&quot;Hello, file!&quot;</span><span class="mtk1">);</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk12">FileSaver</span><span class="mtk1">.</span><span class="mtk11">saveAs</span><span class="mtk1">(</span><span class="mtk12">file</span><span class="mtk1">, </span><span class="mtk8">&quot;myFile.txt&quot;</span><span class="mtk1">);</span></span></span> <span class="grvsc-line"><span class="grvsc-source"></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk3">// Save URL</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk12">FileSaver</span><span class="mtk1">.</span><span class="mtk11">saveAs</span><span class="mtk1">(</span><span class="mtk8">&quot;https://httpbin.org/image&quot;</span><span class="mtk1">, </span><span class="mtk8">&quot;image.jpg&quot;</span><span class="mtk1">);</span></span></span></code></pre> <p>The <code>saveAs</code> function takes two parameters:</p> <ul> <li>The file content, which can be a <code>Blob</code> object or a URL</li> <li>The file name</li> </ul> <p>We’re all done! FileSaver will take care of the rest of the logic for us.</p> <h2 id="zip-and-download-multiple-files" style="position:relative;"><a href="#zip-and-download-multiple-files" aria-label="zip and download multiple files permalink" class="anchor before"><svg aria-hidden="true" focusable="false" height="16" version="1.1" viewBox="0 0 16 16" width="16"><path fill-rule="evenodd" d="M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z"></path></svg></a>Zip and download multiple files</h2> <p>In some instances, we need to download multiple files in one hit. Although this can be achieved by looping through the files and triggering the save function, this will end up with many files added to the download folder.</p> <p>An alternative solution is to use <a href="https://stuk.github.io/jszip/">JSZip</a>, a library for creating, reading, and editing .zip files.</p> <p>First, we need to install the library:</p> <pre class="grvsc-container default-dark" data-language="" data-index="7"><code class="grvsc-code"><span class="grvsc-line"><span class="grvsc-source">npm i jszip</span></span></code></pre> <p>Then, in the following code snippet, we’ll create a zip file with two text files and download it:</p> <pre class="grvsc-container default-dark" data-language="javascript" data-index="8"><code class="grvsc-code"><span class="grvsc-line"><span class="grvsc-source"><span class="mtk4">const</span><span class="mtk1"> </span><span class="mtk12">zip</span><span class="mtk1"> = </span><span class="mtk4">new</span><span class="mtk1"> </span><span class="mtk10">JSZip</span><span class="mtk1">();</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk4">const</span><span class="mtk1"> </span><span class="mtk12">file1</span><span class="mtk1"> = </span><span class="mtk4">new</span><span class="mtk1"> </span><span class="mtk10">Blob</span><span class="mtk1">([</span><span class="mtk8">&quot;Hello, file 1!&quot;</span><span class="mtk1">], { </span><span class="mtk12">type:</span><span class="mtk1"> </span><span class="mtk8">&quot;text/plain&quot;</span><span class="mtk1"> });</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk4">const</span><span class="mtk1"> </span><span class="mtk12">file2</span><span class="mtk1"> = </span><span class="mtk4">new</span><span class="mtk1"> </span><span class="mtk10">Blob</span><span class="mtk1">([</span><span class="mtk8">&quot;Hello, file 2!&quot;</span><span class="mtk1">], { </span><span class="mtk12">type:</span><span class="mtk1"> </span><span class="mtk8">&quot;text/plain&quot;</span><span class="mtk1"> });</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk12">zip</span><span class="mtk1">.</span><span class="mtk11">file</span><span class="mtk1">(</span><span class="mtk8">&quot;file1.txt&quot;</span><span class="mtk1">, </span><span class="mtk12">file1</span><span class="mtk1">);</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk12">zip</span><span class="mtk1">.</span><span class="mtk11">file</span><span class="mtk1">(</span><span class="mtk8">&quot;file2.txt&quot;</span><span class="mtk1">, </span><span class="mtk12">file2</span><span class="mtk1">);</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk4">const</span><span class="mtk1"> </span><span class="mtk12">content</span><span class="mtk1"> = </span><span class="mtk15">await</span><span class="mtk1"> </span><span class="mtk12">zip</span><span class="mtk1">.</span><span class="mtk11">generateAsync</span><span class="mtk1">({ </span><span class="mtk12">type:</span><span class="mtk1"> </span><span class="mtk8">&quot;blob&quot;</span><span class="mtk1"> });</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk4">const</span><span class="mtk1"> </span><span class="mtk12">contentUrl</span><span class="mtk1"> = </span><span class="mtk12">URL</span><span class="mtk1">.</span><span class="mtk11">createObjectURL</span><span class="mtk1">(</span><span class="mtk12">content</span><span class="mtk1">);</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk11">saveFile</span><span class="mtk1">(</span><span class="mtk12">contentUrl</span><span class="mtk1">, </span><span class="mtk8">&quot;zipContent.zip&quot;</span><span class="mtk1">);</span></span></span></code></pre> <p>Additionally, we can use the FileSaver’s <code>saveAs</code> function instead of the <code>saveFile</code> function we created earlier.</p> <h2 id="browser-saveas-configuration" style="position:relative;"><a href="#browser-saveas-configuration" aria-label="browser saveas configuration permalink" class="anchor before"><svg aria-hidden="true" focusable="false" height="16" version="1.1" viewBox="0 0 16 16" width="16"><path fill-rule="evenodd" d="M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z"></path></svg></a>Browser SaveAs configuration</h2> <p>Typically, when the file is downloaded, it will be saved in the download folder. However, the user can configure the browser to “saveAs” and choose a different location to save the file.</p> <p>In Chrome, the user can go to <code>Settings > Advanced > Downloads</code> and toggle the “Ask where to save each file before downloading” option.</p> <p>In Edge, the user can go to <code>Settings > Downloads</code> and toggle the “Ask me what to do with each download” option.</p> <p>In Firefox, the user can go to <code>Options > General > Files and Applications</code> and toggle the “Always ask you where to save files” option.</p> <p>In Safari, the user can go to <code>Preferences > General</code> and toggle the “File download location” option.</p> <h2 id="demo" style="position:relative;"><a href="#demo" aria-label="demo permalink" class="anchor before"><svg aria-hidden="true" focusable="false" height="16" version="1.1" viewBox="0 0 16 16" width="16"><path fill-rule="evenodd" d="M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z"></path></svg></a>Demo</h2> <iframe height="300" style="width: 100%;" scrolling="no" title="saveAs" src="https://codepen.io/muhimasri/embed/gOxRdEx?default-tab=html%2Cresult" frameborder="no" loading="lazy" allowtransparency="true" allowfullscreen="true"> See the Pen <a href="https://codepen.io/muhimasri/pen/gOxRdEx"> saveAs</a> by Muhi Masri (<a href="https://codepen.io/muhimasri">@muhimasri</a>) on <a href="https://codepen.io">CodePen</a>. </iframe> <h2 id="conclusion" style="position:relative;"><a href="#conclusion" aria-label="conclusion permalink" class="anchor before"><svg aria-hidden="true" focusable="false" height="16" version="1.1" viewBox="0 0 16 16" width="16"><path fill-rule="evenodd" d="M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z"></path></svg></a>Conclusion</h2> <p>Creating a custom solution to download and save files programmatically in JavaScript gives us flexibility and control but can be time-consuming and error-prone. Using a library like FileSaver.js saves us time and effort as the library is well-tested and maintained.</p> <p>Bye for now 👋</p> <style class="grvsc-styles"> .grvsc-container { overflow: auto; position: relative; -webkit-overflow-scrolling: touch; padding-top: 1rem; padding-top: var(--grvsc-padding-top, var(--grvsc-padding-v, 1rem)); padding-bottom: 1rem; padding-bottom: var(--grvsc-padding-bottom, var(--grvsc-padding-v, 1rem)); border-radius: 8px; border-radius: var(--grvsc-border-radius, 8px); font-feature-settings: normal; line-height: 1.4; } .grvsc-code { display: table; } .grvsc-line { display: table-row; box-sizing: border-box; width: 100%; position: relative; } .grvsc-line > * { position: relative; } .grvsc-gutter-pad { display: table-cell; padding-left: 0.75rem; padding-left: calc(var(--grvsc-padding-left, var(--grvsc-padding-h, 1.5rem)) / 2); } .grvsc-gutter { display: table-cell; -webkit-user-select: none; -moz-user-select: none; user-select: none; } .grvsc-gutter::before { content: attr(data-content); } .grvsc-source { display: table-cell; padding-left: 1.5rem; padding-left: var(--grvsc-padding-left, var(--grvsc-padding-h, 1.5rem)); padding-right: 1.5rem; padding-right: var(--grvsc-padding-right, var(--grvsc-padding-h, 1.5rem)); } .grvsc-source:empty::after { content: ' '; -webkit-user-select: none; -moz-user-select: none; user-select: none; } .grvsc-gutter + .grvsc-source { padding-left: 0.75rem; padding-left: calc(var(--grvsc-padding-left, var(--grvsc-padding-h, 1.5rem)) / 2); } /* Line transformer styles */ .grvsc-has-line-highlighting > .grvsc-code > .grvsc-line::before { content: ' '; position: absolute; width: 100%; } .grvsc-line-diff-add::before { background-color: var(--grvsc-line-diff-add-background-color, rgba(0, 255, 60, 0.2)); } .grvsc-line-diff-del::before { background-color: var(--grvsc-line-diff-del-background-color, rgba(255, 0, 20, 0.2)); } .grvsc-line-number { padding: 0 2px; text-align: right; opacity: 0.7; } .default-dark { background-color: #1E1E1E; color: #D4D4D4; } .default-dark .mtk4 { color: #569CD6; } .default-dark .mtk1 { color: #D4D4D4; } .default-dark .mtk11 { color: #DCDCAA; } .default-dark .mtk12 { color: #9CDCFE; } .default-dark .mtk8 { color: #CE9178; } .default-dark .mtk10 { color: #4EC9B0; } .default-dark .mtk15 { color: #C586C0; } .default-dark .mtk3 { color: #6A9955; } .default-dark .grvsc-line-highlighted::before { background-color: var(--grvsc-line-highlighted-background-color, rgba(255, 255, 255, 0.1)); box-shadow: inset var(--grvsc-line-highlighted-border-width, 4px) 0 0 0 var(--grvsc-line-highlighted-border-color, rgba(255, 255, 255, 0.5)); } </style><![CDATA[How to Create Dynamic States with React Redux]]>https://muhimasri.comhow-to-create-dynamic-states-with-react-reduxhttps://muhimasri.comhow-to-create-dynamic-states-with-react-redux<p><a href="https://redux.js.org/">Redux</a> is one of the most popular state management libraries in the React ecosystem. If you’re not familiar with the state management concept, it’s a layer added to your project that maintains and shares data across all components.</p> <p>In Redux, we typically create predefine states in the reducer and dispatch required updates to all subscribed components. For example:</p> <pre class="grvsc-container default-dark" data-language="jsx" data-index="0"><code class="grvsc-code"><span class="grvsc-line"><span class="grvsc-source"><span class="mtk4">const</span><span class="mtk1"> </span><span class="mtk12">initialState</span><span class="mtk1"> = {</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">title:</span><span class="mtk1"> </span><span class="mtk8">&quot;Do groceries&quot;</span><span class="mtk1">,</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">completed:</span><span class="mtk1"> </span><span class="mtk4">false</span><span class="mtk1">,</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1">};</span></span></span> <span class="grvsc-line"><span class="grvsc-source"></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk15">export</span><span class="mtk1"> </span><span class="mtk4">const</span><span class="mtk1"> </span><span class="mtk11">todoReducer</span><span class="mtk1"> = (</span><span class="mtk12">state</span><span class="mtk1"> = </span><span class="mtk12">initialState</span><span class="mtk1">, </span><span class="mtk12">action</span><span class="mtk1">) </span><span class="mtk4">=&gt;</span><span class="mtk1"> {</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk15">switch</span><span class="mtk1"> (</span><span class="mtk12">action</span><span class="mtk1">.</span><span class="mtk12">type</span><span class="mtk1">) {</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk15">case</span><span class="mtk1"> </span><span class="mtk8">&quot;UPDATE_TITLE&quot;</span><span class="mtk1">: {</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk15">return</span><span class="mtk1"> {</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> ...</span><span class="mtk12">state</span><span class="mtk1">,</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">title:</span><span class="mtk1"> </span><span class="mtk12">action</span><span class="mtk1">.</span><span class="mtk12">value</span><span class="mtk1">,</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> };</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> }</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk15">default</span><span class="mtk1">:</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk15">return</span><span class="mtk1"> </span><span class="mtk12">state</span><span class="mtk1">;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> }</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1">};</span></span></span></code></pre> <p>The above code is a simple reducer that updates a to-do item. Usually, we have a dynamic to-do list so instead, we can store a list and return a new immutable version when the user updates a value:</p> <pre class="grvsc-container default-dark" data-language="jsx" data-index="1"><code class="grvsc-code"><span class="grvsc-line"><span class="grvsc-source"><span class="mtk4">const</span><span class="mtk1"> </span><span class="mtk12">initialState</span><span class="mtk1"> = {</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">todoList:</span><span class="mtk1"> [</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> { </span><span class="mtk12">id:</span><span class="mtk1"> </span><span class="mtk7">1</span><span class="mtk1">, </span><span class="mtk12">title:</span><span class="mtk1"> </span><span class="mtk8">&quot;Do groceries&quot;</span><span class="mtk1">, </span><span class="mtk12">completed:</span><span class="mtk1"> </span><span class="mtk4">false</span><span class="mtk1"> },</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> { </span><span class="mtk12">id:</span><span class="mtk1"> </span><span class="mtk7">2</span><span class="mtk1">, </span><span class="mtk12">title:</span><span class="mtk1"> </span><span class="mtk8">&quot;Do shopping&quot;</span><span class="mtk1">, </span><span class="mtk12">completed:</span><span class="mtk1"> </span><span class="mtk4">false</span><span class="mtk1"> },</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> ],</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1">};</span></span></span> <span class="grvsc-line"><span class="grvsc-source"></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk15">export</span><span class="mtk1"> </span><span class="mtk4">const</span><span class="mtk1"> </span><span class="mtk11">todoReducer</span><span class="mtk1"> = (</span><span class="mtk12">state</span><span class="mtk1"> = </span><span class="mtk12">initialState</span><span class="mtk1">, </span><span class="mtk12">action</span><span class="mtk1">) </span><span class="mtk4">=&gt;</span><span class="mtk1"> {</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk15">switch</span><span class="mtk1"> (</span><span class="mtk12">action</span><span class="mtk1">.</span><span class="mtk12">type</span><span class="mtk1">) {</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk15">case</span><span class="mtk1"> </span><span class="mtk8">&quot;UPDATE_TODO_LIST&quot;</span><span class="mtk1">: {</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk15">return</span><span class="mtk1"> {</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> ...</span><span class="mtk12">state</span><span class="mtk1">,</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">todoList:</span><span class="mtk1"> [...</span><span class="mtk12">action</span><span class="mtk1">.</span><span class="mtk12">value</span><span class="mtk1">],</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> };</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> }</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk15">default</span><span class="mtk1">:</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk15">return</span><span class="mtk1"> </span><span class="mtk12">state</span><span class="mtk1">;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> }</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1">};</span></span></span></code></pre> <p>And the component will have a change handler that updates the item based on the id. Afterwards, it will dispatch the changes:</p> <pre class="grvsc-container grvsc-has-line-highlighting default-dark" data-language="jsx" data-index="2"><code class="grvsc-code"><span class="grvsc-line"><span class="grvsc-source"><span class="mtk15">export</span><span class="mtk1"> </span><span class="mtk4">const</span><span class="mtk1"> </span><span class="mtk11">TodoList</span><span class="mtk1"> = () </span><span class="mtk4">=&gt;</span><span class="mtk1"> {</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk4">const</span><span class="mtk1"> </span><span class="mtk12">todoList</span><span class="mtk1"> = </span><span class="mtk11">useSelector</span><span class="mtk1">(</span><span class="mtk12">state</span><span class="mtk1"> </span><span class="mtk4">=&gt;</span><span class="mtk1"> </span><span class="mtk12">state</span><span class="mtk1">.</span><span class="mtk12">todoList</span><span class="mtk1">)</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk4">const</span><span class="mtk1"> </span><span class="mtk12">dispatch</span><span class="mtk1"> = </span><span class="mtk11">useDispatch</span><span class="mtk1">();</span></span></span> <span class="grvsc-line"><span class="grvsc-source"></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk4">function</span><span class="mtk1"> </span><span class="mtk11">changeHandler</span><span class="mtk1">(</span><span class="mtk12">e</span><span class="mtk1">, </span><span class="mtk12">id</span><span class="mtk1">) {</span></span></span> <span class="grvsc-line grvsc-line-highlighted"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk4">const</span><span class="mtk1"> </span><span class="mtk12">todoItem</span><span class="mtk1"> = </span><span class="mtk12">todoList</span><span class="mtk1">.</span><span class="mtk11">find</span><span class="mtk1">(</span><span class="mtk12">item</span><span class="mtk1"> </span><span class="mtk4">=&gt;</span><span class="mtk1"> </span><span class="mtk12">item</span><span class="mtk1">.</span><span class="mtk12">id</span><span class="mtk1"> === </span><span class="mtk12">id</span><span class="mtk1">);</span></span></span> <span class="grvsc-line grvsc-line-highlighted"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">todoItem</span><span class="mtk1">.</span><span class="mtk12">title</span><span class="mtk1"> = </span><span class="mtk12">e</span><span class="mtk1">.</span><span class="mtk12">target</span><span class="mtk1">.</span><span class="mtk12">value</span><span class="mtk1">;</span></span></span> <span class="grvsc-line grvsc-line-highlighted"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk11">dispatch</span><span class="mtk1">({</span></span></span> <span class="grvsc-line grvsc-line-highlighted"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">type:</span><span class="mtk1"> </span><span class="mtk8">&quot;UPDATE_TODO_LIST&quot;</span><span class="mtk1">,</span></span></span> <span class="grvsc-line grvsc-line-highlighted"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">value:</span><span class="mtk1"> </span><span class="mtk12">todoList</span><span class="mtk1">,</span></span></span> <span class="grvsc-line grvsc-line-highlighted"><span class="grvsc-source"><span class="mtk1"> });</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> }</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk15">return</span><span class="mtk1"> (</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk17">&lt;</span><span class="mtk4">article</span><span class="mtk17">&gt;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk4">{</span><span class="mtk12">todoList</span><span class="mtk1">.</span><span class="mtk11">map</span><span class="mtk1">((</span><span class="mtk12">item</span><span class="mtk1">) </span><span class="mtk4">=&gt;</span><span class="mtk1"> (</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk17">&lt;</span><span class="mtk4">section</span><span class="mtk1"> </span><span class="mtk12">key</span><span class="mtk1">=</span><span class="mtk4">{</span><span class="mtk12">item</span><span class="mtk1">.</span><span class="mtk12">id</span><span class="mtk4">}</span><span class="mtk17">&gt;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk17">&lt;</span><span class="mtk4">input</span><span class="mtk1"> </span><span class="mtk12">type</span><span class="mtk1">=</span><span class="mtk8">&quot;text&quot;</span><span class="mtk1"> </span><span class="mtk12">value</span><span class="mtk1">=</span><span class="mtk4">{</span><span class="mtk12">item</span><span class="mtk1">.</span><span class="mtk12">title</span><span class="mtk4">}</span><span class="mtk1"> </span><span class="mtk12">onChange</span><span class="mtk1">=</span><span class="mtk4">{</span><span class="mtk1">(</span><span class="mtk12">e</span><span class="mtk1">) </span><span class="mtk4">=&gt;</span><span class="mtk1"> </span><span class="mtk11">changeHandler</span><span class="mtk1">(</span><span class="mtk12">e</span><span class="mtk1">, </span><span class="mtk12">item</span><span class="mtk1">.</span><span class="mtk12">id</span><span class="mtk1">)</span><span class="mtk4">}</span><span class="mtk1"> </span><span class="mtk17">/&gt;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk17">&lt;/</span><span class="mtk4">section</span><span class="mtk17">&gt;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> ))</span><span class="mtk4">}</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk17">&lt;/</span><span class="mtk4">article</span><span class="mtk17">&gt;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> );</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1">};</span></span></span></code></pre> <p>Although this approach works just fine and React’s virtual DOM is efficient when re-rendering lists, we might get performance issues as the application grows bigger and the data structure becomes more complex. Especially when the component is a multi-column editable grid that contains nested children.</p> <p>In this tutorial, we will explain how to dynamically create and update states in Redux that will enable us to surgically edit data in a grid without re-rendering the whole list.</p> <p><em>The tutorial assumes that you have a basic understanding of Redux. If not, please go through the overview on the <a href="https://redux.js.org/tutorials/essentials/part-1-overview-concepts">official site</a>.</em></p> <h2 id="create-a-basic-todo-component" style="position:relative;"><a href="#create-a-basic-todo-component" aria-label="create a basic todo component permalink" class="anchor before"><svg aria-hidden="true" focusable="false" height="16" version="1.1" viewBox="0 0 16 16" width="16"><path fill-rule="evenodd" d="M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z"></path></svg></a>Create a basic todo component</h2> <p>We are going to create a component with a real API call and display the list in a table element. Let’s go through the required steps:</p> <ol> <li>Create an <code>async</code> function to trigger an API call. We’re going to use <a href="https://jsonplaceholder.typicode.com/">{JSON} Placeholder</a> service that returns a fake to-do list.</li> </ol> <pre class="grvsc-container default-dark" data-language="jsx" data-index="3"><code class="grvsc-code"><span class="grvsc-line"><span class="grvsc-source"><span class="mtk4">async</span><span class="mtk1"> </span><span class="mtk4">function</span><span class="mtk1"> </span><span class="mtk11">getTodoList</span><span class="mtk1">() {</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk4">const</span><span class="mtk1"> </span><span class="mtk12">response</span><span class="mtk1"> = </span><span class="mtk15">await</span><span class="mtk1"> </span><span class="mtk11">fetch</span><span class="mtk1">(</span><span class="mtk8">&quot;https://jsonplaceholder.typicode.com/todos&quot;</span><span class="mtk1">);</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1">}</span></span></span></code></pre> <ol start="2"> <li>Add the API function in the <code>useEffect</code> hook to be triggered when the component is ready and then update the <code>todoList</code> state</li> </ol> <pre class="grvsc-container default-dark" data-language="jsx" data-index="4"><code class="grvsc-code"><span class="grvsc-line"><span class="grvsc-source"><span class="mtk11">useEffect</span><span class="mtk1">(() </span><span class="mtk4">=&gt;</span><span class="mtk1"> {</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk4">async</span><span class="mtk1"> </span><span class="mtk4">function</span><span class="mtk1"> </span><span class="mtk11">getTodoList</span><span class="mtk1">() {</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk4">const</span><span class="mtk1"> </span><span class="mtk12">response</span><span class="mtk1"> = </span><span class="mtk15">await</span><span class="mtk1"> </span><span class="mtk11">fetch</span><span class="mtk1">(</span><span class="mtk8">&quot;https://jsonplaceholder.typicode.com/todos&quot;</span><span class="mtk1">);</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk11">setTodoList</span><span class="mtk1">(</span><span class="mtk15">await</span><span class="mtk1"> </span><span class="mtk12">response</span><span class="mtk1">.</span><span class="mtk11">json</span><span class="mtk1">());</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> }</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk11">getTodoList</span><span class="mtk1">();</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1">}, []);</span></span></span></code></pre> <ol start="3"> <li>Create a <code>table</code> element and loop through the data to return dynamic <code>tr</code> and <code>td</code> elements</li> </ol> <pre class="grvsc-container default-dark" data-language="jsx" data-index="5"><code class="grvsc-code"><span class="grvsc-line"><span class="grvsc-source"><span class="mtk17">&lt;</span><span class="mtk4">table</span><span class="mtk17">&gt;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk17">&lt;</span><span class="mtk4">thead</span><span class="mtk17">&gt;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk17">&lt;</span><span class="mtk4">tr</span><span class="mtk17">&gt;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk17">&lt;</span><span class="mtk4">th</span><span class="mtk17">&gt;</span><span class="mtk1">Task</span><span class="mtk17">&lt;/</span><span class="mtk4">th</span><span class="mtk17">&gt;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk17">&lt;</span><span class="mtk4">th</span><span class="mtk17">&gt;</span><span class="mtk1">Completed</span><span class="mtk17">&lt;/</span><span class="mtk4">th</span><span class="mtk17">&gt;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk17">&lt;/</span><span class="mtk4">tr</span><span class="mtk17">&gt;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk17">&lt;/</span><span class="mtk4">thead</span><span class="mtk17">&gt;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk17">&lt;</span><span class="mtk4">tbody</span><span class="mtk17">&gt;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk4">{</span><span class="mtk12">todoList</span><span class="mtk1">.</span><span class="mtk11">map</span><span class="mtk1">((</span><span class="mtk12">item</span><span class="mtk1">) </span><span class="mtk4">=&gt;</span><span class="mtk1"> (</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk17">&lt;</span><span class="mtk4">tr</span><span class="mtk1"> </span><span class="mtk12">key</span><span class="mtk1">=</span><span class="mtk4">{</span><span class="mtk12">item</span><span class="mtk1">.</span><span class="mtk12">id</span><span class="mtk4">}</span><span class="mtk17">&gt;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk17">&lt;</span><span class="mtk4">td</span><span class="mtk17">&gt;</span><span class="mtk4">{</span><span class="mtk12">item</span><span class="mtk1">.</span><span class="mtk12">title</span><span class="mtk4">}</span><span class="mtk17">&lt;/</span><span class="mtk4">td</span><span class="mtk17">&gt;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk17">&lt;</span><span class="mtk4">td</span><span class="mtk17">&gt;</span><span class="mtk4">{</span><span class="mtk12">item</span><span class="mtk1">.</span><span class="mtk12">completed</span><span class="mtk4">}</span><span class="mtk17">&lt;/</span><span class="mtk4">td</span><span class="mtk17">&gt;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk17">&lt;/</span><span class="mtk4">tr</span><span class="mtk17">&gt;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> ))</span><span class="mtk4">}</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk17">&lt;/</span><span class="mtk4">tbody</span><span class="mtk17">&gt;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk17">&lt;/</span><span class="mtk4">table</span><span class="mtk17">&gt;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"></span></span></code></pre> <h5 id="full-component" style="position:relative;"><a href="#full-component" aria-label="full component permalink" class="anchor before"><svg aria-hidden="true" focusable="false" height="16" version="1.1" viewBox="0 0 16 16" width="16"><path fill-rule="evenodd" d="M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z"></path></svg></a>Full component</h5> <pre class="grvsc-container default-dark" data-language="jsx" data-index="6"><code class="grvsc-code"><span class="grvsc-line"><span class="grvsc-source"><span class="mtk15">import</span><span class="mtk1"> { </span><span class="mtk12">useState</span><span class="mtk1">, </span><span class="mtk12">useEffect</span><span class="mtk1"> } </span><span class="mtk15">from</span><span class="mtk1"> </span><span class="mtk8">&quot;react&quot;</span><span class="mtk1">;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk15">import</span><span class="mtk1"> </span><span class="mtk8">&quot;./todo.css&quot;</span><span class="mtk1">;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk15">export</span><span class="mtk1"> </span><span class="mtk4">const</span><span class="mtk1"> </span><span class="mtk11">TodoList</span><span class="mtk1"> = () </span><span class="mtk4">=&gt;</span><span class="mtk1"> {</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk4">const</span><span class="mtk1"> [</span><span class="mtk12">todoList</span><span class="mtk1">, </span><span class="mtk12">setTodoList</span><span class="mtk1">] = </span><span class="mtk11">useState</span><span class="mtk1">([]);</span></span></span> <span class="grvsc-line"><span class="grvsc-source"></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk11">useEffect</span><span class="mtk1">(() </span><span class="mtk4">=&gt;</span><span class="mtk1"> {</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk4">async</span><span class="mtk1"> </span><span class="mtk4">function</span><span class="mtk1"> </span><span class="mtk11">getTodoList</span><span class="mtk1">() {</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk4">const</span><span class="mtk1"> </span><span class="mtk12">response</span><span class="mtk1"> = </span><span class="mtk15">await</span><span class="mtk1"> </span><span class="mtk11">fetch</span><span class="mtk1">(</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk8">&quot;https://jsonplaceholder.typicode.com/todos&quot;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> );</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk11">setTodoList</span><span class="mtk1">(</span><span class="mtk15">await</span><span class="mtk1"> </span><span class="mtk12">response</span><span class="mtk1">.</span><span class="mtk11">json</span><span class="mtk1">());</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> }</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk11">getTodoList</span><span class="mtk1">();</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> }, []);</span></span></span> <span class="grvsc-line"><span class="grvsc-source"></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk15">return</span><span class="mtk1"> (</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk17">&lt;</span><span class="mtk4">table</span><span class="mtk17">&gt;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk17">&lt;</span><span class="mtk4">thead</span><span class="mtk17">&gt;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk17">&lt;</span><span class="mtk4">tr</span><span class="mtk17">&gt;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk17">&lt;</span><span class="mtk4">th</span><span class="mtk17">&gt;</span><span class="mtk1">Task</span><span class="mtk17">&lt;/</span><span class="mtk4">th</span><span class="mtk17">&gt;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk17">&lt;</span><span class="mtk4">th</span><span class="mtk17">&gt;</span><span class="mtk1">Completed</span><span class="mtk17">&lt;/</span><span class="mtk4">th</span><span class="mtk17">&gt;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk17">&lt;/</span><span class="mtk4">tr</span><span class="mtk17">&gt;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk17">&lt;/</span><span class="mtk4">thead</span><span class="mtk17">&gt;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk17">&lt;</span><span class="mtk4">tbody</span><span class="mtk17">&gt;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk4">{</span><span class="mtk12">todoList</span><span class="mtk1">.</span><span class="mtk11">map</span><span class="mtk1">((</span><span class="mtk12">item</span><span class="mtk1">) </span><span class="mtk4">=&gt;</span><span class="mtk1"> (</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk17">&lt;</span><span class="mtk4">tr</span><span class="mtk1"> </span><span class="mtk12">key</span><span class="mtk1">=</span><span class="mtk4">{</span><span class="mtk12">item</span><span class="mtk1">.</span><span class="mtk12">id</span><span class="mtk4">}</span><span class="mtk17">&gt;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk17">&lt;</span><span class="mtk4">td</span><span class="mtk17">&gt;</span><span class="mtk4">{</span><span class="mtk12">item</span><span class="mtk1">.</span><span class="mtk12">title</span><span class="mtk4">}</span><span class="mtk17">&lt;/</span><span class="mtk4">td</span><span class="mtk17">&gt;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk17">&lt;</span><span class="mtk4">td</span><span class="mtk17">&gt;</span><span class="mtk4">{</span><span class="mtk12">item</span><span class="mtk1">.</span><span class="mtk12">completed</span><span class="mtk4">}</span><span class="mtk17">&lt;/</span><span class="mtk4">td</span><span class="mtk17">&gt;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk17">&lt;/</span><span class="mtk4">tr</span><span class="mtk17">&gt;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> ))</span><span class="mtk4">}</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk17">&lt;/</span><span class="mtk4">tbody</span><span class="mtk17">&gt;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk17">&lt;/</span><span class="mtk4">table</span><span class="mtk17">&gt;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> );</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1">};</span></span></span></code></pre> <p>So far, we have a simple two-column and read-only to-do list. Keeping reading, it will get more exciting I promise 😊</p> <h2 id="add-dynamic-states" style="position:relative;"><a href="#add-dynamic-states" aria-label="add dynamic states permalink" class="anchor before"><svg aria-hidden="true" focusable="false" height="16" version="1.1" viewBox="0 0 16 16" width="16"><path fill-rule="evenodd" d="M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z"></path></svg></a>Add dynamic states</h2> <p>The key to updating a specific item without re-rendering the whole list is to create dynamic states based on ids (similar to a dictionary). The initial state in the reducer will be an empty object and as soon as the data is ready in the component we’ll re-generate the data as a key/value based object, for example:</p> <pre class="grvsc-container default-dark" data-language="jsx" data-index="7"><code class="grvsc-code"><span class="grvsc-line"><span class="grvsc-source"><span class="mtk1">{</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk7">1</span><span class="mtk1">: {</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">title:</span><span class="mtk1"> </span><span class="mtk8">&#39;Do groceries&#39;</span><span class="mtk1">,</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">completed:</span><span class="mtk1"> </span><span class="mtk4">false</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> },</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk7">2</span><span class="mtk1">: {</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">title:</span><span class="mtk1"> </span><span class="mtk8">&#39;Do shopping&#39;</span><span class="mtk1">,</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">completed:</span><span class="mtk1"> </span><span class="mtk4">true</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> },</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk7">3</span><span class="mtk1">: {</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">title:</span><span class="mtk1"> </span><span class="mtk8">&#39;Go to the gym&#39;</span><span class="mtk1">,</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">completed:</span><span class="mtk1"> </span><span class="mtk4">false</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> }</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1">}</span></span></span></code></pre> <p>Let’s create a reducer with a new action type that updates the data list:</p> <pre class="grvsc-container grvsc-has-line-highlighting default-dark" data-language="jsx" data-index="8"><code class="grvsc-code"><span class="grvsc-line"><span class="grvsc-source"><span class="mtk4">const</span><span class="mtk1"> </span><span class="mtk12">initialState</span><span class="mtk1"> = {};</span></span></span> <span class="grvsc-line"><span class="grvsc-source"></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk15">export</span><span class="mtk1"> </span><span class="mtk4">const</span><span class="mtk1"> </span><span class="mtk11">todoReducer</span><span class="mtk1"> = (</span><span class="mtk12">state</span><span class="mtk1"> = </span><span class="mtk12">initialState</span><span class="mtk1">, </span><span class="mtk12">action</span><span class="mtk1">) </span><span class="mtk4">=&gt;</span><span class="mtk1"> {</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk15">switch</span><span class="mtk1"> (</span><span class="mtk12">action</span><span class="mtk1">.</span><span class="mtk12">type</span><span class="mtk1">) {</span></span></span> <span class="grvsc-line grvsc-line-highlighted"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk15">case</span><span class="mtk1"> </span><span class="mtk8">&quot;UPDATE_TODO_LIST&quot;</span><span class="mtk1">: {</span></span></span> <span class="grvsc-line grvsc-line-highlighted"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk15">return</span><span class="mtk1"> </span><span class="mtk12">action</span><span class="mtk1">.</span><span class="mtk12">value</span><span class="mtk1">.</span><span class="mtk11">reduce</span><span class="mtk1">(</span></span></span> <span class="grvsc-line grvsc-line-highlighted"><span class="grvsc-source"><span class="mtk1"> (</span><span class="mtk12">accumulator</span><span class="mtk1">, </span><span class="mtk12">current</span><span class="mtk1">) </span><span class="mtk4">=&gt;</span><span class="mtk1"> ({ ...</span><span class="mtk12">accumulator</span><span class="mtk1">, </span><span class="mtk12">[current.id]:</span><span class="mtk1"> </span><span class="mtk12">current</span><span class="mtk1"> }),</span></span></span> <span class="grvsc-line grvsc-line-highlighted"><span class="grvsc-source"><span class="mtk1"> {}</span></span></span> <span class="grvsc-line grvsc-line-highlighted"><span class="grvsc-source"><span class="mtk1"> );</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> }</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk15">default</span><span class="mtk1">:</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk15">return</span><span class="mtk1"> </span><span class="mtk12">state</span><span class="mtk1">;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> }</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1">};</span></span></span></code></pre> <p>As you can see above, we used the array’s <code>reduce</code> function to re-generate the data to an id-based object.</p> <p>Next, in the <code>TodoList</code> component, we’ll dispatch the data right after the API call.</p> <pre class="grvsc-container grvsc-has-line-highlighting default-dark" data-language="jsx" data-index="9"><code class="grvsc-code"><span class="grvsc-line"><span class="grvsc-source"><span class="mtk11">useEffect</span><span class="mtk1">(() </span><span class="mtk4">=&gt;</span><span class="mtk1"> {</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk4">async</span><span class="mtk1"> </span><span class="mtk4">function</span><span class="mtk1"> </span><span class="mtk11">getTodoList</span><span class="mtk1">() {</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk4">const</span><span class="mtk1"> </span><span class="mtk12">response</span><span class="mtk1"> = </span><span class="mtk15">await</span><span class="mtk1"> </span><span class="mtk11">fetch</span><span class="mtk1">(</span><span class="mtk8">&quot;https://jsonplaceholder.typicode.com/todos&quot;</span><span class="mtk1">);</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk4">const</span><span class="mtk1"> </span><span class="mtk12">data</span><span class="mtk1"> = </span><span class="mtk15">await</span><span class="mtk1"> </span><span class="mtk12">response</span><span class="mtk1">.</span><span class="mtk11">json</span><span class="mtk1">();</span></span></span> <span class="grvsc-line grvsc-line-highlighted"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk11">dispatch</span><span class="mtk1">({</span></span></span> <span class="grvsc-line grvsc-line-highlighted"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">type:</span><span class="mtk1"> </span><span class="mtk8">&quot;UPDATE_TODO_LIST&quot;</span><span class="mtk1">,</span></span></span> <span class="grvsc-line grvsc-line-highlighted"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">value:</span><span class="mtk1"> </span><span class="mtk12">data</span><span class="mtk1">,</span></span></span> <span class="grvsc-line grvsc-line-highlighted"><span class="grvsc-source"><span class="mtk1"> });</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk11">setTodoList</span><span class="mtk1">(</span><span class="mtk12">data</span><span class="mtk1">);</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> }</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk11">getTodoList</span><span class="mtk1">();</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1">}, []);</span></span></span></code></pre> <p>As soon as the component is ready, the reducer will convert the to-do list to a new object and update the state. Keep in mind that the process of calling the API and converting the data will only happen once.</p> <h2 id="update-input-fields" style="position:relative;"><a href="#update-input-fields" aria-label="update input fields permalink" class="anchor before"><svg aria-hidden="true" focusable="false" height="16" version="1.1" viewBox="0 0 16 16" width="16"><path fill-rule="evenodd" d="M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z"></path></svg></a>Update input fields</h2> <p>Updating a specific input field in the <code>table</code> list is now possible without re-rendering the <code>Todo</code> component. We first need to add a new action type in the reducer that will update a specific id and field as follows:</p> <pre class="grvsc-container grvsc-has-line-highlighting default-dark" data-language="jsx" data-index="10"><code class="grvsc-code"><span class="grvsc-line"><span class="grvsc-source"><span class="mtk4">const</span><span class="mtk1"> </span><span class="mtk12">initialState</span><span class="mtk1"> = {};</span></span></span> <span class="grvsc-line"><span class="grvsc-source"></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk15">export</span><span class="mtk1"> </span><span class="mtk4">const</span><span class="mtk1"> </span><span class="mtk11">todoReducer</span><span class="mtk1"> = (</span><span class="mtk12">state</span><span class="mtk1"> = </span><span class="mtk12">initialState</span><span class="mtk1">, </span><span class="mtk12">action</span><span class="mtk1">) </span><span class="mtk4">=&gt;</span><span class="mtk1"> {</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk15">switch</span><span class="mtk1"> (</span><span class="mtk12">action</span><span class="mtk1">.</span><span class="mtk12">type</span><span class="mtk1">) {</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk15">case</span><span class="mtk1"> </span><span class="mtk8">&quot;UPDATE_TODO_LIST&quot;</span><span class="mtk1">: {</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk15">return</span><span class="mtk1"> </span><span class="mtk12">action</span><span class="mtk1">.</span><span class="mtk12">value</span><span class="mtk1">.</span><span class="mtk11">reduce</span><span class="mtk1">(</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> (</span><span class="mtk12">accumulator</span><span class="mtk1">, </span><span class="mtk12">current</span><span class="mtk1">) </span><span class="mtk4">=&gt;</span><span class="mtk1"> ({ ...</span><span class="mtk12">accumulator</span><span class="mtk1">, </span><span class="mtk12">[current.id]:</span><span class="mtk1"> </span><span class="mtk12">current</span><span class="mtk1"> }),</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> {}</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> );</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> }</span></span></span> <span class="grvsc-line grvsc-line-highlighted"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk15">case</span><span class="mtk1"> </span><span class="mtk8">&quot;UPDATE_TODO_FIELD&quot;</span><span class="mtk1">: {</span></span></span> <span class="grvsc-line grvsc-line-highlighted"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk15">return</span><span class="mtk1"> {</span></span></span> <span class="grvsc-line grvsc-line-highlighted"><span class="grvsc-source"><span class="mtk1"> ...</span><span class="mtk12">state</span><span class="mtk1">,</span></span></span> <span class="grvsc-line grvsc-line-highlighted"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">[action.id]:</span><span class="mtk1"> {</span></span></span> <span class="grvsc-line grvsc-line-highlighted"><span class="grvsc-source"><span class="mtk1"> ...</span><span class="mtk12">state</span><span class="mtk1">[</span><span class="mtk12">action</span><span class="mtk1">.</span><span class="mtk12">id</span><span class="mtk1">],</span></span></span> <span class="grvsc-line grvsc-line-highlighted"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">[action.field]:</span><span class="mtk1"> </span><span class="mtk12">action</span><span class="mtk1">.</span><span class="mtk12">value</span><span class="mtk1">,</span></span></span> <span class="grvsc-line grvsc-line-highlighted"><span class="grvsc-source"><span class="mtk1"> },</span></span></span> <span class="grvsc-line grvsc-line-highlighted"><span class="grvsc-source"><span class="mtk1"> };</span></span></span> <span class="grvsc-line grvsc-line-highlighted"><span class="grvsc-source"><span class="mtk1"> }</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk15">default</span><span class="mtk1">:</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk15">return</span><span class="mtk1"> </span><span class="mtk12">state</span><span class="mtk1">;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> }</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1">};</span></span></span></code></pre> <p>Using JavaScript’s dynamic key assignment and spread operator, we can modify the field of a specific to-do item. What is left now is to create custom input field components for both the “title” and “completed” properties. Let’s go through the required steps:</p> <ol> <li>Add two separate components, a checkbox for the “completed” field and an input text for the “title” field:</li> </ol> <pre class="grvsc-container default-dark" data-language="jsx" data-index="11"><code class="grvsc-code"><span class="grvsc-line"><span class="grvsc-source"><span class="mtk4">const</span><span class="mtk1"> </span><span class="mtk11">TextBox</span><span class="mtk1"> = () </span><span class="mtk4">=&gt;</span><span class="mtk1"> {</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk15">return</span><span class="mtk1"> </span><span class="mtk17">&lt;</span><span class="mtk4">input</span><span class="mtk1"> </span><span class="mtk12">type</span><span class="mtk1">=</span><span class="mtk8">&quot;text&quot;</span><span class="mtk1"> </span><span class="mtk17">/&gt;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1">}</span></span></span> <span class="grvsc-line"><span class="grvsc-source"></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk4">const</span><span class="mtk1"> </span><span class="mtk11">CheckBox</span><span class="mtk1"> = () </span><span class="mtk4">=&gt;</span><span class="mtk1"> {</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk15">return</span><span class="mtk1"> </span><span class="mtk17">&lt;</span><span class="mtk4">input</span><span class="mtk1"> </span><span class="mtk12">type</span><span class="mtk1">=</span><span class="mtk8">&quot;checkbox&quot;</span><span class="mtk1"> </span><span class="mtk17">/&gt;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1">}</span></span></span></code></pre> <ol start="2"> <li>Add <code>useSelector</code> that subscribes to an id and field:</li> </ol> <pre class="grvsc-container grvsc-has-line-highlighting default-dark" data-language="jsx" data-index="12"><code class="grvsc-code"><span class="grvsc-line"><span class="grvsc-source"><span class="mtk4">const</span><span class="mtk1"> </span><span class="mtk11">TextBox</span><span class="mtk1"> = ({</span><span class="mtk12">id</span><span class="mtk1">}) </span><span class="mtk4">=&gt;</span><span class="mtk1"> {</span></span></span> <span class="grvsc-line grvsc-line-highlighted"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk4">const</span><span class="mtk1"> </span><span class="mtk12">value</span><span class="mtk1"> = </span><span class="mtk11">useSelector</span><span class="mtk1">(</span><span class="mtk12">state</span><span class="mtk1"> </span><span class="mtk4">=&gt;</span><span class="mtk1"> </span><span class="mtk12">state</span><span class="mtk1">[</span><span class="mtk12">id</span><span class="mtk1">]?.</span><span class="mtk12">title</span><span class="mtk1">)</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk15">return</span><span class="mtk1"> </span><span class="mtk17">&lt;</span><span class="mtk4">input</span><span class="mtk1"> </span><span class="mtk12">type</span><span class="mtk1">=</span><span class="mtk8">&quot;text&quot;</span><span class="mtk1"> </span><span class="mtk12">value</span><span class="mtk1">=</span><span class="mtk4">{</span><span class="mtk12">value</span><span class="mtk4">}</span><span class="mtk1"> </span><span class="mtk17">/&gt;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1">}</span></span></span> <span class="grvsc-line"><span class="grvsc-source"></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk4">const</span><span class="mtk1"> </span><span class="mtk11">CheckBox</span><span class="mtk1"> = ({</span><span class="mtk12">id</span><span class="mtk1">}) </span><span class="mtk4">=&gt;</span><span class="mtk1"> {</span></span></span> <span class="grvsc-line grvsc-line-highlighted"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk4">const</span><span class="mtk1"> </span><span class="mtk12">value</span><span class="mtk1"> = </span><span class="mtk11">useSelector</span><span class="mtk1">(</span><span class="mtk12">state</span><span class="mtk1"> </span><span class="mtk4">=&gt;</span><span class="mtk1"> </span><span class="mtk12">state</span><span class="mtk1">[</span><span class="mtk12">id</span><span class="mtk1">]?.</span><span class="mtk12">completed</span><span class="mtk1">);</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk15">return</span><span class="mtk1"> </span><span class="mtk17">&lt;</span><span class="mtk4">input</span><span class="mtk1"> </span><span class="mtk12">type</span><span class="mtk1">=</span><span class="mtk8">&quot;checkbox&quot;</span><span class="mtk1"> </span><span class="mtk12">value</span><span class="mtk1">=</span><span class="mtk4">{</span><span class="mtk12">value</span><span class="mtk4">}</span><span class="mtk1"> </span><span class="mtk17">/&gt;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1">}</span></span></span></code></pre> <p><em>We’re accessing ids directly from the state (<code>state[id]</code>) as we only have one main reducer in this example but in a real-life scenario, we’d probably have multiple combined reducers that can be accessed by name (<code>state.myReducerName[id]</code>)</em></p> <ol start="3"> <li>Dispatch input changes to the new action that we created in the previous step and pass it the id, field, and value:</li> </ol> <pre class="grvsc-container grvsc-has-line-highlighting default-dark" data-language="jsx" data-index="13"><code class="grvsc-code"><span class="grvsc-line"><span class="grvsc-source"><span class="mtk4">const</span><span class="mtk1"> </span><span class="mtk11">TextBox</span><span class="mtk1"> = ({</span><span class="mtk12">id</span><span class="mtk1">}) </span><span class="mtk4">=&gt;</span><span class="mtk1"> {</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk4">const</span><span class="mtk1"> </span><span class="mtk12">value</span><span class="mtk1"> = </span><span class="mtk11">useSelector</span><span class="mtk1">(</span><span class="mtk12">state</span><span class="mtk1"> </span><span class="mtk4">=&gt;</span><span class="mtk1"> </span><span class="mtk12">state</span><span class="mtk1">[</span><span class="mtk12">id</span><span class="mtk1">]?.</span><span class="mtk12">title</span><span class="mtk1">)</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk4">const</span><span class="mtk1"> </span><span class="mtk12">dispatch</span><span class="mtk1"> = </span><span class="mtk11">useDispatch</span><span class="mtk1">();</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk4">function</span><span class="mtk1"> </span><span class="mtk11">changeHandler</span><span class="mtk1">(</span><span class="mtk12">e</span><span class="mtk1">) {</span></span></span> <span class="grvsc-line grvsc-line-highlighted"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk11">dispatch</span><span class="mtk1">({</span></span></span> <span class="grvsc-line grvsc-line-highlighted"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">type:</span><span class="mtk1"> </span><span class="mtk8">&#39;UPDATE_TODO_FIELD&#39;</span><span class="mtk1">,</span></span></span> <span class="grvsc-line grvsc-line-highlighted"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">id</span><span class="mtk1">, </span><span class="mtk12">value:</span><span class="mtk1"> </span><span class="mtk12">e</span><span class="mtk1">.</span><span class="mtk12">target</span><span class="mtk1">.</span><span class="mtk12">value</span><span class="mtk1">, </span><span class="mtk12">field:</span><span class="mtk1"> </span><span class="mtk8">&#39;title&#39;</span></span></span> <span class="grvsc-line grvsc-line-highlighted"><span class="grvsc-source"><span class="mtk1"> })</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> }</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk15">return</span><span class="mtk1"> </span><span class="mtk17">&lt;</span><span class="mtk4">input</span><span class="mtk1"> </span><span class="mtk12">type</span><span class="mtk1">=</span><span class="mtk8">&quot;text&quot;</span><span class="mtk1"> </span><span class="mtk12">value</span><span class="mtk1">=</span><span class="mtk4">{</span><span class="mtk12">value</span><span class="mtk4">}</span><span class="mtk1"> </span><span class="mtk12">onChange</span><span class="mtk1">=</span><span class="mtk4">{</span><span class="mtk12">changeHandler</span><span class="mtk4">}</span><span class="mtk1"> </span><span class="mtk17">/&gt;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1">}</span></span></span> <span class="grvsc-line"><span class="grvsc-source"></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk4">const</span><span class="mtk1"> </span><span class="mtk11">CheckBox</span><span class="mtk1"> = ({</span><span class="mtk12">id</span><span class="mtk1">}) </span><span class="mtk4">=&gt;</span><span class="mtk1"> {</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk4">const</span><span class="mtk1"> </span><span class="mtk12">value</span><span class="mtk1"> = </span><span class="mtk11">useSelector</span><span class="mtk1">(</span><span class="mtk12">state</span><span class="mtk1"> </span><span class="mtk4">=&gt;</span><span class="mtk1"> </span><span class="mtk12">state</span><span class="mtk1">[</span><span class="mtk12">id</span><span class="mtk1">]?.</span><span class="mtk12">completed</span><span class="mtk1">);</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk4">const</span><span class="mtk1"> </span><span class="mtk12">dispatch</span><span class="mtk1"> = </span><span class="mtk11">useDispatch</span><span class="mtk1">();</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk4">function</span><span class="mtk1"> </span><span class="mtk11">changeHandler</span><span class="mtk1">(</span><span class="mtk12">e</span><span class="mtk1">) {</span></span></span> <span class="grvsc-line grvsc-line-highlighted"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk11">dispatch</span><span class="mtk1">({</span></span></span> <span class="grvsc-line grvsc-line-highlighted"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">type:</span><span class="mtk1"> </span><span class="mtk8">&#39;UPDATE_TODO_FIELD&#39;</span><span class="mtk1">,</span></span></span> <span class="grvsc-line grvsc-line-highlighted"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">id</span><span class="mtk1">, </span><span class="mtk12">value:</span><span class="mtk1"> </span><span class="mtk12">e</span><span class="mtk1">.</span><span class="mtk12">target</span><span class="mtk1">.</span><span class="mtk12">checked</span><span class="mtk1">, </span><span class="mtk12">field:</span><span class="mtk1"> </span><span class="mtk8">&#39;completed&#39;</span></span></span> <span class="grvsc-line grvsc-line-highlighted"><span class="grvsc-source"><span class="mtk1"> })</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> }</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk15">return</span><span class="mtk1"> </span><span class="mtk17">&lt;</span><span class="mtk4">input</span><span class="mtk1"> </span><span class="mtk12">type</span><span class="mtk1">=</span><span class="mtk8">&quot;checkbox&quot;</span><span class="mtk1"> </span><span class="mtk12">value</span><span class="mtk1">=</span><span class="mtk4">{</span><span class="mtk12">value</span><span class="mtk4">}</span><span class="mtk1"> </span><span class="mtk12">onChange</span><span class="mtk1">=</span><span class="mtk4">{</span><span class="mtk12">changeHandler</span><span class="mtk4">}</span><span class="mtk1"> </span><span class="mtk17">/&gt;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1">}</span></span></span></code></pre> <h5 id="full-component-1" style="position:relative;"><a href="#full-component-1" aria-label="full component 1 permalink" class="anchor before"><svg aria-hidden="true" focusable="false" height="16" version="1.1" viewBox="0 0 16 16" width="16"><path fill-rule="evenodd" d="M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z"></path></svg></a>Full component</h5> <pre class="grvsc-container default-dark" data-language="jsx" data-index="14"><code class="grvsc-code"><span class="grvsc-line"><span class="grvsc-source"><span class="mtk15">import</span><span class="mtk1"> { </span><span class="mtk12">useState</span><span class="mtk1">, </span><span class="mtk12">useEffect</span><span class="mtk1"> } </span><span class="mtk15">from</span><span class="mtk1"> </span><span class="mtk8">&quot;react&quot;</span><span class="mtk1">;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk15">import</span><span class="mtk1"> { </span><span class="mtk12">useDispatch</span><span class="mtk1">, </span><span class="mtk12">useSelector</span><span class="mtk1"> } </span><span class="mtk15">from</span><span class="mtk1"> </span><span class="mtk8">&quot;react-redux&quot;</span><span class="mtk1">;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk15">import</span><span class="mtk1"> </span><span class="mtk8">&quot;./todo.css&quot;</span><span class="mtk1">;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk15">export</span><span class="mtk1"> </span><span class="mtk4">const</span><span class="mtk1"> </span><span class="mtk11">TodoList</span><span class="mtk1"> = () </span><span class="mtk4">=&gt;</span><span class="mtk1"> {</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk4">const</span><span class="mtk1"> [</span><span class="mtk12">todoList</span><span class="mtk1">, </span><span class="mtk12">setTodoList</span><span class="mtk1">] = </span><span class="mtk11">useState</span><span class="mtk1">([]);</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk4">const</span><span class="mtk1"> </span><span class="mtk12">dispatch</span><span class="mtk1"> = </span><span class="mtk11">useDispatch</span><span class="mtk1">();</span></span></span> <span class="grvsc-line"><span class="grvsc-source"></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk11">useEffect</span><span class="mtk1">(() </span><span class="mtk4">=&gt;</span><span class="mtk1"> {</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk4">async</span><span class="mtk1"> </span><span class="mtk4">function</span><span class="mtk1"> </span><span class="mtk11">getTodoList</span><span class="mtk1">() {</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk4">const</span><span class="mtk1"> </span><span class="mtk12">response</span><span class="mtk1"> = </span><span class="mtk15">await</span><span class="mtk1"> </span><span class="mtk11">fetch</span><span class="mtk1">(</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk8">&quot;https://jsonplaceholder.typicode.com/todos&quot;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> );</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk4">const</span><span class="mtk1"> </span><span class="mtk12">data</span><span class="mtk1"> = </span><span class="mtk15">await</span><span class="mtk1"> </span><span class="mtk12">response</span><span class="mtk1">.</span><span class="mtk11">json</span><span class="mtk1">();</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk11">dispatch</span><span class="mtk1">({</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">type:</span><span class="mtk1"> </span><span class="mtk8">&#39;UPDATE_TODO_LIST&#39;</span><span class="mtk1">,</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">value:</span><span class="mtk1"> </span><span class="mtk12">data</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> });</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk11">setTodoList</span><span class="mtk1">(</span><span class="mtk12">data</span><span class="mtk1">);</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> }</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk11">getTodoList</span><span class="mtk1">();</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> }, []);</span></span></span> <span class="grvsc-line"><span class="grvsc-source"></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk15">return</span><span class="mtk1"> (</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk17">&lt;</span><span class="mtk4">table</span><span class="mtk17">&gt;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk17">&lt;</span><span class="mtk4">thead</span><span class="mtk17">&gt;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk17">&lt;</span><span class="mtk4">tr</span><span class="mtk17">&gt;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk17">&lt;</span><span class="mtk4">th</span><span class="mtk17">&gt;</span><span class="mtk1">Task</span><span class="mtk17">&lt;/</span><span class="mtk4">th</span><span class="mtk17">&gt;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk17">&lt;</span><span class="mtk4">th</span><span class="mtk17">&gt;</span><span class="mtk1">Completed</span><span class="mtk17">&lt;/</span><span class="mtk4">th</span><span class="mtk17">&gt;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk17">&lt;/</span><span class="mtk4">tr</span><span class="mtk17">&gt;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk17">&lt;/</span><span class="mtk4">thead</span><span class="mtk17">&gt;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk17">&lt;</span><span class="mtk4">tbody</span><span class="mtk17">&gt;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk4">{</span><span class="mtk12">todoList</span><span class="mtk1">.</span><span class="mtk11">map</span><span class="mtk1">((</span><span class="mtk12">item</span><span class="mtk1">) </span><span class="mtk4">=&gt;</span><span class="mtk1"> (</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk17">&lt;</span><span class="mtk4">tr</span><span class="mtk1"> </span><span class="mtk12">key</span><span class="mtk1">=</span><span class="mtk4">{</span><span class="mtk12">item</span><span class="mtk1">.</span><span class="mtk12">id</span><span class="mtk4">}</span><span class="mtk17">&gt;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk17">&lt;</span><span class="mtk4">td</span><span class="mtk17">&gt;&lt;</span><span class="mtk10">TextBox</span><span class="mtk1"> </span><span class="mtk12">id</span><span class="mtk1">=</span><span class="mtk4">{</span><span class="mtk12">item</span><span class="mtk1">.</span><span class="mtk12">id</span><span class="mtk4">}</span><span class="mtk17">&gt;&lt;/</span><span class="mtk10">TextBox</span><span class="mtk17">&gt;&lt;/</span><span class="mtk4">td</span><span class="mtk17">&gt;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk17">&lt;</span><span class="mtk4">td</span><span class="mtk17">&gt;&lt;</span><span class="mtk10">CheckBox</span><span class="mtk1"> </span><span class="mtk12">id</span><span class="mtk1">=</span><span class="mtk4">{</span><span class="mtk12">item</span><span class="mtk1">.</span><span class="mtk12">id</span><span class="mtk4">}</span><span class="mtk17">&gt;&lt;/</span><span class="mtk10">CheckBox</span><span class="mtk17">&gt;&lt;/</span><span class="mtk4">td</span><span class="mtk17">&gt;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk17">&lt;/</span><span class="mtk4">tr</span><span class="mtk17">&gt;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> ))</span><span class="mtk4">}</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk17">&lt;/</span><span class="mtk4">tbody</span><span class="mtk17">&gt;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk17">&lt;/</span><span class="mtk4">table</span><span class="mtk17">&gt;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> );</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1">};</span></span></span> <span class="grvsc-line"><span class="grvsc-source"></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk4">const</span><span class="mtk1"> </span><span class="mtk11">TextBox</span><span class="mtk1"> = ({</span><span class="mtk12">id</span><span class="mtk1">}) </span><span class="mtk4">=&gt;</span><span class="mtk1"> {</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk4">const</span><span class="mtk1"> </span><span class="mtk12">value</span><span class="mtk1"> = </span><span class="mtk11">useSelector</span><span class="mtk1">(</span><span class="mtk12">state</span><span class="mtk1"> </span><span class="mtk4">=&gt;</span><span class="mtk1"> </span><span class="mtk12">state</span><span class="mtk1">[</span><span class="mtk12">id</span><span class="mtk1">]?.</span><span class="mtk12">title</span><span class="mtk1">)</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk4">const</span><span class="mtk1"> </span><span class="mtk12">dispatch</span><span class="mtk1"> = </span><span class="mtk11">useDispatch</span><span class="mtk1">();</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk4">function</span><span class="mtk1"> </span><span class="mtk11">changeHandler</span><span class="mtk1">(</span><span class="mtk12">e</span><span class="mtk1">) {</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk11">dispatch</span><span class="mtk1">({</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">type:</span><span class="mtk1"> </span><span class="mtk8">&#39;UPDATE_TODO_FIELD&#39;</span><span class="mtk1">,</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">id</span><span class="mtk1">, </span><span class="mtk12">value:</span><span class="mtk1"> </span><span class="mtk12">e</span><span class="mtk1">.</span><span class="mtk12">target</span><span class="mtk1">.</span><span class="mtk12">value</span><span class="mtk1">, </span><span class="mtk12">field:</span><span class="mtk1"> </span><span class="mtk8">&#39;title&#39;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> })</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> }</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk15">return</span><span class="mtk1"> </span><span class="mtk17">&lt;</span><span class="mtk4">input</span><span class="mtk1"> </span><span class="mtk12">type</span><span class="mtk1">=</span><span class="mtk8">&quot;text&quot;</span><span class="mtk1"> </span><span class="mtk12">value</span><span class="mtk1">=</span><span class="mtk4">{</span><span class="mtk12">value</span><span class="mtk4">}</span><span class="mtk1"> </span><span class="mtk12">onChange</span><span class="mtk1">=</span><span class="mtk4">{</span><span class="mtk12">changeHandler</span><span class="mtk4">}</span><span class="mtk1"> </span><span class="mtk17">/&gt;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1">}</span></span></span> <span class="grvsc-line"><span class="grvsc-source"></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk4">const</span><span class="mtk1"> </span><span class="mtk11">CheckBox</span><span class="mtk1"> = ({</span><span class="mtk12">id</span><span class="mtk1">}) </span><span class="mtk4">=&gt;</span><span class="mtk1"> {</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk4">const</span><span class="mtk1"> </span><span class="mtk12">value</span><span class="mtk1"> = </span><span class="mtk11">useSelector</span><span class="mtk1">(</span><span class="mtk12">state</span><span class="mtk1"> </span><span class="mtk4">=&gt;</span><span class="mtk1"> </span><span class="mtk12">state</span><span class="mtk1">[</span><span class="mtk12">id</span><span class="mtk1">]?.</span><span class="mtk12">completed</span><span class="mtk1">);</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk4">const</span><span class="mtk1"> </span><span class="mtk12">dispatch</span><span class="mtk1"> = </span><span class="mtk11">useDispatch</span><span class="mtk1">();</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk4">function</span><span class="mtk1"> </span><span class="mtk11">changeHandler</span><span class="mtk1">(</span><span class="mtk12">e</span><span class="mtk1">) {</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk11">dispatch</span><span class="mtk1">({</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">type:</span><span class="mtk1"> </span><span class="mtk8">&#39;UPDATE_TODO_FIELD&#39;</span><span class="mtk1">,</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">id</span><span class="mtk1">, </span><span class="mtk12">value:</span><span class="mtk1"> </span><span class="mtk12">e</span><span class="mtk1">.</span><span class="mtk12">target</span><span class="mtk1">.</span><span class="mtk12">checked</span><span class="mtk1">, </span><span class="mtk12">field:</span><span class="mtk1"> </span><span class="mtk8">&#39;completed&#39;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> })</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> }</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk15">return</span><span class="mtk1"> </span><span class="mtk17">&lt;</span><span class="mtk4">input</span><span class="mtk1"> </span><span class="mtk12">type</span><span class="mtk1">=</span><span class="mtk8">&quot;checkbox&quot;</span><span class="mtk1"> </span><span class="mtk12">value</span><span class="mtk1">=</span><span class="mtk4">{</span><span class="mtk12">value</span><span class="mtk4">}</span><span class="mtk1"> </span><span class="mtk12">onChange</span><span class="mtk1">=</span><span class="mtk4">{</span><span class="mtk12">changeHandler</span><span class="mtk4">}</span><span class="mtk1"> </span><span class="mtk17">/&gt;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1">}</span></span></span></code></pre> <h2 id="demo" style="position:relative;"><a href="#demo" aria-label="demo permalink" class="anchor before"><svg aria-hidden="true" focusable="false" height="16" version="1.1" viewBox="0 0 16 16" width="16"><path fill-rule="evenodd" d="M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z"></path></svg></a>Demo</h2> <div data-codesandbox="intelligent-feistel-bozf2"> <button>Run Code</button> </div> <h2 id="summary" style="position:relative;"><a href="#summary" aria-label="summary permalink" class="anchor before"><svg aria-hidden="true" focusable="false" height="16" version="1.1" viewBox="0 0 16 16" width="16"><path fill-rule="evenodd" d="M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z"></path></svg></a>Summary</h2> <p>When the <code>TodoList</code> component first renders and dispatches the data, we’re creating a dictionary based on ids. Initially, all input fields will be updated as they’re subscribed to that object. But, whenever the user does any modifications, only the component subscribed to the specific id/field will be rendered leaving us with optimum performance 🚀</p> <p>Bye for now 👋</p> <style class="grvsc-styles"> .grvsc-container { overflow: auto; position: relative; -webkit-overflow-scrolling: touch; padding-top: 1rem; padding-top: var(--grvsc-padding-top, var(--grvsc-padding-v, 1rem)); padding-bottom: 1rem; padding-bottom: var(--grvsc-padding-bottom, var(--grvsc-padding-v, 1rem)); border-radius: 8px; border-radius: var(--grvsc-border-radius, 8px); font-feature-settings: normal; line-height: 1.4; } .grvsc-code { display: table; } .grvsc-line { display: table-row; box-sizing: border-box; width: 100%; position: relative; } .grvsc-line > * { position: relative; } .grvsc-gutter-pad { display: table-cell; padding-left: 0.75rem; padding-left: calc(var(--grvsc-padding-left, var(--grvsc-padding-h, 1.5rem)) / 2); } .grvsc-gutter { display: table-cell; -webkit-user-select: none; -moz-user-select: none; user-select: none; } .grvsc-gutter::before { content: attr(data-content); } .grvsc-source { display: table-cell; padding-left: 1.5rem; padding-left: var(--grvsc-padding-left, var(--grvsc-padding-h, 1.5rem)); padding-right: 1.5rem; padding-right: var(--grvsc-padding-right, var(--grvsc-padding-h, 1.5rem)); } .grvsc-source:empty::after { content: ' '; -webkit-user-select: none; -moz-user-select: none; user-select: none; } .grvsc-gutter + .grvsc-source { padding-left: 0.75rem; padding-left: calc(var(--grvsc-padding-left, var(--grvsc-padding-h, 1.5rem)) / 2); } /* Line transformer styles */ .grvsc-has-line-highlighting > .grvsc-code > .grvsc-line::before { content: ' '; position: absolute; width: 100%; } .grvsc-line-diff-add::before { background-color: var(--grvsc-line-diff-add-background-color, rgba(0, 255, 60, 0.2)); } .grvsc-line-diff-del::before { background-color: var(--grvsc-line-diff-del-background-color, rgba(255, 0, 20, 0.2)); } .grvsc-line-number { padding: 0 2px; text-align: right; opacity: 0.7; } .default-dark { background-color: #1E1E1E; color: #D4D4D4; } .default-dark .mtk4 { color: #569CD6; } .default-dark .mtk1 { color: #D4D4D4; } .default-dark .mtk12 { color: #9CDCFE; } .default-dark .mtk8 { color: #CE9178; } .default-dark .mtk15 { color: #C586C0; } .default-dark .mtk11 { color: #DCDCAA; } .default-dark .mtk7 { color: #B5CEA8; } .default-dark .mtk17 { color: #808080; } .default-dark .mtk10 { color: #4EC9B0; } .default-dark .grvsc-line-highlighted::before { background-color: var(--grvsc-line-highlighted-background-color, rgba(255, 255, 255, 0.1)); box-shadow: inset var(--grvsc-line-highlighted-border-width, 4px) 0 0 0 var(--grvsc-line-highlighted-border-color, rgba(255, 255, 255, 0.5)); } </style><![CDATA[[Part 3] Add and Remove Table Rows with Bootstrap Vue]]>https://muhimasri.compart-3-add-and-remove-table-rows-with-bootstrap-vuehttps://muhimasri.compart-3-add-and-remove-table-rows-with-bootstrap-vue<p><a href="https://muhimasri.com/blogs/part-2-create-a-dynamic-table-with-bootstrap-vue/">In the previous part</a>, we learned how to convert an <a href="https://muhimasri.com/blogs/create-an-editable-dynamic-table-with-bootstrap-vue/">editable Bootstrap table</a> to a dynamic reusable component that works with any schema. Also, we demonstrated how we can enable <code>v-model</code> in a custom component to support a two-way bind.</p> <p>In this tutorial, we’ll continue enhancing this component by showing how to add and remove multiple rows with a confirmation dialog. Here is a quick demo of the final results:</p> <div data-youtube="_tqq_-k90YA"> <button>Play Example</button> </div> <p>Before we start, below is the full code from the <a href="https://muhimasri.com/blogs/part-2-create-a-dynamic-table-with-bootstrap-vue/">previous part</a> (<code>EditableTable.vue</code> component):</p> <pre class="grvsc-container default-dark" data-language="html" data-index="0"><code class="grvsc-code"><span class="grvsc-line"><span class="grvsc-source"><span class="mtk17">&lt;</span><span class="mtk4">template</span><span class="mtk17">&gt;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk17">&lt;</span><span class="mtk4">b-table</span><span class="mtk1"> </span><span class="mtk12">:items</span><span class="mtk1">=</span><span class="mtk8">&quot;tableItems&quot;</span><span class="mtk1"> </span><span class="mtk12">:fields</span><span class="mtk1">=</span><span class="mtk8">&quot;fields&quot;</span><span class="mtk17">&gt;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk17">&lt;</span><span class="mtk4">template</span><span class="mtk1"> </span><span class="mtk12">v-for</span><span class="mtk1">=</span><span class="mtk8">&quot;(field, index) in fields&quot;</span><span class="mtk1"> </span><span class="mtk12">#[`cell(${field.key})`]</span><span class="mtk1">=</span><span class="mtk8">&quot;data&quot;</span><span class="mtk17">&gt;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk17">&lt;</span><span class="mtk4">b-form-datepicker</span><span class="mtk1"> </span><span class="mtk12">v-if</span><span class="mtk1">=</span><span class="mtk8">&quot;field.type === &#39;date&#39; &amp;&amp; tableItems[data.index].isEdit&quot;</span><span class="mtk1"> </span><span class="mtk12">:key</span><span class="mtk1">=</span><span class="mtk8">&quot;index&quot;</span><span class="mtk1"> </span><span class="mtk12">:type</span><span class="mtk1">=</span><span class="mtk8">&quot;field.type&quot;</span><span class="mtk1"> </span><span class="mtk12">:value</span><span class="mtk1">=</span><span class="mtk8">&quot;tableItems[data.index][field.key]&quot;</span><span class="mtk1"> </span><span class="mtk12">@input</span><span class="mtk1">=</span><span class="mtk8">&quot;(value) =&gt; inputHandler(value, data.index, field.key)&quot;</span><span class="mtk17">&gt;&lt;/</span><span class="mtk4">b-form-datepicker</span><span class="mtk17">&gt;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk17">&lt;</span><span class="mtk4">b-form-select</span><span class="mtk1"> </span><span class="mtk12">v-else-if</span><span class="mtk1">=</span><span class="mtk8">&quot;field.type === &#39;select&#39; &amp;&amp; tableItems[data.index].isEdit&quot;</span><span class="mtk1"> </span><span class="mtk12">:key</span><span class="mtk1">=</span><span class="mtk8">&quot;index&quot;</span><span class="mtk1"> </span><span class="mtk12">:value</span><span class="mtk1">=</span><span class="mtk8">&quot;tableItems[data.index][field.key]&quot;</span><span class="mtk1"> </span><span class="mtk12">@input</span><span class="mtk1">=</span><span class="mtk8">&quot;(value) =&gt; inputHandler(value, data.index, field.key)&quot;</span><span class="mtk1"> </span><span class="mtk12">:options</span><span class="mtk1">=</span><span class="mtk8">&quot;field.options&quot;</span><span class="mtk17">&gt;&lt;/</span><span class="mtk4">b-form-select</span><span class="mtk17">&gt;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk17">&lt;</span><span class="mtk4">b-button</span><span class="mtk1"> </span><span class="mtk12">:key</span><span class="mtk1">=</span><span class="mtk8">&quot;index&quot;</span><span class="mtk1"> </span><span class="mtk12">v-else-if</span><span class="mtk1">=</span><span class="mtk8">&quot;field.type === &#39;edit&#39;&quot;</span><span class="mtk1"> </span><span class="mtk12">@click</span><span class="mtk1">=</span><span class="mtk8">&quot;editRowHandler(data)&quot;</span><span class="mtk17">&gt;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk17">&lt;</span><span class="mtk4">span</span><span class="mtk1"> </span><span class="mtk12">v-if</span><span class="mtk1">=</span><span class="mtk8">&quot;!tableItems[data.index].isEdit&quot;</span><span class="mtk17">&gt;</span><span class="mtk1">Edit</span><span class="mtk17">&lt;/</span><span class="mtk4">span</span><span class="mtk17">&gt;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk17">&lt;</span><span class="mtk4">span</span><span class="mtk1"> </span><span class="mtk12">v-else</span><span class="mtk17">&gt;</span><span class="mtk1">Done</span><span class="mtk17">&lt;/</span><span class="mtk4">span</span><span class="mtk17">&gt;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk17">&lt;/</span><span class="mtk4">b-button</span><span class="mtk17">&gt;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk17">&lt;</span><span class="mtk4">b-form-input</span><span class="mtk1"> </span><span class="mtk12">v-else-if</span><span class="mtk1">=</span><span class="mtk8">&quot;field.type &amp;&amp; tableItems[data.index].isEdit&quot;</span><span class="mtk1"> </span><span class="mtk12">:key</span><span class="mtk1">=</span><span class="mtk8">&quot;index&quot;</span><span class="mtk1"> </span><span class="mtk12">:type</span><span class="mtk1">=</span><span class="mtk8">&quot;field.type&quot;</span><span class="mtk1"> </span><span class="mtk12">:value</span><span class="mtk1">=</span><span class="mtk8">&quot;tableItems[data.index][field.key]&quot;</span><span class="mtk1"> </span><span class="mtk12">@blur</span><span class="mtk1">=</span><span class="mtk8">&quot;(e) =&gt; inputHandler(e.target.value, data.index, field.key)&quot;</span><span class="mtk17">&gt;&lt;/</span><span class="mtk4">b-form-input</span><span class="mtk17">&gt;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk17">&lt;</span><span class="mtk4">span</span><span class="mtk1"> </span><span class="mtk12">:key</span><span class="mtk1">=</span><span class="mtk8">&quot;index&quot;</span><span class="mtk1"> </span><span class="mtk12">v-else</span><span class="mtk17">&gt;</span><span class="mtk1">{{data.value}}</span><span class="mtk17">&lt;/</span><span class="mtk4">span</span><span class="mtk17">&gt;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk17">&lt;/</span><span class="mtk4">template</span><span class="mtk17">&gt;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk17">&lt;/</span><span class="mtk4">b-table</span><span class="mtk17">&gt;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk17">&lt;/</span><span class="mtk4">template</span><span class="mtk17">&gt;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk17">&lt;</span><span class="mtk4">script</span><span class="mtk17">&gt;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk15">export</span><span class="mtk1"> </span><span class="mtk15">default</span><span class="mtk1"> {</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">name:</span><span class="mtk1"> </span><span class="mtk8">&quot;EditableTable&quot;</span><span class="mtk1">,</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">components:</span><span class="mtk1"> {},</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">props:</span><span class="mtk1"> {</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">value:</span><span class="mtk1"> </span><span class="mtk10">Array</span><span class="mtk1">,</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">fields:</span><span class="mtk1"> </span><span class="mtk10">Array</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> },</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk11">data</span><span class="mtk1">() {</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk15">return</span><span class="mtk1"> {</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">tableItems:</span><span class="mtk1"> </span><span class="mtk4">this</span><span class="mtk1">.</span><span class="mtk12">value</span><span class="mtk1">.</span><span class="mtk11">map</span><span class="mtk1">(</span><span class="mtk12">item</span><span class="mtk1"> </span><span class="mtk4">=&gt;</span><span class="mtk1"> ({...</span><span class="mtk12">item</span><span class="mtk1">, </span><span class="mtk12">isEdit:</span><span class="mtk1"> </span><span class="mtk4">false</span><span class="mtk1">}))</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> }</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> },</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">methods:</span><span class="mtk1"> {</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk11">editRowHandler</span><span class="mtk1">(</span><span class="mtk12">data</span><span class="mtk1">) {</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk4">this</span><span class="mtk1">.</span><span class="mtk12">tableItems</span><span class="mtk1">[</span><span class="mtk12">data</span><span class="mtk1">.</span><span class="mtk12">index</span><span class="mtk1">].</span><span class="mtk12">isEdit</span><span class="mtk1"> = !</span><span class="mtk4">this</span><span class="mtk1">.</span><span class="mtk12">tableItems</span><span class="mtk1">[</span><span class="mtk12">data</span><span class="mtk1">.</span><span class="mtk12">index</span><span class="mtk1">].</span><span class="mtk12">isEdit</span><span class="mtk1">;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> },</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk11">inputHandler</span><span class="mtk1">(</span><span class="mtk12">value</span><span class="mtk1">, </span><span class="mtk12">index</span><span class="mtk1">, </span><span class="mtk12">key</span><span class="mtk1">) {</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk4">this</span><span class="mtk1">.</span><span class="mtk12">tableItems</span><span class="mtk1">[</span><span class="mtk12">index</span><span class="mtk1">][</span><span class="mtk12">key</span><span class="mtk1">] = </span><span class="mtk12">value</span><span class="mtk1">;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk4">this</span><span class="mtk1">.</span><span class="mtk11">$set</span><span class="mtk1">(</span><span class="mtk4">this</span><span class="mtk1">.</span><span class="mtk12">tableItems</span><span class="mtk1">, </span><span class="mtk12">index</span><span class="mtk1">, </span><span class="mtk4">this</span><span class="mtk1">.</span><span class="mtk12">tableItems</span><span class="mtk1">[</span><span class="mtk12">index</span><span class="mtk1">]);</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk4">this</span><span class="mtk1">.</span><span class="mtk11">$emit</span><span class="mtk1">(</span><span class="mtk8">&quot;input&quot;</span><span class="mtk1">, </span><span class="mtk4">this</span><span class="mtk1">.</span><span class="mtk12">tableItems</span><span class="mtk1">);</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> }</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> }</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1">};</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk17">&lt;/</span><span class="mtk4">script</span><span class="mtk17">&gt;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk17">&lt;</span><span class="mtk4">style</span><span class="mtk17">&gt;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk17">&lt;/</span><span class="mtk4">style</span><span class="mtk17">&gt;</span></span></span></code></pre> <p><em>As we continue building upon the same code from previous parts in this series, it’s recommended that you go through these tutorials from the beginning to understand how the code structure works as we will not be explaining it here. You can navigate to any part using the table of contents.</em></p> <h2 id="adding-new-rows" style="position:relative;"><a href="#adding-new-rows" aria-label="adding new rows permalink" class="anchor before"><svg aria-hidden="true" focusable="false" height="16" version="1.1" viewBox="0 0 16 16" width="16"><path fill-rule="evenodd" d="M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z"></path></svg></a>Adding new rows</h2> <p>Adding a new row is as simple as inserting a new object to the <code>tableItems</code> array and making sure to apply the proper schema. Let’s take a closer look:</p> <ol> <li>Add a button with an event handler</li> <li>Use the array <code>reducer</code> function to generate an object with all the field names we need for an empty row. We can default values to <code>null</code></li> <li>Use <code>unshift</code> to insert a new row at the very beginning of the list</li> <li>Make sure to emit the latest changes for the <code>v-model</code> to update. This was explained in-depth in the <a href="https://muhimasri.com/blogs/part-2-create-a-dynamic-table-with-bootstrap-vue/#two-way-binding">previous part</a>.</li> <li>Finally, set <code>isEdit</code> to true to enable editing the new row</li> </ol> <h5 id="editabletable-component" style="position:relative;"><a href="#editabletable-component" aria-label="editabletable component permalink" class="anchor before"><svg aria-hidden="true" focusable="false" height="16" version="1.1" viewBox="0 0 16 16" width="16"><path fill-rule="evenodd" d="M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z"></path></svg></a>EditableTable Component</h5> <pre class="grvsc-container default-dark" data-language="html" data-index="1"><code class="grvsc-code"><span class="grvsc-line"><span class="grvsc-source"><span class="mtk17">&lt;</span><span class="mtk4">template</span><span class="mtk17">&gt;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk17">&lt;</span><span class="mtk4">article</span><span class="mtk17">&gt;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk17">&lt;</span><span class="mtk4">b-button</span><span class="mtk1"> </span><span class="mtk12">class</span><span class="mtk1">=</span><span class="mtk8">&quot;add-button&quot;</span><span class="mtk1"> </span><span class="mtk12">variant</span><span class="mtk1">=</span><span class="mtk8">&quot;success&quot;</span><span class="mtk1"> </span><span class="mtk12">@click</span><span class="mtk1">=</span><span class="mtk8">&quot;addRowHandler&quot;</span><span class="mtk17">&gt;</span><span class="mtk1">Add Row</span><span class="mtk17">&lt;/</span><span class="mtk4">b-button</span><span class="mtk17">&gt;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk17">&lt;</span><span class="mtk4">b-table</span><span class="mtk1"> </span><span class="mtk12">class</span><span class="mtk1">=</span><span class="mtk8">&quot;b-table&quot;</span><span class="mtk1"> </span><span class="mtk12">:items</span><span class="mtk1">=</span><span class="mtk8">&quot;tableItems&quot;</span><span class="mtk1"> </span><span class="mtk12">:fields</span><span class="mtk1">=</span><span class="mtk8">&quot;fields&quot;</span><span class="mtk1"> </span><span class="mtk12">fixed</span><span class="mtk17">&gt;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk17">&lt;</span><span class="mtk4">template</span><span class="mtk1"> </span><span class="mtk12">v-for</span><span class="mtk1">=</span><span class="mtk8">&quot;(field, index) in fields&quot;</span><span class="mtk1"> </span><span class="mtk12">#[`cell(${field.key})`]</span><span class="mtk1">=</span><span class="mtk8">&quot;data&quot;</span><span class="mtk17">&gt;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk17">&lt;</span><span class="mtk4">b-form-datepicker</span><span class="mtk1"> </span><span class="mtk12">v-if</span><span class="mtk1">=</span><span class="mtk8">&quot;field.type === &#39;date&#39; &amp;&amp; tableItems[data.index].isEdit&quot;</span><span class="mtk1"> </span><span class="mtk12">:key</span><span class="mtk1">=</span><span class="mtk8">&quot;index&quot;</span><span class="mtk1"> </span><span class="mtk12">:type</span><span class="mtk1">=</span><span class="mtk8">&quot;field.type&quot;</span><span class="mtk1"> </span><span class="mtk12">:value</span><span class="mtk1">=</span><span class="mtk8">&quot;tableItems[data.index][field.key]&quot;</span><span class="mtk1"> </span><span class="mtk12">@input</span><span class="mtk1">=</span><span class="mtk8">&quot;(value) =&gt; inputHandler(value, data.index, field.key)&quot;</span><span class="mtk17">&gt;&lt;/</span><span class="mtk4">b-form-datepicker</span><span class="mtk17">&gt;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk17">&lt;</span><span class="mtk4">b-form-select</span><span class="mtk1"> </span><span class="mtk12">v-else-if</span><span class="mtk1">=</span><span class="mtk8">&quot;field.type === &#39;select&#39; &amp;&amp; tableItems[data.index].isEdit&quot;</span><span class="mtk1"> </span><span class="mtk12">:key</span><span class="mtk1">=</span><span class="mtk8">&quot;index&quot;</span><span class="mtk1"> </span><span class="mtk12">:value</span><span class="mtk1">=</span><span class="mtk8">&quot;tableItems[data.index][field.key]&quot;</span><span class="mtk1"> </span><span class="mtk12">@input</span><span class="mtk1">=</span><span class="mtk8">&quot;(value) =&gt; inputHandler(value, data.index, field.key)&quot;</span><span class="mtk1"> </span><span class="mtk12">:options</span><span class="mtk1">=</span><span class="mtk8">&quot;field.options&quot;</span><span class="mtk17">&gt;&lt;/</span><span class="mtk4">b-form-select</span><span class="mtk17">&gt;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk17">&lt;</span><span class="mtk4">b-button</span><span class="mtk1"> </span><span class="mtk12">:key</span><span class="mtk1">=</span><span class="mtk8">&quot;index&quot;</span><span class="mtk1"> </span><span class="mtk12">v-else-if</span><span class="mtk1">=</span><span class="mtk8">&quot;field.type === &#39;edit&#39;&quot;</span><span class="mtk1"> </span><span class="mtk12">@click</span><span class="mtk1">=</span><span class="mtk8">&quot;editRowHandler(data)&quot;</span><span class="mtk17">&gt;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk17">&lt;</span><span class="mtk4">span</span><span class="mtk1"> </span><span class="mtk12">v-if</span><span class="mtk1">=</span><span class="mtk8">&quot;!tableItems[data.index].isEdit&quot;</span><span class="mtk17">&gt;</span><span class="mtk1">Edit</span><span class="mtk17">&lt;/</span><span class="mtk4">span</span><span class="mtk17">&gt;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk17">&lt;</span><span class="mtk4">span</span><span class="mtk1"> </span><span class="mtk12">v-else</span><span class="mtk17">&gt;</span><span class="mtk1">Done</span><span class="mtk17">&lt;/</span><span class="mtk4">span</span><span class="mtk17">&gt;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk17">&lt;/</span><span class="mtk4">b-button</span><span class="mtk17">&gt;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk17">&lt;</span><span class="mtk4">b-form-input</span><span class="mtk1"> </span><span class="mtk12">v-else-if</span><span class="mtk1">=</span><span class="mtk8">&quot;field.type &amp;&amp; tableItems[data.index].isEdit&quot;</span><span class="mtk1"> </span><span class="mtk12">:key</span><span class="mtk1">=</span><span class="mtk8">&quot;index&quot;</span><span class="mtk1"> </span><span class="mtk12">:type</span><span class="mtk1">=</span><span class="mtk8">&quot;field.type&quot;</span><span class="mtk1"> </span><span class="mtk12">:value</span><span class="mtk1">=</span><span class="mtk8">&quot;tableItems[data.index][field.key]&quot;</span><span class="mtk1"> </span><span class="mtk12">@blur</span><span class="mtk1">=</span><span class="mtk8">&quot;(e) =&gt; inputHandler(e.target.value, data.index, field.key)&quot;</span><span class="mtk17">&gt;&lt;/</span><span class="mtk4">b-form-input</span><span class="mtk17">&gt;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk17">&lt;</span><span class="mtk4">span</span><span class="mtk1"> </span><span class="mtk12">:key</span><span class="mtk1">=</span><span class="mtk8">&quot;index&quot;</span><span class="mtk1"> </span><span class="mtk12">v-else</span><span class="mtk17">&gt;</span><span class="mtk1">{{data.value}}</span><span class="mtk17">&lt;/</span><span class="mtk4">span</span><span class="mtk17">&gt;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk17">&lt;/</span><span class="mtk4">template</span><span class="mtk17">&gt;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk17">&lt;/</span><span class="mtk4">b-table</span><span class="mtk17">&gt;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk17">&lt;/</span><span class="mtk4">article</span><span class="mtk17">&gt;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk17">&lt;/</span><span class="mtk4">template</span><span class="mtk17">&gt;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk17">&lt;</span><span class="mtk4">script</span><span class="mtk17">&gt;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk15">export</span><span class="mtk1"> </span><span class="mtk15">default</span><span class="mtk1"> {</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">name:</span><span class="mtk1"> </span><span class="mtk8">&quot;EditableTable&quot;</span><span class="mtk1">,</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">components:</span><span class="mtk1"> {},</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">props:</span><span class="mtk1"> {</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">value:</span><span class="mtk1"> </span><span class="mtk10">Array</span><span class="mtk1">,</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">fields:</span><span class="mtk1"> </span><span class="mtk10">Array</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> },</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk11">data</span><span class="mtk1">() {</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk15">return</span><span class="mtk1"> {</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">tableItems:</span><span class="mtk1"> </span><span class="mtk4">this</span><span class="mtk1">.</span><span class="mtk12">value</span><span class="mtk1">.</span><span class="mtk11">map</span><span class="mtk1">(</span><span class="mtk12">item</span><span class="mtk1"> </span><span class="mtk4">=&gt;</span><span class="mtk1"> ({...</span><span class="mtk12">item</span><span class="mtk1">, </span><span class="mtk12">isEdit:</span><span class="mtk1"> </span><span class="mtk4">false</span><span class="mtk1">}))</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> }</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> },</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">methods:</span><span class="mtk1"> {</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk11">editRowHandler</span><span class="mtk1">(</span><span class="mtk12">data</span><span class="mtk1">) {</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk4">this</span><span class="mtk1">.</span><span class="mtk12">tableItems</span><span class="mtk1">[</span><span class="mtk12">data</span><span class="mtk1">.</span><span class="mtk12">index</span><span class="mtk1">].</span><span class="mtk12">isEdit</span><span class="mtk1"> = !</span><span class="mtk4">this</span><span class="mtk1">.</span><span class="mtk12">tableItems</span><span class="mtk1">[</span><span class="mtk12">data</span><span class="mtk1">.</span><span class="mtk12">index</span><span class="mtk1">].</span><span class="mtk12">isEdit</span><span class="mtk1">;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> },</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk11">inputHandler</span><span class="mtk1">(</span><span class="mtk12">value</span><span class="mtk1">, </span><span class="mtk12">index</span><span class="mtk1">, </span><span class="mtk12">key</span><span class="mtk1">) {</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk4">this</span><span class="mtk1">.</span><span class="mtk12">tableItems</span><span class="mtk1">[</span><span class="mtk12">index</span><span class="mtk1">][</span><span class="mtk12">key</span><span class="mtk1">] = </span><span class="mtk12">value</span><span class="mtk1">;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk4">this</span><span class="mtk1">.</span><span class="mtk11">$set</span><span class="mtk1">(</span><span class="mtk4">this</span><span class="mtk1">.</span><span class="mtk12">tableItems</span><span class="mtk1">, </span><span class="mtk12">index</span><span class="mtk1">, </span><span class="mtk4">this</span><span class="mtk1">.</span><span class="mtk12">tableItems</span><span class="mtk1">[</span><span class="mtk12">index</span><span class="mtk1">]);</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk4">this</span><span class="mtk1">.</span><span class="mtk11">$emit</span><span class="mtk1">(</span><span class="mtk8">&quot;input&quot;</span><span class="mtk1">, </span><span class="mtk4">this</span><span class="mtk1">.</span><span class="mtk12">tableItems</span><span class="mtk1">);</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> },</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk11">addRowHandler</span><span class="mtk1">() {</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk4">const</span><span class="mtk1"> </span><span class="mtk12">newRow</span><span class="mtk1"> = </span><span class="mtk4">this</span><span class="mtk1">.</span><span class="mtk12">fields</span><span class="mtk1">.</span><span class="mtk11">reduce</span><span class="mtk1">((</span><span class="mtk12">a</span><span class="mtk1">, </span><span class="mtk12">c</span><span class="mtk1">) </span><span class="mtk4">=&gt;</span><span class="mtk1"> ({...</span><span class="mtk12">a</span><span class="mtk1">, </span><span class="mtk12">[c.key]:</span><span class="mtk1"> </span><span class="mtk4">null</span><span class="mtk1">}) ,{})</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">newRow</span><span class="mtk1">.</span><span class="mtk12">isEdit</span><span class="mtk1"> = </span><span class="mtk4">true</span><span class="mtk1">;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk4">this</span><span class="mtk1">.</span><span class="mtk12">tableItems</span><span class="mtk1">.</span><span class="mtk11">unshift</span><span class="mtk1">(</span><span class="mtk12">newRow</span><span class="mtk1">);</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk4">this</span><span class="mtk1">.</span><span class="mtk11">$emit</span><span class="mtk1">(</span><span class="mtk8">&#39;input&#39;</span><span class="mtk1">, </span><span class="mtk4">this</span><span class="mtk1">.</span><span class="mtk12">tableItems</span><span class="mtk1">);</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> }</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> }</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1">};</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk17">&lt;/</span><span class="mtk4">script</span><span class="mtk17">&gt;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk17">&lt;</span><span class="mtk4">style</span><span class="mtk17">&gt;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk6">.add-button</span><span class="mtk1"> {</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">margin-bottom</span><span class="mtk1">: </span><span class="mtk7">10px</span><span class="mtk1">;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> }</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk17">&lt;/</span><span class="mtk4">style</span><span class="mtk17">&gt;</span></span></span></code></pre> <p>In <code>app.vue</code> component, we still consume the EditableTable component the same way:</p> <h5 id="app-component" style="position:relative;"><a href="#app-component" aria-label="app component permalink" class="anchor before"><svg aria-hidden="true" focusable="false" height="16" version="1.1" viewBox="0 0 16 16" width="16"><path fill-rule="evenodd" d="M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z"></path></svg></a>App Component</h5> <pre class="grvsc-container default-dark" data-language="html" data-index="2"><code class="grvsc-code"><span class="grvsc-line"><span class="grvsc-source"><span class="mtk17">&lt;</span><span class="mtk4">template</span><span class="mtk17">&gt;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk17">&lt;</span><span class="mtk4">div</span><span class="mtk1"> </span><span class="mtk12">id</span><span class="mtk1">=</span><span class="mtk8">&quot;app&quot;</span><span class="mtk17">&gt;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk17">&lt;</span><span class="mtk4">EditableTable</span><span class="mtk1"> </span><span class="mtk12">v-model</span><span class="mtk1">=</span><span class="mtk8">&quot;items&quot;</span><span class="mtk1"> </span><span class="mtk12">:fields</span><span class="mtk1">=</span><span class="mtk8">&quot;fields&quot;</span><span class="mtk17">&gt;&lt;/</span><span class="mtk4">EditableTable</span><span class="mtk17">&gt;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk17">&lt;/</span><span class="mtk4">div</span><span class="mtk17">&gt;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk17">&lt;/</span><span class="mtk4">template</span><span class="mtk17">&gt;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk17">&lt;</span><span class="mtk4">script</span><span class="mtk17">&gt;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk15">import</span><span class="mtk1"> </span><span class="mtk12">EditableTable</span><span class="mtk1"> </span><span class="mtk15">from</span><span class="mtk1"> </span><span class="mtk8">&#39;./components/EditableTable.vue&#39;</span><span class="mtk1">;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk15">export</span><span class="mtk1"> </span><span class="mtk15">default</span><span class="mtk1"> {</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">name:</span><span class="mtk1"> </span><span class="mtk8">&quot;App&quot;</span><span class="mtk1">,</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">components:</span><span class="mtk1"> {</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">EditableTable</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> },</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk11">data</span><span class="mtk1">() {</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk15">return</span><span class="mtk1"> {</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">fields:</span><span class="mtk1"> [</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> { </span><span class="mtk12">key:</span><span class="mtk1"> </span><span class="mtk8">&quot;name&quot;</span><span class="mtk1">, </span><span class="mtk12">label:</span><span class="mtk1"> </span><span class="mtk8">&quot;Name&quot;</span><span class="mtk1">, </span><span class="mtk12">type:</span><span class="mtk1"> </span><span class="mtk8">&quot;text&quot;</span><span class="mtk1"> },</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> { </span><span class="mtk12">key:</span><span class="mtk1"> </span><span class="mtk8">&quot;department&quot;</span><span class="mtk1">, </span><span class="mtk12">label:</span><span class="mtk1"> </span><span class="mtk8">&quot;Department&quot;</span><span class="mtk1">, </span><span class="mtk12">type:</span><span class="mtk1"> </span><span class="mtk8">&quot;select&quot;</span><span class="mtk1">, </span><span class="mtk12">options:</span><span class="mtk1"> [</span><span class="mtk8">&#39;Development&#39;</span><span class="mtk1">, </span><span class="mtk8">&#39;Marketing&#39;</span><span class="mtk1">, </span><span class="mtk8">&#39;HR&#39;</span><span class="mtk1">, </span><span class="mtk8">&#39;Accounting&#39;</span><span class="mtk1">] },</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> { </span><span class="mtk12">key:</span><span class="mtk1"> </span><span class="mtk8">&quot;age&quot;</span><span class="mtk1">, </span><span class="mtk12">label:</span><span class="mtk1"> </span><span class="mtk8">&quot;Age&quot;</span><span class="mtk1">, </span><span class="mtk12">type:</span><span class="mtk1"> </span><span class="mtk8">&quot;number&quot;</span><span class="mtk1"> },</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> { </span><span class="mtk12">key:</span><span class="mtk1"> </span><span class="mtk8">&quot;dateOfBirth&quot;</span><span class="mtk1">, </span><span class="mtk12">label:</span><span class="mtk1"> </span><span class="mtk8">&quot;Date Of Birth&quot;</span><span class="mtk1">, </span><span class="mtk12">type:</span><span class="mtk1"> </span><span class="mtk8">&quot;date&quot;</span><span class="mtk1"> },</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> { </span><span class="mtk12">key:</span><span class="mtk1"> </span><span class="mtk8">&quot;edit&quot;</span><span class="mtk1">, </span><span class="mtk12">label:</span><span class="mtk1"> </span><span class="mtk8">&quot;&quot;</span><span class="mtk1">, </span><span class="mtk12">type:</span><span class="mtk1"> </span><span class="mtk8">&quot;edit&quot;</span><span class="mtk1"> }</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> ],</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">items:</span><span class="mtk1"> [</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> { </span><span class="mtk12">age:</span><span class="mtk1"> </span><span class="mtk7">40</span><span class="mtk1">, </span><span class="mtk12">name:</span><span class="mtk1"> </span><span class="mtk8">&#39;Dickerson&#39;</span><span class="mtk1">, </span><span class="mtk12">department:</span><span class="mtk1"> </span><span class="mtk8">&#39;Development&#39;</span><span class="mtk1">, </span><span class="mtk12">dateOfBirth:</span><span class="mtk1"> </span><span class="mtk8">&#39;1984-05-20&#39;</span><span class="mtk1"> },</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> { </span><span class="mtk12">age:</span><span class="mtk1"> </span><span class="mtk7">21</span><span class="mtk1">, </span><span class="mtk12">name:</span><span class="mtk1"> </span><span class="mtk8">&#39;Larsen&#39;</span><span class="mtk1">, </span><span class="mtk12">department:</span><span class="mtk1"> </span><span class="mtk8">&#39;Marketing&#39;</span><span class="mtk1">, </span><span class="mtk12">dateOfBirth:</span><span class="mtk1"> </span><span class="mtk8">&#39;1984-05-20&#39;</span><span class="mtk1"> },</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> { </span><span class="mtk12">age:</span><span class="mtk1"> </span><span class="mtk7">89</span><span class="mtk1">, </span><span class="mtk12">name:</span><span class="mtk1"> </span><span class="mtk8">&#39;Geneva&#39;</span><span class="mtk1">, </span><span class="mtk12">department:</span><span class="mtk1"> </span><span class="mtk8">&#39;HR&#39;</span><span class="mtk1">, </span><span class="mtk12">dateOfBirth:</span><span class="mtk1"> </span><span class="mtk8">&#39;1984-05-20&#39;</span><span class="mtk1"> },</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> { </span><span class="mtk12">age:</span><span class="mtk1"> </span><span class="mtk7">38</span><span class="mtk1">, </span><span class="mtk12">name:</span><span class="mtk1"> </span><span class="mtk8">&#39;Jami&#39;</span><span class="mtk1">, </span><span class="mtk12">department:</span><span class="mtk1"> </span><span class="mtk8">&#39;Accounting&#39;</span><span class="mtk1">, </span><span class="mtk12">dateOfBirth:</span><span class="mtk1"> </span><span class="mtk8">&#39;1984-05-20&#39;</span><span class="mtk1"> }</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> ]</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> };</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> }</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1">};</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk17">&lt;/</span><span class="mtk4">script</span><span class="mtk17">&gt;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk17">&lt;</span><span class="mtk4">style</span><span class="mtk17">&gt;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk6">#app</span><span class="mtk1"> {</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">margin</span><span class="mtk1">: </span><span class="mtk7">20px</span><span class="mtk1">;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1">}</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk17">&lt;/</span><span class="mtk4">style</span><span class="mtk17">&gt;</span></span></span></code></pre> <h5 id="demo" style="position:relative;"><a href="#demo" aria-label="demo permalink" class="anchor before"><svg aria-hidden="true" focusable="false" height="16" version="1.1" viewBox="0 0 16 16" width="16"><path fill-rule="evenodd" d="M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z"></path></svg></a>Demo</h5> <div data-youtube="GehOHv0SNps"> <button>Play Example</button> </div> <h2 id="removing-a-row" style="position:relative;"><a href="#removing-a-row" aria-label="removing a row permalink" class="anchor before"><svg aria-hidden="true" focusable="false" height="16" version="1.1" viewBox="0 0 16 16" width="16"><path fill-rule="evenodd" d="M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z"></path></svg></a>Removing a row</h2> <p>Similar to the previous step, we’re going to modify the <code>tableItem</code> array directly but this time by removing an element. Let’s go through the required steps:</p> <ul> <li>Add a remove button for every row and define an event handler</li> <li>Use the array <code>filter</code> function to filter out the element using the index. The index will be passed in the event handler parameter.</li> <li>Emit latest changes for the <code>v-model</code> to update</li> </ul> <h5 id="editabletable-component-1" style="position:relative;"><a href="#editabletable-component-1" aria-label="editabletable component 1 permalink" class="anchor before"><svg aria-hidden="true" focusable="false" height="16" version="1.1" viewBox="0 0 16 16" width="16"><path fill-rule="evenodd" d="M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z"></path></svg></a>EditableTable component:</h5> <pre class="grvsc-container default-dark" data-language="html" data-index="3"><code class="grvsc-code"><span class="grvsc-line"><span class="grvsc-source"><span class="mtk17">&lt;</span><span class="mtk4">template</span><span class="mtk17">&gt;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk17">&lt;</span><span class="mtk4">article</span><span class="mtk17">&gt;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk17">&lt;</span><span class="mtk4">b-button</span><span class="mtk1"> </span><span class="mtk12">class</span><span class="mtk1">=</span><span class="mtk8">&quot;add-button&quot;</span><span class="mtk1"> </span><span class="mtk12">variant</span><span class="mtk1">=</span><span class="mtk8">&quot;success&quot;</span><span class="mtk1"> </span><span class="mtk12">@click</span><span class="mtk1">=</span><span class="mtk8">&quot;addRowwHandler&quot;</span><span class="mtk17">&gt;</span><span class="mtk1">Add Row</span><span class="mtk17">&lt;/</span><span class="mtk4">b-button</span><span class="mtk17">&gt;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk17">&lt;</span><span class="mtk4">b-table</span><span class="mtk1"> </span><span class="mtk12">class</span><span class="mtk1">=</span><span class="mtk8">&quot;b-table&quot;</span><span class="mtk1"> </span><span class="mtk12">:items</span><span class="mtk1">=</span><span class="mtk8">&quot;tableItems&quot;</span><span class="mtk1"> </span><span class="mtk12">:fields</span><span class="mtk1">=</span><span class="mtk8">&quot;fields&quot;</span><span class="mtk1"> </span><span class="mtk12">fixed</span><span class="mtk17">&gt;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk17">&lt;</span><span class="mtk4">template</span><span class="mtk1"> </span><span class="mtk12">v-for</span><span class="mtk1">=</span><span class="mtk8">&quot;(field, index) in fields&quot;</span><span class="mtk1"> </span><span class="mtk12">#[`cell(${field.key})`]</span><span class="mtk1">=</span><span class="mtk8">&quot;data&quot;</span><span class="mtk17">&gt;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk17">&lt;</span><span class="mtk4">b-form-datepicker</span><span class="mtk1"> </span><span class="mtk12">v-if</span><span class="mtk1">=</span><span class="mtk8">&quot;field.type === &#39;date&#39; &amp;&amp; tableItems[data.index].isEdit&quot;</span><span class="mtk1"> </span><span class="mtk12">:key</span><span class="mtk1">=</span><span class="mtk8">&quot;index&quot;</span><span class="mtk1"> </span><span class="mtk12">:type</span><span class="mtk1">=</span><span class="mtk8">&quot;field.type&quot;</span><span class="mtk1"> </span><span class="mtk12">:value</span><span class="mtk1">=</span><span class="mtk8">&quot;tableItems[data.index][field.key]&quot;</span><span class="mtk1"> </span><span class="mtk12">@input</span><span class="mtk1">=</span><span class="mtk8">&quot;(value) =&gt; inputHandler(value, data.index, field.key)&quot;</span><span class="mtk17">&gt;&lt;/</span><span class="mtk4">b-form-datepicker</span><span class="mtk17">&gt;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk17">&lt;</span><span class="mtk4">b-form-select</span><span class="mtk1"> </span><span class="mtk12">v-else-if</span><span class="mtk1">=</span><span class="mtk8">&quot;field.type === &#39;select&#39; &amp;&amp; tableItems[data.index].isEdit&quot;</span><span class="mtk1"> </span><span class="mtk12">:key</span><span class="mtk1">=</span><span class="mtk8">&quot;index&quot;</span><span class="mtk1"> </span><span class="mtk12">:value</span><span class="mtk1">=</span><span class="mtk8">&quot;tableItems[data.index][field.key]&quot;</span><span class="mtk1"> </span><span class="mtk12">@input</span><span class="mtk1">=</span><span class="mtk8">&quot;(value) =&gt; inputHandler(value, data.index, field.key)&quot;</span><span class="mtk1"> </span><span class="mtk12">:options</span><span class="mtk1">=</span><span class="mtk8">&quot;field.options&quot;</span><span class="mtk17">&gt;&lt;/</span><span class="mtk4">b-form-select</span><span class="mtk17">&gt;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk17">&lt;</span><span class="mtk4">div</span><span class="mtk1"> </span><span class="mtk12">:key</span><span class="mtk1">=</span><span class="mtk8">&quot;index&quot;</span><span class="mtk1"> </span><span class="mtk12">v-else-if</span><span class="mtk1">=</span><span class="mtk8">&quot;field.type === &#39;edit&#39;&quot;</span><span class="mtk17">&gt;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk17">&lt;</span><span class="mtk4">b-button</span><span class="mtk1"> </span><span class="mtk12">@click</span><span class="mtk1">=</span><span class="mtk8">&quot;editRowHandler(data)&quot;</span><span class="mtk17">&gt;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk17">&lt;</span><span class="mtk4">span</span><span class="mtk1"> </span><span class="mtk12">v-if</span><span class="mtk1">=</span><span class="mtk8">&quot;!tableItems[data.index].isEdit&quot;</span><span class="mtk17">&gt;</span><span class="mtk1">Edit</span><span class="mtk17">&lt;/</span><span class="mtk4">span</span><span class="mtk17">&gt;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk17">&lt;</span><span class="mtk4">span</span><span class="mtk1"> </span><span class="mtk12">v-else</span><span class="mtk17">&gt;</span><span class="mtk1">Done</span><span class="mtk17">&lt;/</span><span class="mtk4">span</span><span class="mtk17">&gt;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk17">&lt;/</span><span class="mtk4">b-button</span><span class="mtk17">&gt;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk17">&lt;</span><span class="mtk4">b-button</span><span class="mtk1"> </span><span class="mtk12">class</span><span class="mtk1">=</span><span class="mtk8">&quot;delete-button&quot;</span><span class="mtk1"> </span><span class="mtk12">variant</span><span class="mtk1">=</span><span class="mtk8">&quot;danger&quot;</span><span class="mtk1"> </span><span class="mtk12">@click</span><span class="mtk1">=</span><span class="mtk8">&quot;removeRowHandler(data.index)&quot;</span><span class="mtk17">&gt;</span><span class="mtk1">Remove</span><span class="mtk17">&lt;/</span><span class="mtk4">b-button</span><span class="mtk17">&gt;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk17">&lt;/</span><span class="mtk4">div</span><span class="mtk17">&gt;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk17">&lt;</span><span class="mtk4">b-form-input</span><span class="mtk1"> </span><span class="mtk12">v-else-if</span><span class="mtk1">=</span><span class="mtk8">&quot;field.type &amp;&amp; tableItems[data.index].isEdit&quot;</span><span class="mtk1"> </span><span class="mtk12">:key</span><span class="mtk1">=</span><span class="mtk8">&quot;index&quot;</span><span class="mtk1"> </span><span class="mtk12">:type</span><span class="mtk1">=</span><span class="mtk8">&quot;field.type&quot;</span><span class="mtk1"> </span><span class="mtk12">:value</span><span class="mtk1">=</span><span class="mtk8">&quot;tableItems[data.index][field.key]&quot;</span><span class="mtk1"> </span><span class="mtk12">@blur</span><span class="mtk1">=</span><span class="mtk8">&quot;(e) =&gt; inputHandler(e.target.value, data.index, field.key)&quot;</span><span class="mtk17">&gt;&lt;/</span><span class="mtk4">b-form-input</span><span class="mtk17">&gt;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk17">&lt;</span><span class="mtk4">span</span><span class="mtk1"> </span><span class="mtk12">:key</span><span class="mtk1">=</span><span class="mtk8">&quot;index&quot;</span><span class="mtk1"> </span><span class="mtk12">v-else</span><span class="mtk17">&gt;</span><span class="mtk1">{{data.value}}</span><span class="mtk17">&lt;/</span><span class="mtk4">span</span><span class="mtk17">&gt;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk17">&lt;/</span><span class="mtk4">template</span><span class="mtk17">&gt;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk17">&lt;/</span><span class="mtk4">b-table</span><span class="mtk17">&gt;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk17">&lt;/</span><span class="mtk4">article</span><span class="mtk17">&gt;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk17">&lt;/</span><span class="mtk4">template</span><span class="mtk17">&gt;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk17">&lt;</span><span class="mtk4">script</span><span class="mtk17">&gt;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk15">export</span><span class="mtk1"> </span><span class="mtk15">default</span><span class="mtk1"> {</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">name:</span><span class="mtk1"> </span><span class="mtk8">&quot;EditableTable&quot;</span><span class="mtk1">,</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">components:</span><span class="mtk1"> {},</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">props:</span><span class="mtk1"> {</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">value:</span><span class="mtk1"> </span><span class="mtk10">Array</span><span class="mtk1">,</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">fields:</span><span class="mtk1"> </span><span class="mtk10">Array</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> },</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk11">data</span><span class="mtk1">() {</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk15">return</span><span class="mtk1"> {</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">tableItems:</span><span class="mtk1"> </span><span class="mtk4">this</span><span class="mtk1">.</span><span class="mtk12">value</span><span class="mtk1">.</span><span class="mtk11">map</span><span class="mtk1">(</span><span class="mtk12">item</span><span class="mtk1"> </span><span class="mtk4">=&gt;</span><span class="mtk1"> ({...</span><span class="mtk12">item</span><span class="mtk1">, </span><span class="mtk12">isEdit:</span><span class="mtk1"> </span><span class="mtk4">false</span><span class="mtk1">}))</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> }</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> },</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">methods:</span><span class="mtk1"> {</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk11">editRowHandler</span><span class="mtk1">(</span><span class="mtk12">data</span><span class="mtk1">) {</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk4">this</span><span class="mtk1">.</span><span class="mtk12">tableItems</span><span class="mtk1">[</span><span class="mtk12">data</span><span class="mtk1">.</span><span class="mtk12">index</span><span class="mtk1">].</span><span class="mtk12">isEdit</span><span class="mtk1"> = !</span><span class="mtk4">this</span><span class="mtk1">.</span><span class="mtk12">tableItems</span><span class="mtk1">[</span><span class="mtk12">data</span><span class="mtk1">.</span><span class="mtk12">index</span><span class="mtk1">].</span><span class="mtk12">isEdit</span><span class="mtk1">;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> },</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk11">inputHandler</span><span class="mtk1">(</span><span class="mtk12">value</span><span class="mtk1">, </span><span class="mtk12">index</span><span class="mtk1">, </span><span class="mtk12">key</span><span class="mtk1">) {</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk4">this</span><span class="mtk1">.</span><span class="mtk12">tableItems</span><span class="mtk1">[</span><span class="mtk12">index</span><span class="mtk1">][</span><span class="mtk12">key</span><span class="mtk1">] = </span><span class="mtk12">value</span><span class="mtk1">;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk4">this</span><span class="mtk1">.</span><span class="mtk11">$set</span><span class="mtk1">(</span><span class="mtk4">this</span><span class="mtk1">.</span><span class="mtk12">tableItems</span><span class="mtk1">, </span><span class="mtk12">index</span><span class="mtk1">, </span><span class="mtk4">this</span><span class="mtk1">.</span><span class="mtk12">tableItems</span><span class="mtk1">[</span><span class="mtk12">index</span><span class="mtk1">]);</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk4">this</span><span class="mtk1">.</span><span class="mtk11">$emit</span><span class="mtk1">(</span><span class="mtk8">&quot;input&quot;</span><span class="mtk1">, </span><span class="mtk4">this</span><span class="mtk1">.</span><span class="mtk12">tableItems</span><span class="mtk1">);</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> },</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk11">addRowwHandler</span><span class="mtk1">() {</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk4">const</span><span class="mtk1"> </span><span class="mtk12">newRow</span><span class="mtk1"> = </span><span class="mtk4">this</span><span class="mtk1">.</span><span class="mtk12">fields</span><span class="mtk1">.</span><span class="mtk11">reduce</span><span class="mtk1">((</span><span class="mtk12">a</span><span class="mtk1">, </span><span class="mtk12">c</span><span class="mtk1">) </span><span class="mtk4">=&gt;</span><span class="mtk1"> ({...</span><span class="mtk12">a</span><span class="mtk1">, </span><span class="mtk12">[c.key]:</span><span class="mtk1"> </span><span class="mtk4">null</span><span class="mtk1">}) ,{})</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">newRow</span><span class="mtk1">.</span><span class="mtk12">isEdit</span><span class="mtk1"> = </span><span class="mtk4">true</span><span class="mtk1">;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk4">this</span><span class="mtk1">.</span><span class="mtk12">tableItems</span><span class="mtk1">.</span><span class="mtk11">unshift</span><span class="mtk1">(</span><span class="mtk12">newRow</span><span class="mtk1">);</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk4">this</span><span class="mtk1">.</span><span class="mtk11">$emit</span><span class="mtk1">(</span><span class="mtk8">&#39;input&#39;</span><span class="mtk1">, </span><span class="mtk4">this</span><span class="mtk1">.</span><span class="mtk12">tableItems</span><span class="mtk1">);</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> },</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk11">removeRowHandler</span><span class="mtk1">(</span><span class="mtk12">index</span><span class="mtk1">) {</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk4">this</span><span class="mtk1">.</span><span class="mtk12">tableItems</span><span class="mtk1"> = </span><span class="mtk4">this</span><span class="mtk1">.</span><span class="mtk12">tableItems</span><span class="mtk1">.</span><span class="mtk11">filter</span><span class="mtk1">((</span><span class="mtk12">item</span><span class="mtk1">, </span><span class="mtk12">i</span><span class="mtk1">) </span><span class="mtk4">=&gt;</span><span class="mtk1"> </span><span class="mtk12">i</span><span class="mtk1"> !== </span><span class="mtk12">index</span><span class="mtk1">);</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk4">this</span><span class="mtk1">.</span><span class="mtk11">$emit</span><span class="mtk1">(</span><span class="mtk8">&#39;input&#39;</span><span class="mtk1">, </span><span class="mtk4">this</span><span class="mtk1">.</span><span class="mtk12">tableItems</span><span class="mtk1">);</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> }</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> }</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1">};</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk17">&lt;/</span><span class="mtk4">script</span><span class="mtk17">&gt;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk17">&lt;</span><span class="mtk4">style</span><span class="mtk17">&gt;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk6">.add-button</span><span class="mtk1"> {</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">margin-bottom</span><span class="mtk1">: </span><span class="mtk7">10px</span><span class="mtk1">;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> }</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk6">.delete-button</span><span class="mtk1"> {</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">margin-left</span><span class="mtk1">: </span><span class="mtk7">5px</span><span class="mtk1">;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> }</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk17">&lt;/</span><span class="mtk4">style</span><span class="mtk17">&gt;</span></span></span></code></pre> <h5 id="demo-1" style="position:relative;"><a href="#demo-1" aria-label="demo 1 permalink" class="anchor before"><svg aria-hidden="true" focusable="false" height="16" version="1.1" viewBox="0 0 16 16" width="16"><path fill-rule="evenodd" d="M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z"></path></svg></a>Demo:</h5> <div data-youtube="BNtyV03hmHM"> <button>Play Example</button> </div> <h2 id="removing-multiple-rows" style="position:relative;"><a href="#removing-multiple-rows" aria-label="removing multiple rows permalink" class="anchor before"><svg aria-hidden="true" focusable="false" height="16" version="1.1" viewBox="0 0 16 16" width="16"><path fill-rule="evenodd" d="M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z"></path></svg></a>Removing multiple rows</h2> <p>Removing multiple rows at once can be very useful, especially if we are triggering an API call. Let’s go through the required steps:</p> <p>In <code>App.vue</code> component, we need a new column in the <code>fields</code> array with a <code>key</code> (we’ll name it <code>selectRow</code> but it can be any value). Notice that we are not adding <code>type</code> for this column because it will always be a checkbox that determines which rows have been selected:</p> <pre class="grvsc-container default-dark" data-language="javascript" data-index="4"><code class="grvsc-code"><span class="grvsc-line"><span class="grvsc-source"><span class="mtk1">fields: [</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> { </span><span class="mtk12">key:</span><span class="mtk1"> </span><span class="mtk8">&quot;selectRow&quot;</span><span class="mtk1">, </span><span class="mtk12">label:</span><span class="mtk1"> </span><span class="mtk8">&quot;&quot;</span><span class="mtk1"> },</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> ...</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1">]</span></span></span></code></pre> <p>In <code>EditableTable.vue</code> component:</p> <ul> <li>Add a new condition for <code>selectRow</code> that returns a checkbox element. It will have a <code>@change</code> event handler with a <code>:checked</code> value determined by a new <code>isSelected</code> property:</li> </ul> <pre class="grvsc-container default-dark" data-language="html" data-index="5"><code class="grvsc-code"><span class="grvsc-line"><span class="grvsc-source"><span class="mtk17">&lt;</span><span class="mtk4">b-checkbox</span><span class="mtk1"> </span><span class="mtk12">v-else-if</span><span class="mtk1">=</span><span class="mtk8">&quot;field.key === &#39;selectRow&#39;&quot;</span><span class="mtk1"> </span><span class="mtk12">:checked</span><span class="mtk1">=</span><span class="mtk8">&quot;tableItems[data.index].isSelected&quot;</span><span class="mtk1"> </span><span class="mtk12">@change</span><span class="mtk1">=</span><span class="mtk8">&quot;selectRowHandler(data)&quot;</span><span class="mtk17">&gt;&lt;/</span><span class="mtk4">b-checkbox</span><span class="mtk17">&gt;</span></span></span></code></pre> <ul> <li>Toggle <code>isSelected</code> value (true/false) when the checkbox is checked:</li> </ul> <pre class="grvsc-container default-dark" data-language="javascript" data-index="6"><code class="grvsc-code"><span class="grvsc-line"><span class="grvsc-source"><span class="mtk11">selectRowHandler</span><span class="mtk1">(</span><span class="mtk12">data</span><span class="mtk1">) {</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk4">this</span><span class="mtk1">.</span><span class="mtk12">tableItems</span><span class="mtk1">[</span><span class="mtk12">data</span><span class="mtk1">.</span><span class="mtk12">index</span><span class="mtk1">].</span><span class="mtk12">isSelected</span><span class="mtk1"> = !</span><span class="mtk4">this</span><span class="mtk1">.</span><span class="mtk12">tableItems</span><span class="mtk1">[</span><span class="mtk12">data</span><span class="mtk1">.</span><span class="mtk12">index</span><span class="mtk1">].</span><span class="mtk12">isSelected</span><span class="mtk1">;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1">}</span></span></span></code></pre> <ul> <li>Add a new “Remove Rows” button next to the add button with a <code>@click</code> event:</li> </ul> <pre class="grvsc-container default-dark" data-language="html" data-index="7"><code class="grvsc-code"><span class="grvsc-line"><span class="grvsc-source"><span class="mtk17">&lt;</span><span class="mtk4">div</span><span class="mtk1"> </span><span class="mtk12">class</span><span class="mtk1">=</span><span class="mtk8">&quot;action-container&quot;</span><span class="mtk17">&gt;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk17">&lt;</span><span class="mtk4">b-button</span><span class="mtk1"> </span><span class="mtk12">class</span><span class="mtk1">=</span><span class="mtk8">&quot;add-button&quot;</span><span class="mtk1"> </span><span class="mtk12">variant</span><span class="mtk1">=</span><span class="mtk8">&quot;success&quot;</span><span class="mtk1"> </span><span class="mtk12">@click</span><span class="mtk1">=</span><span class="mtk8">&quot;addRowHandler&quot;</span><span class="mtk17">&gt;</span><span class="mtk1">Add Row</span><span class="mtk17">&lt;/</span><span class="mtk4">b-button</span><span class="mtk17">&gt;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk17">&lt;</span><span class="mtk4">b-button</span><span class="mtk1"> </span><span class="mtk12">variant</span><span class="mtk1">=</span><span class="mtk8">&quot;danger&quot;</span><span class="mtk1"> </span><span class="mtk12">@click</span><span class="mtk1">=</span><span class="mtk8">&quot;removeRowsHandler&quot;</span><span class="mtk17">&gt;</span><span class="mtk1">Remove Rows</span><span class="mtk17">&lt;/</span><span class="mtk4">b-button</span><span class="mtk17">&gt;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk17">&lt;/</span><span class="mtk4">div</span><span class="mtk17">&gt;</span></span></span></code></pre> <ul> <li>Finally, filter out selected rows when the “Remove Rows” button is clicked:</li> </ul> <pre class="grvsc-container default-dark" data-language="javascript" data-index="8"><code class="grvsc-code"><span class="grvsc-line"><span class="grvsc-source"><span class="mtk11">removeRowsHandler</span><span class="mtk1">() {</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk4">this</span><span class="mtk1">.</span><span class="mtk12">tableItems</span><span class="mtk1"> = </span><span class="mtk4">this</span><span class="mtk1">.</span><span class="mtk12">tableItems</span><span class="mtk1">.</span><span class="mtk11">filter</span><span class="mtk1">(</span><span class="mtk12">item</span><span class="mtk1"> </span><span class="mtk4">=&gt;</span><span class="mtk1"> !</span><span class="mtk12">item</span><span class="mtk1">.</span><span class="mtk12">isSelected</span><span class="mtk1">);</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk4">this</span><span class="mtk1">.</span><span class="mtk11">$emit</span><span class="mtk1">(</span><span class="mtk8">&#39;input&#39;</span><span class="mtk1">, </span><span class="mtk4">this</span><span class="mtk1">.</span><span class="mtk12">tableItems</span><span class="mtk1">);</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1">}</span></span></span></code></pre> <h5 id="editabletable-component-2" style="position:relative;"><a href="#editabletable-component-2" aria-label="editabletable component 2 permalink" class="anchor before"><svg aria-hidden="true" focusable="false" height="16" version="1.1" viewBox="0 0 16 16" width="16"><path fill-rule="evenodd" d="M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z"></path></svg></a>EditableTable component:</h5> <pre class="grvsc-container default-dark" data-language="html" data-index="9"><code class="grvsc-code"><span class="grvsc-line"><span class="grvsc-source"><span class="mtk17">&lt;</span><span class="mtk4">template</span><span class="mtk17">&gt;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk17">&lt;</span><span class="mtk4">article</span><span class="mtk17">&gt;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk17">&lt;</span><span class="mtk4">div</span><span class="mtk1"> </span><span class="mtk12">class</span><span class="mtk1">=</span><span class="mtk8">&quot;action-container&quot;</span><span class="mtk17">&gt;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk17">&lt;</span><span class="mtk4">b-button</span><span class="mtk1"> </span><span class="mtk12">class</span><span class="mtk1">=</span><span class="mtk8">&quot;add-button&quot;</span><span class="mtk1"> </span><span class="mtk12">variant</span><span class="mtk1">=</span><span class="mtk8">&quot;success&quot;</span><span class="mtk1"> </span><span class="mtk12">@click</span><span class="mtk1">=</span><span class="mtk8">&quot;addRowHandler&quot;</span><span class="mtk17">&gt;</span><span class="mtk1">Add Row</span><span class="mtk17">&lt;/</span><span class="mtk4">b-button</span><span class="mtk17">&gt;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk17">&lt;</span><span class="mtk4">b-button</span><span class="mtk1"> </span><span class="mtk12">variant</span><span class="mtk1">=</span><span class="mtk8">&quot;danger&quot;</span><span class="mtk1"> </span><span class="mtk12">@click</span><span class="mtk1">=</span><span class="mtk8">&quot;removeRowsHandler&quot;</span><span class="mtk17">&gt;</span><span class="mtk1">Remove Rows</span><span class="mtk17">&lt;/</span><span class="mtk4">b-button</span><span class="mtk17">&gt;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk17">&lt;/</span><span class="mtk4">div</span><span class="mtk17">&gt;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk17">&lt;</span><span class="mtk4">b-table</span><span class="mtk1"> </span><span class="mtk12">class</span><span class="mtk1">=</span><span class="mtk8">&quot;b-table&quot;</span><span class="mtk1"> </span><span class="mtk12">:items</span><span class="mtk1">=</span><span class="mtk8">&quot;tableItems&quot;</span><span class="mtk1"> </span><span class="mtk12">:fields</span><span class="mtk1">=</span><span class="mtk8">&quot;fields&quot;</span><span class="mtk1"> </span><span class="mtk12">fixed</span><span class="mtk17">&gt;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk17">&lt;</span><span class="mtk4">template</span><span class="mtk1"> </span><span class="mtk12">v-for</span><span class="mtk1">=</span><span class="mtk8">&quot;(field, index) in fields&quot;</span><span class="mtk1"> </span><span class="mtk12">#[`cell(${field.key})`]</span><span class="mtk1">=</span><span class="mtk8">&quot;data&quot;</span><span class="mtk17">&gt;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk17">&lt;</span><span class="mtk4">b-form-datepicker</span><span class="mtk1"> </span><span class="mtk12">v-if</span><span class="mtk1">=</span><span class="mtk8">&quot;field.type === &#39;date&#39; &amp;&amp; tableItems[data.index].isEdit&quot;</span><span class="mtk1"> </span><span class="mtk12">:key</span><span class="mtk1">=</span><span class="mtk8">&quot;index&quot;</span><span class="mtk1"> </span><span class="mtk12">:type</span><span class="mtk1">=</span><span class="mtk8">&quot;field.type&quot;</span><span class="mtk1"> </span><span class="mtk12">:value</span><span class="mtk1">=</span><span class="mtk8">&quot;tableItems[data.index][field.key]&quot;</span><span class="mtk1"> </span><span class="mtk12">@input</span><span class="mtk1">=</span><span class="mtk8">&quot;(value) =&gt; inputHandler(value, data.index, field.key)&quot;</span><span class="mtk17">&gt;&lt;/</span><span class="mtk4">b-form-datepicker</span><span class="mtk17">&gt;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk17">&lt;</span><span class="mtk4">b-form-select</span><span class="mtk1"> </span><span class="mtk12">v-else-if</span><span class="mtk1">=</span><span class="mtk8">&quot;field.type === &#39;select&#39; &amp;&amp; tableItems[data.index].isEdit&quot;</span><span class="mtk1"> </span><span class="mtk12">:key</span><span class="mtk1">=</span><span class="mtk8">&quot;index&quot;</span><span class="mtk1"> </span><span class="mtk12">:value</span><span class="mtk1">=</span><span class="mtk8">&quot;tableItems[data.index][field.key]&quot;</span><span class="mtk1"> </span><span class="mtk12">@input</span><span class="mtk1">=</span><span class="mtk8">&quot;(value) =&gt; inputHandler(value, data.index, field.key)&quot;</span><span class="mtk1"> </span><span class="mtk12">:options</span><span class="mtk1">=</span><span class="mtk8">&quot;field.options&quot;</span><span class="mtk17">&gt;&lt;/</span><span class="mtk4">b-form-select</span><span class="mtk17">&gt;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk17">&lt;</span><span class="mtk4">b-checkbox</span><span class="mtk1"> </span><span class="mtk12">v-else-if</span><span class="mtk1">=</span><span class="mtk8">&quot;field.key === &#39;selectRow&#39;&quot;</span><span class="mtk1"> </span><span class="mtk12">:checked</span><span class="mtk1">=</span><span class="mtk8">&quot;tableItems[data.index].isSelected&quot;</span><span class="mtk1"> </span><span class="mtk12">:key</span><span class="mtk1">=</span><span class="mtk8">&quot;index&quot;</span><span class="mtk1"> </span><span class="mtk12">@change</span><span class="mtk1">=</span><span class="mtk8">&quot;selectRowHandler(data)&quot;</span><span class="mtk17">&gt;&lt;/</span><span class="mtk4">b-checkbox</span><span class="mtk17">&gt;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk17">&lt;</span><span class="mtk4">div</span><span class="mtk1"> </span><span class="mtk12">:key</span><span class="mtk1">=</span><span class="mtk8">&quot;index&quot;</span><span class="mtk1"> </span><span class="mtk12">v-else-if</span><span class="mtk1">=</span><span class="mtk8">&quot;field.type === &#39;edit&#39;&quot;</span><span class="mtk17">&gt;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk17">&lt;</span><span class="mtk4">b-button</span><span class="mtk1"> </span><span class="mtk12">@click</span><span class="mtk1">=</span><span class="mtk8">&quot;editRowHandler(data)&quot;</span><span class="mtk17">&gt;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk17">&lt;</span><span class="mtk4">span</span><span class="mtk1"> </span><span class="mtk12">v-if</span><span class="mtk1">=</span><span class="mtk8">&quot;!tableItems[data.index].isEdit&quot;</span><span class="mtk17">&gt;</span><span class="mtk1">Edit</span><span class="mtk17">&lt;/</span><span class="mtk4">span</span><span class="mtk17">&gt;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk17">&lt;</span><span class="mtk4">span</span><span class="mtk1"> </span><span class="mtk12">v-else</span><span class="mtk17">&gt;</span><span class="mtk1">Done</span><span class="mtk17">&lt;/</span><span class="mtk4">span</span><span class="mtk17">&gt;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk17">&lt;/</span><span class="mtk4">b-button</span><span class="mtk17">&gt;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk17">&lt;</span><span class="mtk4">b-button</span><span class="mtk1"> </span><span class="mtk12">class</span><span class="mtk1">=</span><span class="mtk8">&quot;delete-button&quot;</span><span class="mtk1"> </span><span class="mtk12">variant</span><span class="mtk1">=</span><span class="mtk8">&quot;danger&quot;</span><span class="mtk1"> </span><span class="mtk12">@click</span><span class="mtk1">=</span><span class="mtk8">&quot;removeRowHandler(data.index)&quot;</span><span class="mtk17">&gt;</span><span class="mtk1">Remove</span><span class="mtk17">&lt;/</span><span class="mtk4">b-button</span><span class="mtk17">&gt;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk17">&lt;/</span><span class="mtk4">div</span><span class="mtk17">&gt;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk17">&lt;</span><span class="mtk4">b-form-input</span><span class="mtk1"> </span><span class="mtk12">v-else-if</span><span class="mtk1">=</span><span class="mtk8">&quot;field.type &amp;&amp; tableItems[data.index].isEdit&quot;</span><span class="mtk1"> </span><span class="mtk12">:key</span><span class="mtk1">=</span><span class="mtk8">&quot;index&quot;</span><span class="mtk1"> </span><span class="mtk12">:type</span><span class="mtk1">=</span><span class="mtk8">&quot;field.type&quot;</span><span class="mtk1"> </span><span class="mtk12">:value</span><span class="mtk1">=</span><span class="mtk8">&quot;tableItems[data.index][field.key]&quot;</span><span class="mtk1"> </span><span class="mtk12">@blur</span><span class="mtk1">=</span><span class="mtk8">&quot;(e) =&gt; inputHandler(e.target.value, data.index, field.key)&quot;</span><span class="mtk17">&gt;&lt;/</span><span class="mtk4">b-form-input</span><span class="mtk17">&gt;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk17">&lt;</span><span class="mtk4">span</span><span class="mtk1"> </span><span class="mtk12">:key</span><span class="mtk1">=</span><span class="mtk8">&quot;index&quot;</span><span class="mtk1"> </span><span class="mtk12">v-else</span><span class="mtk17">&gt;</span><span class="mtk1">{{data.value}}</span><span class="mtk17">&lt;/</span><span class="mtk4">span</span><span class="mtk17">&gt;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk17">&lt;/</span><span class="mtk4">template</span><span class="mtk17">&gt;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk17">&lt;/</span><span class="mtk4">b-table</span><span class="mtk17">&gt;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk17">&lt;/</span><span class="mtk4">article</span><span class="mtk17">&gt;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk17">&lt;/</span><span class="mtk4">template</span><span class="mtk17">&gt;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk17">&lt;</span><span class="mtk4">script</span><span class="mtk17">&gt;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk15">export</span><span class="mtk1"> </span><span class="mtk15">default</span><span class="mtk1"> {</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">name:</span><span class="mtk1"> </span><span class="mtk8">&quot;EditableTable&quot;</span><span class="mtk1">,</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">components:</span><span class="mtk1"> {},</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">props:</span><span class="mtk1"> {</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">value:</span><span class="mtk1"> </span><span class="mtk10">Array</span><span class="mtk1">,</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">fields:</span><span class="mtk1"> </span><span class="mtk10">Array</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> },</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk11">data</span><span class="mtk1">() {</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk15">return</span><span class="mtk1"> {</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">tableItems:</span><span class="mtk1"> </span><span class="mtk4">this</span><span class="mtk1">.</span><span class="mtk12">value</span><span class="mtk1">.</span><span class="mtk11">map</span><span class="mtk1">(</span><span class="mtk12">item</span><span class="mtk1"> </span><span class="mtk4">=&gt;</span><span class="mtk1"> ({...</span><span class="mtk12">item</span><span class="mtk1">, </span><span class="mtk12">isEdit:</span><span class="mtk1"> </span><span class="mtk4">false</span><span class="mtk1">, </span><span class="mtk12">isSelected:</span><span class="mtk1"> </span><span class="mtk4">false</span><span class="mtk1">}))</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> }</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> },</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">methods:</span><span class="mtk1"> {</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk11">editRowHandler</span><span class="mtk1">(</span><span class="mtk12">data</span><span class="mtk1">) {</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk4">this</span><span class="mtk1">.</span><span class="mtk12">tableItems</span><span class="mtk1">[</span><span class="mtk12">data</span><span class="mtk1">.</span><span class="mtk12">index</span><span class="mtk1">].</span><span class="mtk12">isEdit</span><span class="mtk1"> = !</span><span class="mtk4">this</span><span class="mtk1">.</span><span class="mtk12">tableItems</span><span class="mtk1">[</span><span class="mtk12">data</span><span class="mtk1">.</span><span class="mtk12">index</span><span class="mtk1">].</span><span class="mtk12">isEdit</span><span class="mtk1">;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> },</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk11">inputHandler</span><span class="mtk1">(</span><span class="mtk12">value</span><span class="mtk1">, </span><span class="mtk12">index</span><span class="mtk1">, </span><span class="mtk12">key</span><span class="mtk1">) {</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk4">this</span><span class="mtk1">.</span><span class="mtk12">tableItems</span><span class="mtk1">[</span><span class="mtk12">index</span><span class="mtk1">][</span><span class="mtk12">key</span><span class="mtk1">] = </span><span class="mtk12">value</span><span class="mtk1">;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk4">this</span><span class="mtk1">.</span><span class="mtk11">$set</span><span class="mtk1">(</span><span class="mtk4">this</span><span class="mtk1">.</span><span class="mtk12">tableItems</span><span class="mtk1">, </span><span class="mtk12">index</span><span class="mtk1">, </span><span class="mtk4">this</span><span class="mtk1">.</span><span class="mtk12">tableItems</span><span class="mtk1">[</span><span class="mtk12">index</span><span class="mtk1">]);</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk4">this</span><span class="mtk1">.</span><span class="mtk11">$emit</span><span class="mtk1">(</span><span class="mtk8">&quot;input&quot;</span><span class="mtk1">, </span><span class="mtk4">this</span><span class="mtk1">.</span><span class="mtk12">tableItems</span><span class="mtk1">);</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> },</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk11">addRowHandler</span><span class="mtk1">() {</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk4">const</span><span class="mtk1"> </span><span class="mtk12">newRow</span><span class="mtk1"> = </span><span class="mtk4">this</span><span class="mtk1">.</span><span class="mtk12">fields</span><span class="mtk1">.</span><span class="mtk11">reduce</span><span class="mtk1">((</span><span class="mtk12">a</span><span class="mtk1">, </span><span class="mtk12">c</span><span class="mtk1">) </span><span class="mtk4">=&gt;</span><span class="mtk1"> ({...</span><span class="mtk12">a</span><span class="mtk1">, </span><span class="mtk12">[c.key]:</span><span class="mtk1"> </span><span class="mtk4">null</span><span class="mtk1">}) ,{})</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">newRow</span><span class="mtk1">.</span><span class="mtk12">isEdit</span><span class="mtk1"> = </span><span class="mtk4">true</span><span class="mtk1">;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk4">this</span><span class="mtk1">.</span><span class="mtk12">tableItems</span><span class="mtk1">.</span><span class="mtk11">unshift</span><span class="mtk1">(</span><span class="mtk12">newRow</span><span class="mtk1">);</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk4">this</span><span class="mtk1">.</span><span class="mtk11">$emit</span><span class="mtk1">(</span><span class="mtk8">&#39;input&#39;</span><span class="mtk1">, </span><span class="mtk4">this</span><span class="mtk1">.</span><span class="mtk12">tableItems</span><span class="mtk1">);</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> },</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk11">removeRowHandler</span><span class="mtk1">(</span><span class="mtk12">index</span><span class="mtk1">) {</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk4">this</span><span class="mtk1">.</span><span class="mtk12">tableItems</span><span class="mtk1"> = </span><span class="mtk4">this</span><span class="mtk1">.</span><span class="mtk12">tableItems</span><span class="mtk1">.</span><span class="mtk11">filter</span><span class="mtk1">((</span><span class="mtk12">item</span><span class="mtk1">, </span><span class="mtk12">i</span><span class="mtk1">) </span><span class="mtk4">=&gt;</span><span class="mtk1"> </span><span class="mtk12">i</span><span class="mtk1"> !== </span><span class="mtk12">index</span><span class="mtk1">);</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk4">this</span><span class="mtk1">.</span><span class="mtk11">$emit</span><span class="mtk1">(</span><span class="mtk8">&#39;input&#39;</span><span class="mtk1">, </span><span class="mtk4">this</span><span class="mtk1">.</span><span class="mtk12">tableItems</span><span class="mtk1">);</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> },</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk11">removeRowsHandler</span><span class="mtk1">() {</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk4">this</span><span class="mtk1">.</span><span class="mtk12">tableItems</span><span class="mtk1"> = </span><span class="mtk4">this</span><span class="mtk1">.</span><span class="mtk12">tableItems</span><span class="mtk1">.</span><span class="mtk11">filter</span><span class="mtk1">(</span><span class="mtk12">item</span><span class="mtk1"> </span><span class="mtk4">=&gt;</span><span class="mtk1"> !</span><span class="mtk12">item</span><span class="mtk1">.</span><span class="mtk12">isSelected</span><span class="mtk1">);</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk4">this</span><span class="mtk1">.</span><span class="mtk11">$emit</span><span class="mtk1">(</span><span class="mtk8">&#39;input&#39;</span><span class="mtk1">, </span><span class="mtk4">this</span><span class="mtk1">.</span><span class="mtk12">tableItems</span><span class="mtk1">);</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> },</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk11">selectRowHandler</span><span class="mtk1">(</span><span class="mtk12">data</span><span class="mtk1">) {</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk4">this</span><span class="mtk1">.</span><span class="mtk12">tableItems</span><span class="mtk1">[</span><span class="mtk12">data</span><span class="mtk1">.</span><span class="mtk12">index</span><span class="mtk1">].</span><span class="mtk12">isSelected</span><span class="mtk1"> = !</span><span class="mtk4">this</span><span class="mtk1">.</span><span class="mtk12">tableItems</span><span class="mtk1">[</span><span class="mtk12">data</span><span class="mtk1">.</span><span class="mtk12">index</span><span class="mtk1">].</span><span class="mtk12">isSelected</span><span class="mtk1">;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> }</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> }</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1">};</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk17">&lt;/</span><span class="mtk4">script</span><span class="mtk17">&gt;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk17">&lt;</span><span class="mtk4">style</span><span class="mtk17">&gt;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk6">.action-container</span><span class="mtk1"> {</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">margin-bottom</span><span class="mtk1">: </span><span class="mtk7">10px</span><span class="mtk1">;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> }</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk6">.action-container</span><span class="mtk1"> </span><span class="mtk6">button</span><span class="mtk1"> {</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">margin-right</span><span class="mtk1">: </span><span class="mtk7">5px</span><span class="mtk1">;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> }</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk6">.delete-button</span><span class="mtk1"> {</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">margin-left</span><span class="mtk1">: </span><span class="mtk7">5px</span><span class="mtk1">;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> }</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk17">&lt;/</span><span class="mtk4">style</span><span class="mtk17">&gt;</span></span></span></code></pre> <h5 id="app-component-1" style="position:relative;"><a href="#app-component-1" aria-label="app component 1 permalink" class="anchor before"><svg aria-hidden="true" focusable="false" height="16" version="1.1" viewBox="0 0 16 16" width="16"><path fill-rule="evenodd" d="M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z"></path></svg></a>App component:</h5> <pre class="grvsc-container default-dark" data-language="html" data-index="10"><code class="grvsc-code"><span class="grvsc-line"><span class="grvsc-source"><span class="mtk17">&lt;</span><span class="mtk4">template</span><span class="mtk17">&gt;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk17">&lt;</span><span class="mtk4">div</span><span class="mtk1"> </span><span class="mtk12">id</span><span class="mtk1">=</span><span class="mtk8">&quot;app&quot;</span><span class="mtk17">&gt;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk17">&lt;</span><span class="mtk4">EditableTable</span><span class="mtk1"> </span><span class="mtk12">v-model</span><span class="mtk1">=</span><span class="mtk8">&quot;items&quot;</span><span class="mtk1"> </span><span class="mtk12">:fields</span><span class="mtk1">=</span><span class="mtk8">&quot;fields&quot;</span><span class="mtk17">&gt;&lt;/</span><span class="mtk4">EditableTable</span><span class="mtk17">&gt;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk17">&lt;/</span><span class="mtk4">div</span><span class="mtk17">&gt;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk17">&lt;/</span><span class="mtk4">template</span><span class="mtk17">&gt;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk17">&lt;</span><span class="mtk4">script</span><span class="mtk17">&gt;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk15">import</span><span class="mtk1"> </span><span class="mtk12">EditableTable</span><span class="mtk1"> </span><span class="mtk15">from</span><span class="mtk1"> </span><span class="mtk8">&#39;./components/EditableTable.vue&#39;</span><span class="mtk1">;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk15">export</span><span class="mtk1"> </span><span class="mtk15">default</span><span class="mtk1"> {</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">name:</span><span class="mtk1"> </span><span class="mtk8">&quot;App&quot;</span><span class="mtk1">,</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">components:</span><span class="mtk1"> {</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">EditableTable</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> },</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk11">data</span><span class="mtk1">() {</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk15">return</span><span class="mtk1"> {</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">fields:</span><span class="mtk1"> [</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> { </span><span class="mtk12">key:</span><span class="mtk1"> </span><span class="mtk8">&quot;selectRow&quot;</span><span class="mtk1">, </span><span class="mtk12">label:</span><span class="mtk1"> </span><span class="mtk8">&quot;&quot;</span><span class="mtk1"> },</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> { </span><span class="mtk12">key:</span><span class="mtk1"> </span><span class="mtk8">&quot;name&quot;</span><span class="mtk1">, </span><span class="mtk12">label:</span><span class="mtk1"> </span><span class="mtk8">&quot;Name&quot;</span><span class="mtk1">, </span><span class="mtk12">type:</span><span class="mtk1"> </span><span class="mtk8">&quot;text&quot;</span><span class="mtk1"> },</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> { </span><span class="mtk12">key:</span><span class="mtk1"> </span><span class="mtk8">&quot;department&quot;</span><span class="mtk1">, </span><span class="mtk12">label:</span><span class="mtk1"> </span><span class="mtk8">&quot;Department&quot;</span><span class="mtk1">, </span><span class="mtk12">type:</span><span class="mtk1"> </span><span class="mtk8">&quot;select&quot;</span><span class="mtk1">, </span><span class="mtk12">options:</span><span class="mtk1"> [</span><span class="mtk8">&#39;Development&#39;</span><span class="mtk1">, </span><span class="mtk8">&#39;Marketing&#39;</span><span class="mtk1">, </span><span class="mtk8">&#39;HR&#39;</span><span class="mtk1">, </span><span class="mtk8">&#39;Accounting&#39;</span><span class="mtk1">] },</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> { </span><span class="mtk12">key:</span><span class="mtk1"> </span><span class="mtk8">&quot;age&quot;</span><span class="mtk1">, </span><span class="mtk12">label:</span><span class="mtk1"> </span><span class="mtk8">&quot;Age&quot;</span><span class="mtk1">, </span><span class="mtk12">type:</span><span class="mtk1"> </span><span class="mtk8">&quot;number&quot;</span><span class="mtk1"> },</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> { </span><span class="mtk12">key:</span><span class="mtk1"> </span><span class="mtk8">&quot;dateOfBirth&quot;</span><span class="mtk1">, </span><span class="mtk12">label:</span><span class="mtk1"> </span><span class="mtk8">&quot;Date Of Birth&quot;</span><span class="mtk1">, </span><span class="mtk12">type:</span><span class="mtk1"> </span><span class="mtk8">&quot;date&quot;</span><span class="mtk1"> },</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> { </span><span class="mtk12">key:</span><span class="mtk1"> </span><span class="mtk8">&quot;edit&quot;</span><span class="mtk1">, </span><span class="mtk12">label:</span><span class="mtk1"> </span><span class="mtk8">&quot;&quot;</span><span class="mtk1">, </span><span class="mtk12">type:</span><span class="mtk1"> </span><span class="mtk8">&quot;edit&quot;</span><span class="mtk1"> }</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> ],</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">items:</span><span class="mtk1"> [</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> { </span><span class="mtk12">age:</span><span class="mtk1"> </span><span class="mtk7">40</span><span class="mtk1">, </span><span class="mtk12">name:</span><span class="mtk1"> </span><span class="mtk8">&#39;Dickerson&#39;</span><span class="mtk1">, </span><span class="mtk12">department:</span><span class="mtk1"> </span><span class="mtk8">&#39;Development&#39;</span><span class="mtk1">, </span><span class="mtk12">dateOfBirth:</span><span class="mtk1"> </span><span class="mtk8">&#39;1984-05-20&#39;</span><span class="mtk1"> },</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> { </span><span class="mtk12">age:</span><span class="mtk1"> </span><span class="mtk7">21</span><span class="mtk1">, </span><span class="mtk12">name:</span><span class="mtk1"> </span><span class="mtk8">&#39;Larsen&#39;</span><span class="mtk1">, </span><span class="mtk12">department:</span><span class="mtk1"> </span><span class="mtk8">&#39;Marketing&#39;</span><span class="mtk1">, </span><span class="mtk12">dateOfBirth:</span><span class="mtk1"> </span><span class="mtk8">&#39;1984-05-20&#39;</span><span class="mtk1"> },</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> { </span><span class="mtk12">age:</span><span class="mtk1"> </span><span class="mtk7">89</span><span class="mtk1">, </span><span class="mtk12">name:</span><span class="mtk1"> </span><span class="mtk8">&#39;Geneva&#39;</span><span class="mtk1">, </span><span class="mtk12">department:</span><span class="mtk1"> </span><span class="mtk8">&#39;HR&#39;</span><span class="mtk1">, </span><span class="mtk12">dateOfBirth:</span><span class="mtk1"> </span><span class="mtk8">&#39;1984-05-20&#39;</span><span class="mtk1"> },</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> { </span><span class="mtk12">age:</span><span class="mtk1"> </span><span class="mtk7">38</span><span class="mtk1">, </span><span class="mtk12">name:</span><span class="mtk1"> </span><span class="mtk8">&#39;Jami&#39;</span><span class="mtk1">, </span><span class="mtk12">department:</span><span class="mtk1"> </span><span class="mtk8">&#39;Accounting&#39;</span><span class="mtk1">, </span><span class="mtk12">dateOfBirth:</span><span class="mtk1"> </span><span class="mtk8">&#39;1984-05-20&#39;</span><span class="mtk1"> }</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> ]</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> };</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> }</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1">};</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk17">&lt;/</span><span class="mtk4">script</span><span class="mtk17">&gt;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk17">&lt;</span><span class="mtk4">style</span><span class="mtk17">&gt;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk6">#app</span><span class="mtk1"> {</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">margin</span><span class="mtk1">: </span><span class="mtk7">20px</span><span class="mtk1">;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1">}</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk17">&lt;/</span><span class="mtk4">style</span><span class="mtk17">&gt;</span></span></span></code></pre> <h5 id="demo-2" style="position:relative;"><a href="#demo-2" aria-label="demo 2 permalink" class="anchor before"><svg aria-hidden="true" focusable="false" height="16" version="1.1" viewBox="0 0 16 16" width="16"><path fill-rule="evenodd" d="M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z"></path></svg></a>Demo:</h5> <div data-youtube="vnxOC9LQm5w"> <button>Play Example</button> </div> <h2 id="confirmation-dialog" style="position:relative;"><a href="#confirmation-dialog" aria-label="confirmation dialog permalink" class="anchor before"><svg aria-hidden="true" focusable="false" height="16" version="1.1" viewBox="0 0 16 16" width="16"><path fill-rule="evenodd" d="M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z"></path></svg></a>Confirmation dialog</h2> <p>If we are triggering an API call that deletes data from the database, it’s a good idea to add a confirmation dialog before proceeding. This requires few easy steps:</p> <ul> <li>Add a new <code>b-modal</code> component with a title and body content</li> <li>Create a new <code>openDialog</code> flag to open and close the dialog. We can use it in the <code>v-model</code> prop available in the Modal component</li> <li>We’ll change the remove button event handler to open the dialog and the <code>removeRowsHandler</code> event handler will now be triggered on the Modal submit event instead</li> </ul> <h5 id="editabletable-component-full-code" style="position:relative;"><a href="#editabletable-component-full-code" aria-label="editabletable component full code permalink" class="anchor before"><svg aria-hidden="true" focusable="false" height="16" version="1.1" viewBox="0 0 16 16" width="16"><path fill-rule="evenodd" d="M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z"></path></svg></a>EditableTable component full code:</h5> <pre class="grvsc-container default-dark" data-language="html" data-index="11"><code class="grvsc-code"><span class="grvsc-line"><span class="grvsc-source"><span class="mtk17">&lt;</span><span class="mtk4">template</span><span class="mtk17">&gt;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk17">&lt;</span><span class="mtk4">article</span><span class="mtk17">&gt;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk17">&lt;</span><span class="mtk4">b-modal</span><span class="mtk1"> </span><span class="mtk12">id</span><span class="mtk1">=</span><span class="mtk8">&quot;modal-1&quot;</span><span class="mtk1"> </span><span class="mtk12">title</span><span class="mtk1">=</span><span class="mtk8">&quot;Confirm&quot;</span><span class="mtk1"> </span><span class="mtk12">v-model</span><span class="mtk1">=</span><span class="mtk8">&quot;openDialog&quot;</span><span class="mtk1"> </span><span class="mtk12">ok-title</span><span class="mtk1">=</span><span class="mtk8">&quot;Remove&quot;</span><span class="mtk1"> </span><span class="mtk12">@ok</span><span class="mtk1">=</span><span class="mtk8">&quot;removeRowsHandler&quot;</span><span class="mtk17">&gt;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk17">&lt;</span><span class="mtk4">p</span><span class="mtk1"> </span><span class="mtk12">class</span><span class="mtk1">=</span><span class="mtk8">&quot;my-4&quot;</span><span class="mtk17">&gt;</span><span class="mtk1">Are you sure you want to remove the selected rows?</span><span class="mtk17">&lt;/</span><span class="mtk4">p</span><span class="mtk17">&gt;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk17">&lt;/</span><span class="mtk4">b-modal</span><span class="mtk17">&gt;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk17">&lt;</span><span class="mtk4">div</span><span class="mtk1"> </span><span class="mtk12">class</span><span class="mtk1">=</span><span class="mtk8">&quot;action-container&quot;</span><span class="mtk17">&gt;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk17">&lt;</span><span class="mtk4">b-button</span><span class="mtk1"> </span><span class="mtk12">class</span><span class="mtk1">=</span><span class="mtk8">&quot;add-button&quot;</span><span class="mtk1"> </span><span class="mtk12">variant</span><span class="mtk1">=</span><span class="mtk8">&quot;success&quot;</span><span class="mtk1"> </span><span class="mtk12">@click</span><span class="mtk1">=</span><span class="mtk8">&quot;addRowHandler&quot;</span><span class="mtk17">&gt;</span><span class="mtk1">Add Row</span><span class="mtk17">&lt;/</span><span class="mtk4">b-button</span><span class="mtk17">&gt;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk17">&lt;</span><span class="mtk4">b-button</span><span class="mtk1"> </span><span class="mtk12">variant</span><span class="mtk1">=</span><span class="mtk8">&quot;danger&quot;</span><span class="mtk1"> </span><span class="mtk12">@click</span><span class="mtk1">=</span><span class="mtk8">&quot;openDialog = true&quot;</span><span class="mtk17">&gt;</span><span class="mtk1">Delete Rows</span><span class="mtk17">&lt;/</span><span class="mtk4">b-button</span><span class="mtk17">&gt;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk17">&lt;/</span><span class="mtk4">div</span><span class="mtk17">&gt;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk17">&lt;</span><span class="mtk4">b-table</span><span class="mtk1"> </span><span class="mtk12">class</span><span class="mtk1">=</span><span class="mtk8">&quot;b-table&quot;</span><span class="mtk1"> </span><span class="mtk12">:items</span><span class="mtk1">=</span><span class="mtk8">&quot;tableItems&quot;</span><span class="mtk1"> </span><span class="mtk12">:fields</span><span class="mtk1">=</span><span class="mtk8">&quot;fields&quot;</span><span class="mtk1"> </span><span class="mtk12">fixed</span><span class="mtk17">&gt;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk17">&lt;</span><span class="mtk4">template</span><span class="mtk1"> </span><span class="mtk12">v-for</span><span class="mtk1">=</span><span class="mtk8">&quot;(field, index) in fields&quot;</span><span class="mtk1"> </span><span class="mtk12">#[`cell(${field.key})`]</span><span class="mtk1">=</span><span class="mtk8">&quot;data&quot;</span><span class="mtk17">&gt;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk17">&lt;</span><span class="mtk4">b-form-datepicker</span><span class="mtk1"> </span><span class="mtk12">v-if</span><span class="mtk1">=</span><span class="mtk8">&quot;field.type === &#39;date&#39; &amp;&amp; tableItems[data.index].isEdit&quot;</span><span class="mtk1"> </span><span class="mtk12">:key</span><span class="mtk1">=</span><span class="mtk8">&quot;index&quot;</span><span class="mtk1"> </span><span class="mtk12">:type</span><span class="mtk1">=</span><span class="mtk8">&quot;field.type&quot;</span><span class="mtk1"> </span><span class="mtk12">:value</span><span class="mtk1">=</span><span class="mtk8">&quot;tableItems[data.index][field.key]&quot;</span><span class="mtk1"> </span><span class="mtk12">@input</span><span class="mtk1">=</span><span class="mtk8">&quot;(value) =&gt; inputHandler(value, data.index, field.key)&quot;</span><span class="mtk17">&gt;&lt;/</span><span class="mtk4">b-form-datepicker</span><span class="mtk17">&gt;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk17">&lt;</span><span class="mtk4">b-form-select</span><span class="mtk1"> </span><span class="mtk12">v-else-if</span><span class="mtk1">=</span><span class="mtk8">&quot;field.type === &#39;select&#39; &amp;&amp; tableItems[data.index].isEdit&quot;</span><span class="mtk1"> </span><span class="mtk12">:key</span><span class="mtk1">=</span><span class="mtk8">&quot;index&quot;</span><span class="mtk1"> </span><span class="mtk12">:value</span><span class="mtk1">=</span><span class="mtk8">&quot;tableItems[data.index][field.key]&quot;</span><span class="mtk1"> </span><span class="mtk12">@input</span><span class="mtk1">=</span><span class="mtk8">&quot;(value) =&gt; inputHandler(value, data.index, field.key)&quot;</span><span class="mtk1"> </span><span class="mtk12">:options</span><span class="mtk1">=</span><span class="mtk8">&quot;field.options&quot;</span><span class="mtk17">&gt;&lt;/</span><span class="mtk4">b-form-select</span><span class="mtk17">&gt;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk17">&lt;</span><span class="mtk4">b-checkbox</span><span class="mtk1"> </span><span class="mtk12">v-else-if</span><span class="mtk1">=</span><span class="mtk8">&quot;field.key === &#39;selectRow&#39;&quot;</span><span class="mtk1"> </span><span class="mtk12">:checked</span><span class="mtk1">=</span><span class="mtk8">&quot;tableItems[data.index].isSelected&quot;</span><span class="mtk1"> </span><span class="mtk12">:key</span><span class="mtk1">=</span><span class="mtk8">&quot;index&quot;</span><span class="mtk1"> </span><span class="mtk12">@change</span><span class="mtk1">=</span><span class="mtk8">&quot;selectRowHandler(data)&quot;</span><span class="mtk17">&gt;&lt;/</span><span class="mtk4">b-checkbox</span><span class="mtk17">&gt;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk17">&lt;</span><span class="mtk4">div</span><span class="mtk1"> </span><span class="mtk12">:key</span><span class="mtk1">=</span><span class="mtk8">&quot;index&quot;</span><span class="mtk1"> </span><span class="mtk12">v-else-if</span><span class="mtk1">=</span><span class="mtk8">&quot;field.type === &#39;edit&#39;&quot;</span><span class="mtk17">&gt;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk17">&lt;</span><span class="mtk4">b-button</span><span class="mtk1"> </span><span class="mtk12">@click</span><span class="mtk1">=</span><span class="mtk8">&quot;editRowHandler(data)&quot;</span><span class="mtk17">&gt;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk17">&lt;</span><span class="mtk4">span</span><span class="mtk1"> </span><span class="mtk12">v-if</span><span class="mtk1">=</span><span class="mtk8">&quot;!tableItems[data.index].isEdit&quot;</span><span class="mtk17">&gt;</span><span class="mtk1">Edit</span><span class="mtk17">&lt;/</span><span class="mtk4">span</span><span class="mtk17">&gt;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk17">&lt;</span><span class="mtk4">span</span><span class="mtk1"> </span><span class="mtk12">v-else</span><span class="mtk17">&gt;</span><span class="mtk1">Done</span><span class="mtk17">&lt;/</span><span class="mtk4">span</span><span class="mtk17">&gt;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk17">&lt;/</span><span class="mtk4">b-button</span><span class="mtk17">&gt;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk17">&lt;</span><span class="mtk4">b-button</span><span class="mtk1"> </span><span class="mtk12">class</span><span class="mtk1">=</span><span class="mtk8">&quot;delete-button&quot;</span><span class="mtk1"> </span><span class="mtk12">variant</span><span class="mtk1">=</span><span class="mtk8">&quot;danger&quot;</span><span class="mtk1"> </span><span class="mtk12">@click</span><span class="mtk1">=</span><span class="mtk8">&quot;removeRowHandler(data.index)&quot;</span><span class="mtk17">&gt;</span><span class="mtk1">Remove</span><span class="mtk17">&lt;/</span><span class="mtk4">b-button</span><span class="mtk17">&gt;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk17">&lt;/</span><span class="mtk4">div</span><span class="mtk17">&gt;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk17">&lt;</span><span class="mtk4">b-form-input</span><span class="mtk1"> </span><span class="mtk12">v-else-if</span><span class="mtk1">=</span><span class="mtk8">&quot;field.type &amp;&amp; tableItems[data.index].isEdit&quot;</span><span class="mtk1"> </span><span class="mtk12">:key</span><span class="mtk1">=</span><span class="mtk8">&quot;index&quot;</span><span class="mtk1"> </span><span class="mtk12">:type</span><span class="mtk1">=</span><span class="mtk8">&quot;field.type&quot;</span><span class="mtk1"> </span><span class="mtk12">:value</span><span class="mtk1">=</span><span class="mtk8">&quot;tableItems[data.index][field.key]&quot;</span><span class="mtk1"> </span><span class="mtk12">@blur</span><span class="mtk1">=</span><span class="mtk8">&quot;(e) =&gt; inputHandler(e.target.value, data.index, field.key)&quot;</span><span class="mtk17">&gt;&lt;/</span><span class="mtk4">b-form-input</span><span class="mtk17">&gt;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk17">&lt;</span><span class="mtk4">span</span><span class="mtk1"> </span><span class="mtk12">:key</span><span class="mtk1">=</span><span class="mtk8">&quot;index&quot;</span><span class="mtk1"> </span><span class="mtk12">v-else</span><span class="mtk17">&gt;</span><span class="mtk1">{{data.value}}</span><span class="mtk17">&lt;/</span><span class="mtk4">span</span><span class="mtk17">&gt;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk17">&lt;/</span><span class="mtk4">template</span><span class="mtk17">&gt;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk17">&lt;/</span><span class="mtk4">b-table</span><span class="mtk17">&gt;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk17">&lt;/</span><span class="mtk4">article</span><span class="mtk17">&gt;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk17">&lt;/</span><span class="mtk4">template</span><span class="mtk17">&gt;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk17">&lt;</span><span class="mtk4">script</span><span class="mtk17">&gt;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk15">export</span><span class="mtk1"> </span><span class="mtk15">default</span><span class="mtk1"> {</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">name:</span><span class="mtk1"> </span><span class="mtk8">&quot;EditableTable&quot;</span><span class="mtk1">,</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">components:</span><span class="mtk1"> {},</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">props:</span><span class="mtk1"> {</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">value:</span><span class="mtk1"> </span><span class="mtk10">Array</span><span class="mtk1">,</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">fields:</span><span class="mtk1"> </span><span class="mtk10">Array</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> },</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk11">data</span><span class="mtk1">() {</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk15">return</span><span class="mtk1"> {</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">tableItems:</span><span class="mtk1"> </span><span class="mtk4">this</span><span class="mtk1">.</span><span class="mtk12">value</span><span class="mtk1">.</span><span class="mtk11">map</span><span class="mtk1">(</span><span class="mtk12">item</span><span class="mtk1"> </span><span class="mtk4">=&gt;</span><span class="mtk1"> ({...</span><span class="mtk12">item</span><span class="mtk1">, </span><span class="mtk12">isEdit:</span><span class="mtk1"> </span><span class="mtk4">false</span><span class="mtk1">, </span><span class="mtk12">isSelected:</span><span class="mtk1"> </span><span class="mtk4">false</span><span class="mtk1">})),</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">openDialog:</span><span class="mtk1"> </span><span class="mtk4">false</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> }</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> },</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">methods:</span><span class="mtk1"> {</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk11">editRowHandler</span><span class="mtk1">(</span><span class="mtk12">data</span><span class="mtk1">) {</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk4">this</span><span class="mtk1">.</span><span class="mtk12">tableItems</span><span class="mtk1">[</span><span class="mtk12">data</span><span class="mtk1">.</span><span class="mtk12">index</span><span class="mtk1">].</span><span class="mtk12">isEdit</span><span class="mtk1"> = !</span><span class="mtk4">this</span><span class="mtk1">.</span><span class="mtk12">tableItems</span><span class="mtk1">[</span><span class="mtk12">data</span><span class="mtk1">.</span><span class="mtk12">index</span><span class="mtk1">].</span><span class="mtk12">isEdit</span><span class="mtk1">;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> },</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk11">inputHandler</span><span class="mtk1">(</span><span class="mtk12">value</span><span class="mtk1">, </span><span class="mtk12">index</span><span class="mtk1">, </span><span class="mtk12">key</span><span class="mtk1">) {</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk4">this</span><span class="mtk1">.</span><span class="mtk12">tableItems</span><span class="mtk1">[</span><span class="mtk12">index</span><span class="mtk1">][</span><span class="mtk12">key</span><span class="mtk1">] = </span><span class="mtk12">value</span><span class="mtk1">;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk4">this</span><span class="mtk1">.</span><span class="mtk11">$set</span><span class="mtk1">(</span><span class="mtk4">this</span><span class="mtk1">.</span><span class="mtk12">tableItems</span><span class="mtk1">, </span><span class="mtk12">index</span><span class="mtk1">, </span><span class="mtk4">this</span><span class="mtk1">.</span><span class="mtk12">tableItems</span><span class="mtk1">[</span><span class="mtk12">index</span><span class="mtk1">]);</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk4">this</span><span class="mtk1">.</span><span class="mtk11">$emit</span><span class="mtk1">(</span><span class="mtk8">&quot;input&quot;</span><span class="mtk1">, </span><span class="mtk4">this</span><span class="mtk1">.</span><span class="mtk12">tableItems</span><span class="mtk1">);</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> },</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk11">addRowHandler</span><span class="mtk1">() {</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk4">const</span><span class="mtk1"> </span><span class="mtk12">newRow</span><span class="mtk1"> = </span><span class="mtk4">this</span><span class="mtk1">.</span><span class="mtk12">fields</span><span class="mtk1">.</span><span class="mtk11">reduce</span><span class="mtk1">((</span><span class="mtk12">a</span><span class="mtk1">, </span><span class="mtk12">c</span><span class="mtk1">) </span><span class="mtk4">=&gt;</span><span class="mtk1"> ({...</span><span class="mtk12">a</span><span class="mtk1">, </span><span class="mtk12">[c.key]:</span><span class="mtk1"> </span><span class="mtk4">null</span><span class="mtk1">}) ,{})</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">newRow</span><span class="mtk1">.</span><span class="mtk12">isEdit</span><span class="mtk1"> = </span><span class="mtk4">true</span><span class="mtk1">;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk4">this</span><span class="mtk1">.</span><span class="mtk12">tableItems</span><span class="mtk1">.</span><span class="mtk11">unshift</span><span class="mtk1">(</span><span class="mtk12">newRow</span><span class="mtk1">);</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk4">this</span><span class="mtk1">.</span><span class="mtk11">$emit</span><span class="mtk1">(</span><span class="mtk8">&#39;input&#39;</span><span class="mtk1">, </span><span class="mtk4">this</span><span class="mtk1">.</span><span class="mtk12">tableItems</span><span class="mtk1">);</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> },</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk11">removeRowHandler</span><span class="mtk1">(</span><span class="mtk12">index</span><span class="mtk1">) {</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk4">this</span><span class="mtk1">.</span><span class="mtk12">tableItems</span><span class="mtk1"> = </span><span class="mtk4">this</span><span class="mtk1">.</span><span class="mtk12">tableItems</span><span class="mtk1">.</span><span class="mtk11">filter</span><span class="mtk1">((</span><span class="mtk12">item</span><span class="mtk1">, </span><span class="mtk12">i</span><span class="mtk1">) </span><span class="mtk4">=&gt;</span><span class="mtk1"> </span><span class="mtk12">i</span><span class="mtk1"> !== </span><span class="mtk12">index</span><span class="mtk1">);</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk4">this</span><span class="mtk1">.</span><span class="mtk11">$emit</span><span class="mtk1">(</span><span class="mtk8">&#39;input&#39;</span><span class="mtk1">, </span><span class="mtk4">this</span><span class="mtk1">.</span><span class="mtk12">tableItems</span><span class="mtk1">);</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> },</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk11">removeRowsHandler</span><span class="mtk1">() {</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk4">this</span><span class="mtk1">.</span><span class="mtk12">tableItems</span><span class="mtk1"> = </span><span class="mtk4">this</span><span class="mtk1">.</span><span class="mtk12">tableItems</span><span class="mtk1">.</span><span class="mtk11">filter</span><span class="mtk1">(</span><span class="mtk12">item</span><span class="mtk1"> </span><span class="mtk4">=&gt;</span><span class="mtk1"> !</span><span class="mtk12">item</span><span class="mtk1">.</span><span class="mtk12">isSelected</span><span class="mtk1">);</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk4">this</span><span class="mtk1">.</span><span class="mtk11">$emit</span><span class="mtk1">(</span><span class="mtk8">&#39;input&#39;</span><span class="mtk1">, </span><span class="mtk4">this</span><span class="mtk1">.</span><span class="mtk12">tableItems</span><span class="mtk1">);</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> },</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk11">selectRowHandler</span><span class="mtk1">(</span><span class="mtk12">data</span><span class="mtk1">) {</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk4">this</span><span class="mtk1">.</span><span class="mtk12">tableItems</span><span class="mtk1">[</span><span class="mtk12">data</span><span class="mtk1">.</span><span class="mtk12">index</span><span class="mtk1">].</span><span class="mtk12">isSelected</span><span class="mtk1"> = !</span><span class="mtk4">this</span><span class="mtk1">.</span><span class="mtk12">tableItems</span><span class="mtk1">[</span><span class="mtk12">data</span><span class="mtk1">.</span><span class="mtk12">index</span><span class="mtk1">].</span><span class="mtk12">isSelected</span><span class="mtk1">;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> }</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> }</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1">};</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk17">&lt;/</span><span class="mtk4">script</span><span class="mtk17">&gt;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk17">&lt;</span><span class="mtk4">style</span><span class="mtk17">&gt;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk6">.action-container</span><span class="mtk1"> {</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">margin-bottom</span><span class="mtk1">: </span><span class="mtk7">10px</span><span class="mtk1">;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> }</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk6">.action-container</span><span class="mtk1"> </span><span class="mtk6">button</span><span class="mtk1"> {</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">margin-right</span><span class="mtk1">: </span><span class="mtk7">5px</span><span class="mtk1">;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> }</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk6">.delete-button</span><span class="mtk1"> {</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">margin-left</span><span class="mtk1">: </span><span class="mtk7">5px</span><span class="mtk1">;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> }</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk17">&lt;/</span><span class="mtk4">style</span><span class="mtk17">&gt;</span></span></span></code></pre> <h5 id="demo-3" style="position:relative;"><a href="#demo-3" aria-label="demo 3 permalink" class="anchor before"><svg aria-hidden="true" focusable="false" height="16" version="1.1" viewBox="0 0 16 16" width="16"><path fill-rule="evenodd" d="M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z"></path></svg></a>Demo:</h5> <div data-youtube="0cXBTKhaCAc"> <button>Play Example</button> </div> <h2 id="summary" style="position:relative;"><a href="#summary" aria-label="summary permalink" class="anchor before"><svg aria-hidden="true" focusable="false" height="16" version="1.1" viewBox="0 0 16 16" width="16"><path fill-rule="evenodd" d="M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z"></path></svg></a>Summary</h2> <p>If you made it to this section, pat yourself on the back! You just learned how to:</p> <ul> <li>Add and remove table rows</li> <li>Create a multi-select feature that removes multiple rows</li> <li>Confirmation dialog before removing table rows</li> </ul> <p>You can access the <a href="https://github.com/muhimasri/vue-editable-table-example">complete repository here</a>.</p> <p>Bye for now 👋</p> <style class="grvsc-styles"> .grvsc-container { overflow: auto; position: relative; -webkit-overflow-scrolling: touch; padding-top: 1rem; padding-top: var(--grvsc-padding-top, var(--grvsc-padding-v, 1rem)); padding-bottom: 1rem; padding-bottom: var(--grvsc-padding-bottom, var(--grvsc-padding-v, 1rem)); border-radius: 8px; border-radius: var(--grvsc-border-radius, 8px); font-feature-settings: normal; line-height: 1.4; } .grvsc-code { display: table; } .grvsc-line { display: table-row; box-sizing: border-box; width: 100%; position: relative; } .grvsc-line > * { position: relative; } .grvsc-gutter-pad { display: table-cell; padding-left: 0.75rem; padding-left: calc(var(--grvsc-padding-left, var(--grvsc-padding-h, 1.5rem)) / 2); } .grvsc-gutter { display: table-cell; -webkit-user-select: none; -moz-user-select: none; user-select: none; } .grvsc-gutter::before { content: attr(data-content); } .grvsc-source { display: table-cell; padding-left: 1.5rem; padding-left: var(--grvsc-padding-left, var(--grvsc-padding-h, 1.5rem)); padding-right: 1.5rem; padding-right: var(--grvsc-padding-right, var(--grvsc-padding-h, 1.5rem)); } .grvsc-source:empty::after { content: ' '; -webkit-user-select: none; -moz-user-select: none; user-select: none; } .grvsc-gutter + .grvsc-source { padding-left: 0.75rem; padding-left: calc(var(--grvsc-padding-left, var(--grvsc-padding-h, 1.5rem)) / 2); } /* Line transformer styles */ .grvsc-has-line-highlighting > .grvsc-code > .grvsc-line::before { content: ' '; position: absolute; width: 100%; } .grvsc-line-diff-add::before { background-color: var(--grvsc-line-diff-add-background-color, rgba(0, 255, 60, 0.2)); } .grvsc-line-diff-del::before { background-color: var(--grvsc-line-diff-del-background-color, rgba(255, 0, 20, 0.2)); } .grvsc-line-number { padding: 0 2px; text-align: right; opacity: 0.7; } .default-dark { background-color: #1E1E1E; color: #D4D4D4; } .default-dark .mtk17 { color: #808080; } .default-dark .mtk4 { color: #569CD6; } .default-dark .mtk1 { color: #D4D4D4; } .default-dark .mtk12 { color: #9CDCFE; } .default-dark .mtk8 { color: #CE9178; } .default-dark .mtk15 { color: #C586C0; } .default-dark .mtk10 { color: #4EC9B0; } .default-dark .mtk11 { color: #DCDCAA; } .default-dark .mtk6 { color: #D7BA7D; } .default-dark .mtk7 { color: #B5CEA8; } .default-dark .grvsc-line-highlighted::before { background-color: var(--grvsc-line-highlighted-background-color, rgba(255, 255, 255, 0.1)); box-shadow: inset var(--grvsc-line-highlighted-border-width, 4px) 0 0 0 var(--grvsc-line-highlighted-border-color, rgba(255, 255, 255, 0.5)); } </style><![CDATA[[Part 2] Create a Dynamic Table with Bootstrap Vue]]>https://muhimasri.compart-2-create-a-dynamic-table-with-bootstrap-vuehttps://muhimasri.compart-2-create-a-dynamic-table-with-bootstrap-vue<p><a href="https://muhimasri.com/blogs/create-an-editable-dynamic-table-with-bootstrap-vue/">In the previous part</a>, we did a deep dive into editing a table, both at a row and cell level. The approach we did can only support one data schema as the template slots are explicitly using the field keys.</p> <p>In this tutorial, we’ll go through the steps required to make the table dynamic by decoupling the code and reuse it across the whole project with different schemas.</p> <p>Before we start, below is the full code from the <a href="https://muhimasri.com/blogs/create-an-editable-dynamic-table-with-bootstrap-vue/">previous part</a> (editing table rows):</p> <pre class="grvsc-container default-dark" data-language="html" data-index="0"><code class="grvsc-code"><span class="grvsc-line"><span class="grvsc-source"><span class="mtk17">&lt;</span><span class="mtk4">template</span><span class="mtk17">&gt;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk17">&lt;</span><span class="mtk4">article</span><span class="mtk17">&gt;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk17">&lt;</span><span class="mtk4">b-table</span><span class="mtk1"> </span><span class="mtk12">:items</span><span class="mtk1">=</span><span class="mtk8">&quot;items&quot;</span><span class="mtk1"> </span><span class="mtk12">:fields</span><span class="mtk1">=</span><span class="mtk8">&quot;fields&quot;</span><span class="mtk17">&gt;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk17">&lt;</span><span class="mtk4">template</span><span class="mtk1"> </span><span class="mtk12">#cell(name)</span><span class="mtk1">=</span><span class="mtk8">&quot;data&quot;</span><span class="mtk17">&gt;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk17">&lt;</span><span class="mtk4">b-form-input</span><span class="mtk1"> </span><span class="mtk12">v-if</span><span class="mtk1">=</span><span class="mtk8">&quot;items[data.index].isEdit&quot;</span><span class="mtk1"> </span><span class="mtk12">type</span><span class="mtk1">=</span><span class="mtk8">&quot;text&quot;</span><span class="mtk1"> </span><span class="mtk12">v-model</span><span class="mtk1">=</span><span class="mtk8">&quot;items[data.index].name&quot;</span><span class="mtk17">&gt;&lt;/</span><span class="mtk4">b-form-input</span><span class="mtk17">&gt;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk17">&lt;</span><span class="mtk4">span</span><span class="mtk1"> </span><span class="mtk12">v-else</span><span class="mtk17">&gt;</span><span class="mtk1">{{data.value}}</span><span class="mtk17">&lt;/</span><span class="mtk4">span</span><span class="mtk17">&gt;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk17">&lt;/</span><span class="mtk4">template</span><span class="mtk17">&gt;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk17">&lt;</span><span class="mtk4">template</span><span class="mtk1"> </span><span class="mtk12">#cell(department)</span><span class="mtk1">=</span><span class="mtk8">&quot;data&quot;</span><span class="mtk17">&gt;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk17">&lt;</span><span class="mtk4">b-form-select</span><span class="mtk1"> </span><span class="mtk12">v-if</span><span class="mtk1">=</span><span class="mtk8">&quot;items[data.index].isEdit&quot;</span><span class="mtk1"> </span><span class="mtk12">v-model</span><span class="mtk1">=</span><span class="mtk8">&quot;items[data.index].department&quot;</span><span class="mtk1"> </span><span class="mtk12">:options</span><span class="mtk1">=</span><span class="mtk8">&quot;[&#39;Development&#39;, &#39;Marketing&#39;, &#39;HR&#39;, &#39;Accounting&#39;]&quot;</span><span class="mtk17">&gt;&lt;/</span><span class="mtk4">b-form-select</span><span class="mtk17">&gt;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk17">&lt;</span><span class="mtk4">span</span><span class="mtk1"> </span><span class="mtk12">v-else</span><span class="mtk17">&gt;</span><span class="mtk1">{{data.value}}</span><span class="mtk17">&lt;/</span><span class="mtk4">span</span><span class="mtk17">&gt;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk17">&lt;/</span><span class="mtk4">template</span><span class="mtk17">&gt;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk17">&lt;</span><span class="mtk4">template</span><span class="mtk1"> </span><span class="mtk12">#cell(age)</span><span class="mtk1">=</span><span class="mtk8">&quot;data&quot;</span><span class="mtk17">&gt;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk17">&lt;</span><span class="mtk4">b-form-input</span><span class="mtk1"> </span><span class="mtk12">v-if</span><span class="mtk1">=</span><span class="mtk8">&quot;items[data.index].isEdit&quot;</span><span class="mtk1"> </span><span class="mtk12">type</span><span class="mtk1">=</span><span class="mtk8">&quot;number&quot;</span><span class="mtk1"> </span><span class="mtk12">v-model</span><span class="mtk1">=</span><span class="mtk8">&quot;items[data.index].age&quot;</span><span class="mtk17">&gt;&lt;/</span><span class="mtk4">b-form-input</span><span class="mtk17">&gt;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk17">&lt;</span><span class="mtk4">span</span><span class="mtk1"> </span><span class="mtk12">v-else</span><span class="mtk17">&gt;</span><span class="mtk1">{{data.value}}</span><span class="mtk17">&lt;/</span><span class="mtk4">span</span><span class="mtk17">&gt;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk17">&lt;/</span><span class="mtk4">template</span><span class="mtk17">&gt;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk17">&lt;</span><span class="mtk4">template</span><span class="mtk1"> </span><span class="mtk12">#cell(dateOfBirth)</span><span class="mtk1">=</span><span class="mtk8">&quot;data&quot;</span><span class="mtk17">&gt;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk17">&lt;</span><span class="mtk4">b-form-datepicker</span><span class="mtk1"> </span><span class="mtk12">v-if</span><span class="mtk1">=</span><span class="mtk8">&quot;items[data.index].isEdit&quot;</span><span class="mtk1"> </span><span class="mtk12">v-model</span><span class="mtk1">=</span><span class="mtk8">&quot;items[data.index].dateOfBirth&quot;</span><span class="mtk17">&gt;&lt;/</span><span class="mtk4">b-form-datepicker</span><span class="mtk17">&gt;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk17">&lt;</span><span class="mtk4">span</span><span class="mtk1"> </span><span class="mtk12">v-else</span><span class="mtk17">&gt;</span><span class="mtk1">{{data.value}}</span><span class="mtk17">&lt;/</span><span class="mtk4">span</span><span class="mtk17">&gt;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk17">&lt;/</span><span class="mtk4">template</span><span class="mtk17">&gt;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk17">&lt;</span><span class="mtk4">template</span><span class="mtk1"> </span><span class="mtk12">#cell(edit)</span><span class="mtk1">=</span><span class="mtk8">&quot;data&quot;</span><span class="mtk17">&gt;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk17">&lt;</span><span class="mtk4">b-button</span><span class="mtk1"> </span><span class="mtk12">@click</span><span class="mtk1">=</span><span class="mtk8">&quot;editRowHandler(data)&quot;</span><span class="mtk17">&gt;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk17">&lt;</span><span class="mtk4">span</span><span class="mtk1"> </span><span class="mtk12">v-if</span><span class="mtk1">=</span><span class="mtk8">&quot;!items[data.index].isEdit&quot;</span><span class="mtk17">&gt;</span><span class="mtk1">Edit</span><span class="mtk17">&lt;/</span><span class="mtk4">span</span><span class="mtk17">&gt;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk17">&lt;</span><span class="mtk4">span</span><span class="mtk1"> </span><span class="mtk12">v-else</span><span class="mtk17">&gt;</span><span class="mtk1">Done</span><span class="mtk17">&lt;/</span><span class="mtk4">span</span><span class="mtk17">&gt;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk17">&lt;/</span><span class="mtk4">b-button</span><span class="mtk17">&gt;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk17">&lt;/</span><span class="mtk4">template</span><span class="mtk17">&gt;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk17">&lt;/</span><span class="mtk4">b-table</span><span class="mtk17">&gt;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk17">&lt;</span><span class="mtk4">pre</span><span class="mtk17">&gt;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> {{items}}</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk17">&lt;/</span><span class="mtk4">pre</span><span class="mtk17">&gt;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk17">&lt;/</span><span class="mtk4">article</span><span class="mtk17">&gt;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk17">&lt;/</span><span class="mtk4">template</span><span class="mtk17">&gt;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk17">&lt;</span><span class="mtk4">script</span><span class="mtk17">&gt;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk15">export</span><span class="mtk1"> </span><span class="mtk15">default</span><span class="mtk1"> {</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">name:</span><span class="mtk1"> </span><span class="mtk8">&quot;App&quot;</span><span class="mtk1">,</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">components:</span><span class="mtk1"> {},</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk11">data</span><span class="mtk1">() {</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk15">return</span><span class="mtk1"> {</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">fields:</span><span class="mtk1"> [</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> { </span><span class="mtk12">key:</span><span class="mtk1"> </span><span class="mtk8">&quot;name&quot;</span><span class="mtk1">, </span><span class="mtk12">label:</span><span class="mtk1"> </span><span class="mtk8">&quot;Name&quot;</span><span class="mtk1">},</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> { </span><span class="mtk12">key:</span><span class="mtk1"> </span><span class="mtk8">&quot;department&quot;</span><span class="mtk1">, </span><span class="mtk12">label:</span><span class="mtk1"> </span><span class="mtk8">&quot;Department&quot;</span><span class="mtk1"> },</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> { </span><span class="mtk12">key:</span><span class="mtk1"> </span><span class="mtk8">&quot;age&quot;</span><span class="mtk1">, </span><span class="mtk12">label:</span><span class="mtk1"> </span><span class="mtk8">&quot;Age&quot;</span><span class="mtk1"> },</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> { </span><span class="mtk12">key:</span><span class="mtk1"> </span><span class="mtk8">&quot;dateOfBirth&quot;</span><span class="mtk1">, </span><span class="mtk12">label:</span><span class="mtk1"> </span><span class="mtk8">&quot;Date Of Birth&quot;</span><span class="mtk1"> },</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> { </span><span class="mtk12">key:</span><span class="mtk1"> </span><span class="mtk8">&#39;edit&#39;</span><span class="mtk1">, </span><span class="mtk12">label:</span><span class="mtk1"> </span><span class="mtk8">&#39;&#39;</span><span class="mtk1">}</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> ],</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">items:</span><span class="mtk1"> [</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> { </span><span class="mtk12">age:</span><span class="mtk1"> </span><span class="mtk7">40</span><span class="mtk1">, </span><span class="mtk12">name:</span><span class="mtk1"> </span><span class="mtk8">&#39;Dickerson&#39;</span><span class="mtk1">, </span><span class="mtk12">department:</span><span class="mtk1"> </span><span class="mtk8">&#39;Development&#39;</span><span class="mtk1">, </span><span class="mtk12">dateOfBirth:</span><span class="mtk1"> </span><span class="mtk8">&#39;1984-05-20&#39;</span><span class="mtk1"> },</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> { </span><span class="mtk12">age:</span><span class="mtk1"> </span><span class="mtk7">21</span><span class="mtk1">, </span><span class="mtk12">name:</span><span class="mtk1"> </span><span class="mtk8">&#39;Larsen&#39;</span><span class="mtk1">, </span><span class="mtk12">department:</span><span class="mtk1"> </span><span class="mtk8">&#39;Marketing&#39;</span><span class="mtk1">, </span><span class="mtk12">dateOfBirth:</span><span class="mtk1"> </span><span class="mtk8">&#39;1984-05-20&#39;</span><span class="mtk1"> },</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> { </span><span class="mtk12">age:</span><span class="mtk1"> </span><span class="mtk7">89</span><span class="mtk1">, </span><span class="mtk12">name:</span><span class="mtk1"> </span><span class="mtk8">&#39;Geneva&#39;</span><span class="mtk1">, </span><span class="mtk12">department:</span><span class="mtk1"> </span><span class="mtk8">&#39;HR&#39;</span><span class="mtk1">, </span><span class="mtk12">dateOfBirth:</span><span class="mtk1"> </span><span class="mtk8">&#39;1984-05-20&#39;</span><span class="mtk1"> },</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> { </span><span class="mtk12">age:</span><span class="mtk1"> </span><span class="mtk7">38</span><span class="mtk1">, </span><span class="mtk12">name:</span><span class="mtk1"> </span><span class="mtk8">&#39;Jami&#39;</span><span class="mtk1">, </span><span class="mtk12">department:</span><span class="mtk1"> </span><span class="mtk8">&#39;Accounting&#39;</span><span class="mtk1">, </span><span class="mtk12">dateOfBirth:</span><span class="mtk1"> </span><span class="mtk8">&#39;1984-05-20&#39;</span><span class="mtk1"> }</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> ],</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">selectedRow:</span><span class="mtk1"> {}</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> };</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> },</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk11">mounted</span><span class="mtk1">() {</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk4">this</span><span class="mtk1">.</span><span class="mtk12">items</span><span class="mtk1"> = </span><span class="mtk4">this</span><span class="mtk1">.</span><span class="mtk12">items</span><span class="mtk1">.</span><span class="mtk11">map</span><span class="mtk1">(</span><span class="mtk12">item</span><span class="mtk1"> </span><span class="mtk4">=&gt;</span><span class="mtk1"> ({...</span><span class="mtk12">item</span><span class="mtk1">, </span><span class="mtk12">isEdit:</span><span class="mtk1"> </span><span class="mtk4">false</span><span class="mtk1">}));</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> },</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">methods:</span><span class="mtk1"> {</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk11">editRowHandler</span><span class="mtk1">(</span><span class="mtk12">data</span><span class="mtk1">) {</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk4">this</span><span class="mtk1">.</span><span class="mtk12">items</span><span class="mtk1">[</span><span class="mtk12">data</span><span class="mtk1">.</span><span class="mtk12">index</span><span class="mtk1">].</span><span class="mtk12">isEdit</span><span class="mtk1"> = !</span><span class="mtk4">this</span><span class="mtk1">.</span><span class="mtk12">items</span><span class="mtk1">[</span><span class="mtk12">data</span><span class="mtk1">.</span><span class="mtk12">index</span><span class="mtk1">].</span><span class="mtk12">isEdit</span><span class="mtk1">;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> }</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> }</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1">};</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk17">&lt;/</span><span class="mtk4">script</span><span class="mtk17">&gt;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk17">&lt;</span><span class="mtk4">style</span><span class="mtk17">&gt;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk17">&lt;/</span><span class="mtk4">style</span><span class="mtk17">&gt;</span></span></span></code></pre> <p><em>As we continue building upon the same code from previous parts in this series, it’s recommended that you go through these tutorials from the beginning to understand how the code structure works as we will not be explaining it. You can navigate to any part using the table of contents.</em></p> <h2 id="code-encapsulation" style="position:relative;"><a href="#code-encapsulation" aria-label="code encapsulation permalink" class="anchor before"><svg aria-hidden="true" focusable="false" height="16" version="1.1" viewBox="0 0 16 16" width="16"><path fill-rule="evenodd" d="M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z"></path></svg></a>Code encapsulation</h2> <p>Encapsulating the code means creating an independent component with isolated features that can be consumed anywhere in the project. In our case, the editable table code was all done in <code>app.vue</code> so we’ll extract the code to a separate component with the following steps:</p> <ul> <li>Create a new component <code>EditableTable.vue</code></li> <li>Add two props in the EditableTable component (<code>items</code> and <code>fields</code>)</li> <li>Move the existing code but without the data part (<code>items</code> and <code>fields</code>) as this now is required to be passed as a prop by the consumer</li> <li>In <code>app.vue</code>, import the new component and pass it the required props.</li> </ul> <h5 id="editabletable-component" style="position:relative;"><a href="#editabletable-component" aria-label="editabletable component permalink" class="anchor before"><svg aria-hidden="true" focusable="false" height="16" version="1.1" viewBox="0 0 16 16" width="16"><path fill-rule="evenodd" d="M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z"></path></svg></a>EditableTable Component</h5> <pre class="grvsc-container default-dark" data-language="html" data-index="1"><code class="grvsc-code"><span class="grvsc-line"><span class="grvsc-source"><span class="mtk17">&lt;</span><span class="mtk4">template</span><span class="mtk17">&gt;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk17">&lt;</span><span class="mtk4">b-table</span><span class="mtk1"> </span><span class="mtk12">:items</span><span class="mtk1">=</span><span class="mtk8">&quot;tableItems&quot;</span><span class="mtk1"> </span><span class="mtk12">:fields</span><span class="mtk1">=</span><span class="mtk8">&quot;fields&quot;</span><span class="mtk17">&gt;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk17">&lt;</span><span class="mtk4">template</span><span class="mtk1"> </span><span class="mtk12">#cell(name)</span><span class="mtk1">=</span><span class="mtk8">&quot;data&quot;</span><span class="mtk17">&gt;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk17">&lt;</span><span class="mtk4">b-form-input</span><span class="mtk1"> </span><span class="mtk12">v-if</span><span class="mtk1">=</span><span class="mtk8">&quot;tableItems[data.index].isEdit&quot;</span><span class="mtk1"> </span><span class="mtk12">type</span><span class="mtk1">=</span><span class="mtk8">&quot;text&quot;</span><span class="mtk1"> </span><span class="mtk12">v-model</span><span class="mtk1">=</span><span class="mtk8">&quot;tableItems[data.index].name&quot;</span><span class="mtk17">&gt;&lt;/</span><span class="mtk4">b-form-input</span><span class="mtk17">&gt;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk17">&lt;</span><span class="mtk4">span</span><span class="mtk1"> </span><span class="mtk12">v-else</span><span class="mtk17">&gt;</span><span class="mtk1">{{data.value}}</span><span class="mtk17">&lt;/</span><span class="mtk4">span</span><span class="mtk17">&gt;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk17">&lt;/</span><span class="mtk4">template</span><span class="mtk17">&gt;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk17">&lt;</span><span class="mtk4">template</span><span class="mtk1"> </span><span class="mtk12">#cell(department)</span><span class="mtk1">=</span><span class="mtk8">&quot;data&quot;</span><span class="mtk17">&gt;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk17">&lt;</span><span class="mtk4">b-form-select</span><span class="mtk1"> </span><span class="mtk12">v-if</span><span class="mtk1">=</span><span class="mtk8">&quot;tableItems[data.index].isEdit&quot;</span><span class="mtk1"> </span><span class="mtk12">v-model</span><span class="mtk1">=</span><span class="mtk8">&quot;tableItems[data.index].department&quot;</span><span class="mtk1"> </span><span class="mtk12">:options</span><span class="mtk1">=</span><span class="mtk8">&quot;[&#39;Development&#39;, &#39;Marketing&#39;, &#39;HR&#39;, &#39;Accounting&#39;]&quot;</span><span class="mtk17">&gt;&lt;/</span><span class="mtk4">b-form-select</span><span class="mtk17">&gt;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk17">&lt;</span><span class="mtk4">span</span><span class="mtk1"> </span><span class="mtk12">v-else</span><span class="mtk17">&gt;</span><span class="mtk1">{{data.value}}</span><span class="mtk17">&lt;/</span><span class="mtk4">span</span><span class="mtk17">&gt;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk17">&lt;/</span><span class="mtk4">template</span><span class="mtk17">&gt;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk17">&lt;</span><span class="mtk4">template</span><span class="mtk1"> </span><span class="mtk12">#cell(age)</span><span class="mtk1">=</span><span class="mtk8">&quot;data&quot;</span><span class="mtk17">&gt;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk17">&lt;</span><span class="mtk4">b-form-input</span><span class="mtk1"> </span><span class="mtk12">v-if</span><span class="mtk1">=</span><span class="mtk8">&quot;tableItems[data.index].isEdit&quot;</span><span class="mtk1"> </span><span class="mtk12">type</span><span class="mtk1">=</span><span class="mtk8">&quot;number&quot;</span><span class="mtk1"> </span><span class="mtk12">v-model</span><span class="mtk1">=</span><span class="mtk8">&quot;tableItems[data.index].age&quot;</span><span class="mtk17">&gt;&lt;/</span><span class="mtk4">b-form-input</span><span class="mtk17">&gt;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk17">&lt;</span><span class="mtk4">span</span><span class="mtk1"> </span><span class="mtk12">v-else</span><span class="mtk17">&gt;</span><span class="mtk1">{{data.value}}</span><span class="mtk17">&lt;/</span><span class="mtk4">span</span><span class="mtk17">&gt;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk17">&lt;/</span><span class="mtk4">template</span><span class="mtk17">&gt;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk17">&lt;</span><span class="mtk4">template</span><span class="mtk1"> </span><span class="mtk12">#cell(dateOfBirth)</span><span class="mtk1">=</span><span class="mtk8">&quot;data&quot;</span><span class="mtk17">&gt;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk17">&lt;</span><span class="mtk4">b-form-datepicker</span><span class="mtk1"> </span><span class="mtk12">v-if</span><span class="mtk1">=</span><span class="mtk8">&quot;tableItems[data.index].isEdit&quot;</span><span class="mtk1"> </span><span class="mtk12">v-model</span><span class="mtk1">=</span><span class="mtk8">&quot;tableItems[data.index].dateOfBirth&quot;</span><span class="mtk17">&gt;&lt;/</span><span class="mtk4">b-form-datepicker</span><span class="mtk17">&gt;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk17">&lt;</span><span class="mtk4">span</span><span class="mtk1"> </span><span class="mtk12">v-else</span><span class="mtk17">&gt;</span><span class="mtk1">{{data.value}}</span><span class="mtk17">&lt;/</span><span class="mtk4">span</span><span class="mtk17">&gt;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk17">&lt;/</span><span class="mtk4">template</span><span class="mtk17">&gt;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk17">&lt;</span><span class="mtk4">template</span><span class="mtk1"> </span><span class="mtk12">#cell(edit)</span><span class="mtk1">=</span><span class="mtk8">&quot;data&quot;</span><span class="mtk17">&gt;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk17">&lt;</span><span class="mtk4">b-button</span><span class="mtk1"> </span><span class="mtk12">@click</span><span class="mtk1">=</span><span class="mtk8">&quot;editRowHandler(data)&quot;</span><span class="mtk17">&gt;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk17">&lt;</span><span class="mtk4">span</span><span class="mtk1"> </span><span class="mtk12">v-if</span><span class="mtk1">=</span><span class="mtk8">&quot;!tableItems[data.index].isEdit&quot;</span><span class="mtk17">&gt;</span><span class="mtk1">Edit</span><span class="mtk17">&lt;/</span><span class="mtk4">span</span><span class="mtk17">&gt;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk17">&lt;</span><span class="mtk4">span</span><span class="mtk1"> </span><span class="mtk12">v-else</span><span class="mtk17">&gt;</span><span class="mtk1">Done</span><span class="mtk17">&lt;/</span><span class="mtk4">span</span><span class="mtk17">&gt;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk17">&lt;/</span><span class="mtk4">b-button</span><span class="mtk17">&gt;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk17">&lt;/</span><span class="mtk4">template</span><span class="mtk17">&gt;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk17">&lt;/</span><span class="mtk4">b-table</span><span class="mtk17">&gt;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk17">&lt;/</span><span class="mtk4">template</span><span class="mtk17">&gt;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk17">&lt;</span><span class="mtk4">script</span><span class="mtk17">&gt;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk15">export</span><span class="mtk1"> </span><span class="mtk15">default</span><span class="mtk1"> {</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">name:</span><span class="mtk1"> </span><span class="mtk8">&quot;EditableTable&quot;</span><span class="mtk1">,</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">components:</span><span class="mtk1"> {},</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">props:</span><span class="mtk1"> {</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">items:</span><span class="mtk1"> </span><span class="mtk10">Array</span><span class="mtk1">,</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">fields:</span><span class="mtk1"> </span><span class="mtk10">Array</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> },</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk11">data</span><span class="mtk1">() {</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk15">return</span><span class="mtk1"> {</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">tableItems:</span><span class="mtk1"> </span><span class="mtk4">this</span><span class="mtk1">.</span><span class="mtk12">items</span><span class="mtk1">.</span><span class="mtk11">map</span><span class="mtk1">(</span><span class="mtk12">item</span><span class="mtk1"> </span><span class="mtk4">=&gt;</span><span class="mtk1"> ({...</span><span class="mtk12">item</span><span class="mtk1">, </span><span class="mtk12">isEdit:</span><span class="mtk1"> </span><span class="mtk4">false</span><span class="mtk1">}))</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> }</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> },</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">methods:</span><span class="mtk1"> {</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk11">editRowHandler</span><span class="mtk1">(</span><span class="mtk12">data</span><span class="mtk1">) {</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk4">this</span><span class="mtk1">.</span><span class="mtk12">tableItems</span><span class="mtk1">[</span><span class="mtk12">data</span><span class="mtk1">.</span><span class="mtk12">index</span><span class="mtk1">].</span><span class="mtk12">isEdit</span><span class="mtk1"> = !</span><span class="mtk4">this</span><span class="mtk1">.</span><span class="mtk12">tableItems</span><span class="mtk1">[</span><span class="mtk12">data</span><span class="mtk1">.</span><span class="mtk12">index</span><span class="mtk1">].</span><span class="mtk12">isEdit</span><span class="mtk1">;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> }</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> }</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1">};</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk17">&lt;/</span><span class="mtk4">script</span><span class="mtk17">&gt;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk17">&lt;</span><span class="mtk4">style</span><span class="mtk17">&gt;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk17">&lt;/</span><span class="mtk4">style</span><span class="mtk17">&gt;</span></span></span></code></pre> <p>Notice we are not using <code>items</code> anymore, instead, we created a new data called <code>tableItems</code>. If you recall from the <a href="https://muhimasri.com/blogs/create-an-editable-dynamic-table-with-bootstrap-vue/">previous part</a>, we had to re-generate the <code>items</code> model to include a new property <code>isEdit</code> for every row. This will determine whether or not a row is in edit mode. In the above code, we are doing the same thing except we created a new data array as it’s considered a bad practice to modify the prop directly. Props should only be modified by the consumer.</p> <h5 id="main-app-component" style="position:relative;"><a href="#main-app-component" aria-label="main app component permalink" class="anchor before"><svg aria-hidden="true" focusable="false" height="16" version="1.1" viewBox="0 0 16 16" width="16"><path fill-rule="evenodd" d="M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z"></path></svg></a>Main App Component</h5> <pre class="grvsc-container default-dark" data-language="html" data-index="2"><code class="grvsc-code"><span class="grvsc-line"><span class="grvsc-source"><span class="mtk17">&lt;</span><span class="mtk4">template</span><span class="mtk17">&gt;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk17">&lt;</span><span class="mtk4">div</span><span class="mtk1"> </span><span class="mtk12">id</span><span class="mtk1">=</span><span class="mtk8">&quot;app&quot;</span><span class="mtk17">&gt;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk17">&lt;</span><span class="mtk4">EditableTable</span><span class="mtk1"> </span><span class="mtk12">:items</span><span class="mtk1">=</span><span class="mtk8">&quot;items&quot;</span><span class="mtk1"> </span><span class="mtk12">:fields</span><span class="mtk1">=</span><span class="mtk8">&quot;fields&quot;</span><span class="mtk17">&gt;&lt;/</span><span class="mtk4">EditableTable</span><span class="mtk17">&gt;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk17">&lt;/</span><span class="mtk4">div</span><span class="mtk17">&gt;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk17">&lt;/</span><span class="mtk4">template</span><span class="mtk17">&gt;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk17">&lt;</span><span class="mtk4">script</span><span class="mtk17">&gt;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk15">import</span><span class="mtk1"> </span><span class="mtk12">EditableTable</span><span class="mtk1"> </span><span class="mtk15">from</span><span class="mtk1"> </span><span class="mtk8">&#39;./components/EditableTable.vue&#39;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk15">export</span><span class="mtk1"> </span><span class="mtk15">default</span><span class="mtk1"> {</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">name:</span><span class="mtk1"> </span><span class="mtk8">&quot;App&quot;</span><span class="mtk1">,</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">components:</span><span class="mtk1"> {</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">EditableTable</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> },</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk11">data</span><span class="mtk1">() {</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk15">return</span><span class="mtk1"> {</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">fields:</span><span class="mtk1"> [</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> { </span><span class="mtk12">key:</span><span class="mtk1"> </span><span class="mtk8">&quot;name&quot;</span><span class="mtk1">, </span><span class="mtk12">label:</span><span class="mtk1"> </span><span class="mtk8">&quot;Name&quot;</span><span class="mtk1"> },</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> { </span><span class="mtk12">key:</span><span class="mtk1"> </span><span class="mtk8">&quot;department&quot;</span><span class="mtk1">, </span><span class="mtk12">label:</span><span class="mtk1"> </span><span class="mtk8">&quot;Department&quot;</span><span class="mtk1"> },</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> { </span><span class="mtk12">key:</span><span class="mtk1"> </span><span class="mtk8">&quot;age&quot;</span><span class="mtk1">, </span><span class="mtk12">label:</span><span class="mtk1"> </span><span class="mtk8">&quot;Age&quot;</span><span class="mtk1"> },</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> { </span><span class="mtk12">key:</span><span class="mtk1"> </span><span class="mtk8">&quot;dateOfBirth&quot;</span><span class="mtk1">, </span><span class="mtk12">label:</span><span class="mtk1"> </span><span class="mtk8">&quot;Date Of Birth&quot;</span><span class="mtk1"> },</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> { </span><span class="mtk12">key:</span><span class="mtk1"> </span><span class="mtk8">&quot;edit&quot;</span><span class="mtk1">, </span><span class="mtk12">label:</span><span class="mtk1"> </span><span class="mtk8">&quot;&quot;</span><span class="mtk1"> }</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> ],</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">items:</span><span class="mtk1"> [</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> { </span><span class="mtk12">age:</span><span class="mtk1"> </span><span class="mtk7">40</span><span class="mtk1">, </span><span class="mtk12">name:</span><span class="mtk1"> </span><span class="mtk8">&#39;Dickerson&#39;</span><span class="mtk1">, </span><span class="mtk12">department:</span><span class="mtk1"> </span><span class="mtk8">&#39;Development&#39;</span><span class="mtk1">, </span><span class="mtk12">dateOfBirth:</span><span class="mtk1"> </span><span class="mtk8">&#39;1984-05-20&#39;</span><span class="mtk1"> },</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> { </span><span class="mtk12">age:</span><span class="mtk1"> </span><span class="mtk7">21</span><span class="mtk1">, </span><span class="mtk12">name:</span><span class="mtk1"> </span><span class="mtk8">&#39;Larsen&#39;</span><span class="mtk1">, </span><span class="mtk12">department:</span><span class="mtk1"> </span><span class="mtk8">&#39;Marketing&#39;</span><span class="mtk1">, </span><span class="mtk12">dateOfBirth:</span><span class="mtk1"> </span><span class="mtk8">&#39;1984-05-20&#39;</span><span class="mtk1"> },</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> { </span><span class="mtk12">age:</span><span class="mtk1"> </span><span class="mtk7">89</span><span class="mtk1">, </span><span class="mtk12">name:</span><span class="mtk1"> </span><span class="mtk8">&#39;Geneva&#39;</span><span class="mtk1">, </span><span class="mtk12">department:</span><span class="mtk1"> </span><span class="mtk8">&#39;HR&#39;</span><span class="mtk1">, </span><span class="mtk12">dateOfBirth:</span><span class="mtk1"> </span><span class="mtk8">&#39;1984-05-20&#39;</span><span class="mtk1"> },</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> { </span><span class="mtk12">age:</span><span class="mtk1"> </span><span class="mtk7">38</span><span class="mtk1">, </span><span class="mtk12">name:</span><span class="mtk1"> </span><span class="mtk8">&#39;Jami&#39;</span><span class="mtk1">, </span><span class="mtk12">department:</span><span class="mtk1"> </span><span class="mtk8">&#39;Accounting&#39;</span><span class="mtk1">, </span><span class="mtk12">dateOfBirth:</span><span class="mtk1"> </span><span class="mtk8">&#39;1984-05-20&#39;</span><span class="mtk1"> }</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> ]</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> };</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> }</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1">};</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk17">&lt;/</span><span class="mtk4">script</span><span class="mtk17">&gt;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk17">&lt;</span><span class="mtk4">style</span><span class="mtk17">&gt;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk6">#app</span><span class="mtk1"> {</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">text-align</span><span class="mtk1">: </span><span class="mtk8">center</span><span class="mtk1">;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">margin</span><span class="mtk1">: </span><span class="mtk7">60px</span><span class="mtk1">;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1">}</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk6">thead</span><span class="mtk1">, </span><span class="mtk6">tbody</span><span class="mtk1">, </span><span class="mtk6">tfoot</span><span class="mtk1">, </span><span class="mtk6">tr</span><span class="mtk1">, </span><span class="mtk6">td</span><span class="mtk1">, </span><span class="mtk6">th</span><span class="mtk1"> {</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">text-align</span><span class="mtk1">: </span><span class="mtk8">left</span><span class="mtk1">;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">width</span><span class="mtk1">: </span><span class="mtk7">100px</span><span class="mtk1">;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">vertical-align</span><span class="mtk1">: </span><span class="mtk8">middle</span><span class="mtk1">;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1">}</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk6">pre</span><span class="mtk1"> {</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">text-align</span><span class="mtk1">: </span><span class="mtk8">left</span><span class="mtk1">;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">color</span><span class="mtk1">: </span><span class="mtk8">#d63384</span><span class="mtk1"> </span><span class="mtk4">!important</span><span class="mtk1">;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1">}</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk17">&lt;/</span><span class="mtk4">style</span><span class="mtk17">&gt;</span></span></span></code></pre> <h2 id="dynamic-schema" style="position:relative;"><a href="#dynamic-schema" aria-label="dynamic schema permalink" class="anchor before"><svg aria-hidden="true" focusable="false" height="16" version="1.1" viewBox="0 0 16 16" width="16"><path fill-rule="evenodd" d="M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z"></path></svg></a>Dynamic schema</h2> <p>Encapsulation was a good step forward towards sharing the code and reducing redundancies. But with great power comes great responsibility! What if we need different columns for different datasets? What’s the point of creating a reusable table component if we can only have one schema? We have to keep the consumer happy and make sure the component is flexible enough to meet different scenarios.</p> <p>Implementing a dynamic schema is a bit tricky but it will end up with less code and a more robust and scalable component. Here are the steps required to achieve this objective:</p> <ul> <li>Add a new property to the <code>fields</code> object to determine the type of the input field. For example, the “Name” field will be <code>{ key: "name", label: "Name", type: "text"}</code> and the “Date of Birth” will be <code>{ key: "dateOfBirth", label: "Date Of Birth", type: "date" }</code></li> <li>Instead of creating multiple slots, we only need one with a <code>for</code> loop and dynamic slots. Vue allows dynamic slots by using the square bracket as well as string interpolation to attach the key of the current field. E.g. <code>#[`cell(${field.key})`]</code></li> <li>Within the slot, we can add a condition to check the type and show the proper input field element.</li> <li>Finally, we need a way to pass the options to the select element. One way to make this work is by adding another property to the field object with the options we need. E.g. <code>options: ['option1', 'option2', 'option3'...]</code></li> </ul> <h5 id="editabletable-component-1" style="position:relative;"><a href="#editabletable-component-1" aria-label="editabletable component 1 permalink" class="anchor before"><svg aria-hidden="true" focusable="false" height="16" version="1.1" viewBox="0 0 16 16" width="16"><path fill-rule="evenodd" d="M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z"></path></svg></a>EditableTable component</h5> <pre class="grvsc-container default-dark" data-language="html" data-index="3"><code class="grvsc-code"><span class="grvsc-line"><span class="grvsc-source"><span class="mtk17">&lt;</span><span class="mtk4">template</span><span class="mtk17">&gt;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk17">&lt;</span><span class="mtk4">b-table</span><span class="mtk1"> </span><span class="mtk12">:items</span><span class="mtk1">=</span><span class="mtk8">&quot;tableItems&quot;</span><span class="mtk1"> </span><span class="mtk12">:fields</span><span class="mtk1">=</span><span class="mtk8">&quot;fields&quot;</span><span class="mtk17">&gt;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk17">&lt;</span><span class="mtk4">template</span><span class="mtk1"> </span><span class="mtk12">v-for</span><span class="mtk1">=</span><span class="mtk8">&quot;(field, index) in fields&quot;</span><span class="mtk1"> </span><span class="mtk12">#[`cell(${field.key})`]</span><span class="mtk1">=</span><span class="mtk8">&quot;data&quot;</span><span class="mtk17">&gt;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk17">&lt;</span><span class="mtk4">b-form-datepicker</span><span class="mtk1"> </span><span class="mtk12">v-if</span><span class="mtk1">=</span><span class="mtk8">&quot;field.type === &#39;date&#39; &amp;&amp; tableItems[data.index].isEdit&quot;</span><span class="mtk1"> </span><span class="mtk12">:key</span><span class="mtk1">=</span><span class="mtk8">&quot;index&quot;</span><span class="mtk1"> </span><span class="mtk12">:type</span><span class="mtk1">=</span><span class="mtk8">&quot;field.type&quot;</span><span class="mtk1"> </span><span class="mtk12">v-model</span><span class="mtk1">=</span><span class="mtk8">&quot;tableItems[data.index][field.key]&quot;</span><span class="mtk17">&gt;&lt;/</span><span class="mtk4">b-form-datepicker</span><span class="mtk17">&gt;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk17">&lt;</span><span class="mtk4">b-form-select</span><span class="mtk1"> </span><span class="mtk12">v-else-if</span><span class="mtk1">=</span><span class="mtk8">&quot;field.type === &#39;select&#39; &amp;&amp; tableItems[data.index].isEdit&quot;</span><span class="mtk1"> </span><span class="mtk12">:key</span><span class="mtk1">=</span><span class="mtk8">&quot;index&quot;</span><span class="mtk1"> </span><span class="mtk12">v-model</span><span class="mtk1">=</span><span class="mtk8">&quot;tableItems[data.index][field.key]&quot;</span><span class="mtk1"> </span><span class="mtk12">:options</span><span class="mtk1">=</span><span class="mtk8">&quot;field.options&quot;</span><span class="mtk17">&gt;&lt;/</span><span class="mtk4">b-form-select</span><span class="mtk17">&gt;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk17">&lt;</span><span class="mtk4">b-button</span><span class="mtk1"> </span><span class="mtk12">:key</span><span class="mtk1">=</span><span class="mtk8">&quot;index&quot;</span><span class="mtk1"> </span><span class="mtk12">v-else-if</span><span class="mtk1">=</span><span class="mtk8">&quot;field.type === &#39;edit&#39;&quot;</span><span class="mtk1"> </span><span class="mtk12">@click</span><span class="mtk1">=</span><span class="mtk8">&quot;editRowHandler(data)&quot;</span><span class="mtk17">&gt;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk17">&lt;</span><span class="mtk4">span</span><span class="mtk1"> </span><span class="mtk12">v-if</span><span class="mtk1">=</span><span class="mtk8">&quot;!tableItems[data.index].isEdit&quot;</span><span class="mtk17">&gt;</span><span class="mtk1">Edit</span><span class="mtk17">&lt;/</span><span class="mtk4">span</span><span class="mtk17">&gt;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk17">&lt;</span><span class="mtk4">span</span><span class="mtk1"> </span><span class="mtk12">v-else</span><span class="mtk17">&gt;</span><span class="mtk1">Done</span><span class="mtk17">&lt;/</span><span class="mtk4">span</span><span class="mtk17">&gt;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk17">&lt;/</span><span class="mtk4">b-button</span><span class="mtk17">&gt;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk17">&lt;</span><span class="mtk4">b-form-input</span><span class="mtk1"> </span><span class="mtk12">v-else-if</span><span class="mtk1">=</span><span class="mtk8">&quot;field.type &amp;&amp; tableItems[data.index].isEdit&quot;</span><span class="mtk1"> </span><span class="mtk12">:key</span><span class="mtk1">=</span><span class="mtk8">&quot;index&quot;</span><span class="mtk1"> </span><span class="mtk12">:type</span><span class="mtk1">=</span><span class="mtk8">&quot;field.type&quot;</span><span class="mtk1"> </span><span class="mtk12">v-model</span><span class="mtk1">=</span><span class="mtk8">&quot;tableItems[data.index][field.key]&quot;</span><span class="mtk17">&gt;&lt;/</span><span class="mtk4">b-form-input</span><span class="mtk17">&gt;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk17">&lt;</span><span class="mtk4">span</span><span class="mtk1"> </span><span class="mtk12">:key</span><span class="mtk1">=</span><span class="mtk8">&quot;index&quot;</span><span class="mtk1"> </span><span class="mtk12">v-else</span><span class="mtk17">&gt;</span><span class="mtk1">{{data.value}}</span><span class="mtk17">&lt;/</span><span class="mtk4">span</span><span class="mtk17">&gt;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk17">&lt;/</span><span class="mtk4">template</span><span class="mtk17">&gt;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk17">&lt;/</span><span class="mtk4">b-table</span><span class="mtk17">&gt;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk17">&lt;/</span><span class="mtk4">template</span><span class="mtk17">&gt;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk17">&lt;</span><span class="mtk4">script</span><span class="mtk17">&gt;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk15">export</span><span class="mtk1"> </span><span class="mtk15">default</span><span class="mtk1"> {</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">name:</span><span class="mtk1"> </span><span class="mtk8">&quot;EditableTable&quot;</span><span class="mtk1">,</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">components:</span><span class="mtk1"> {},</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">props:</span><span class="mtk1"> {</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">items:</span><span class="mtk1"> </span><span class="mtk10">Array</span><span class="mtk1">,</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">fields:</span><span class="mtk1"> </span><span class="mtk10">Array</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> },</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk11">data</span><span class="mtk1">() {</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk15">return</span><span class="mtk1"> {</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">tableItems:</span><span class="mtk1"> </span><span class="mtk4">this</span><span class="mtk1">.</span><span class="mtk12">items</span><span class="mtk1">.</span><span class="mtk11">map</span><span class="mtk1">(</span><span class="mtk12">item</span><span class="mtk1"> </span><span class="mtk4">=&gt;</span><span class="mtk1"> ({...</span><span class="mtk12">item</span><span class="mtk1">, </span><span class="mtk12">isEdit:</span><span class="mtk1"> </span><span class="mtk4">false</span><span class="mtk1">}))</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> }</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> },</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">methods:</span><span class="mtk1"> {</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk11">editRowHandler</span><span class="mtk1">(</span><span class="mtk12">data</span><span class="mtk1">) {</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk4">this</span><span class="mtk1">.</span><span class="mtk12">tableItems</span><span class="mtk1">[</span><span class="mtk12">data</span><span class="mtk1">.</span><span class="mtk12">index</span><span class="mtk1">].</span><span class="mtk12">isEdit</span><span class="mtk1"> = !</span><span class="mtk4">this</span><span class="mtk1">.</span><span class="mtk12">tableItems</span><span class="mtk1">[</span><span class="mtk12">data</span><span class="mtk1">.</span><span class="mtk12">index</span><span class="mtk1">].</span><span class="mtk12">isEdit</span><span class="mtk1">;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> }</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> }</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1">};</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk17">&lt;/</span><span class="mtk4">script</span><span class="mtk17">&gt;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk17">&lt;</span><span class="mtk4">style</span><span class="mtk17">&gt;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk17">&lt;/</span><span class="mtk4">style</span><span class="mtk17">&gt;</span></span></span></code></pre> <h5 id="main-app-component-1" style="position:relative;"><a href="#main-app-component-1" aria-label="main app component 1 permalink" class="anchor before"><svg aria-hidden="true" focusable="false" height="16" version="1.1" viewBox="0 0 16 16" width="16"><path fill-rule="evenodd" d="M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z"></path></svg></a>Main App component</h5> <pre class="grvsc-container default-dark" data-language="html" data-index="4"><code class="grvsc-code"><span class="grvsc-line"><span class="grvsc-source"><span class="mtk17">&lt;</span><span class="mtk4">template</span><span class="mtk17">&gt;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk17">&lt;</span><span class="mtk4">div</span><span class="mtk1"> </span><span class="mtk12">id</span><span class="mtk1">=</span><span class="mtk8">&quot;app&quot;</span><span class="mtk17">&gt;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk17">&lt;</span><span class="mtk4">EditableTable</span><span class="mtk1"> </span><span class="mtk12">:items</span><span class="mtk1">=</span><span class="mtk8">&quot;items&quot;</span><span class="mtk1"> </span><span class="mtk12">:fields</span><span class="mtk1">=</span><span class="mtk8">&quot;fields&quot;</span><span class="mtk17">&gt;&lt;/</span><span class="mtk4">EditableTable</span><span class="mtk17">&gt;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk17">&lt;/</span><span class="mtk4">div</span><span class="mtk17">&gt;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk17">&lt;/</span><span class="mtk4">template</span><span class="mtk17">&gt;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk17">&lt;</span><span class="mtk4">script</span><span class="mtk17">&gt;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk15">import</span><span class="mtk1"> </span><span class="mtk12">EditableTable</span><span class="mtk1"> </span><span class="mtk15">from</span><span class="mtk1"> </span><span class="mtk8">&#39;./components/EditableTable.vue&#39;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk15">export</span><span class="mtk1"> </span><span class="mtk15">default</span><span class="mtk1"> {</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">name:</span><span class="mtk1"> </span><span class="mtk8">&quot;App&quot;</span><span class="mtk1">,</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">components:</span><span class="mtk1"> {</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">EditableTable</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> },</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk11">data</span><span class="mtk1">() {</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk15">return</span><span class="mtk1"> {</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">fields:</span><span class="mtk1"> [</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> { </span><span class="mtk12">key:</span><span class="mtk1"> </span><span class="mtk8">&quot;name&quot;</span><span class="mtk1">, </span><span class="mtk12">label:</span><span class="mtk1"> </span><span class="mtk8">&quot;Name&quot;</span><span class="mtk1">, </span><span class="mtk12">type:</span><span class="mtk1"> </span><span class="mtk8">&#39;text&#39;</span><span class="mtk1"> },</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> { </span><span class="mtk12">key:</span><span class="mtk1"> </span><span class="mtk8">&quot;department&quot;</span><span class="mtk1">, </span><span class="mtk12">label:</span><span class="mtk1"> </span><span class="mtk8">&quot;Department&quot;</span><span class="mtk1">, </span><span class="mtk12">type:</span><span class="mtk1"> </span><span class="mtk8">&#39;select&#39;</span><span class="mtk1">, </span><span class="mtk12">options:</span><span class="mtk1"> [</span><span class="mtk8">&#39;Development&#39;</span><span class="mtk1">, </span><span class="mtk8">&#39;Marketing&#39;</span><span class="mtk1">, </span><span class="mtk8">&#39;HR&#39;</span><span class="mtk1">, </span><span class="mtk8">&#39;Accounting&#39;</span><span class="mtk1">] },</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> { </span><span class="mtk12">key:</span><span class="mtk1"> </span><span class="mtk8">&quot;age&quot;</span><span class="mtk1">, </span><span class="mtk12">label:</span><span class="mtk1"> </span><span class="mtk8">&quot;Age&quot;</span><span class="mtk1">, </span><span class="mtk12">type:</span><span class="mtk1"> </span><span class="mtk8">&#39;number&#39;</span><span class="mtk1"> },</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> { </span><span class="mtk12">key:</span><span class="mtk1"> </span><span class="mtk8">&quot;dateOfBirth&quot;</span><span class="mtk1">, </span><span class="mtk12">label:</span><span class="mtk1"> </span><span class="mtk8">&quot;Date Of Birth&quot;</span><span class="mtk1">, </span><span class="mtk12">type:</span><span class="mtk1"> </span><span class="mtk8">&#39;date&#39;</span><span class="mtk1"> },</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> { </span><span class="mtk12">key:</span><span class="mtk1"> </span><span class="mtk8">&quot;edit&quot;</span><span class="mtk1">, </span><span class="mtk12">label:</span><span class="mtk1"> </span><span class="mtk8">&quot;&quot;</span><span class="mtk1">, </span><span class="mtk12">type:</span><span class="mtk1"> </span><span class="mtk8">&quot;edit&quot;</span><span class="mtk1"> }</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> ],</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">items:</span><span class="mtk1"> [</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> { </span><span class="mtk12">age:</span><span class="mtk1"> </span><span class="mtk7">40</span><span class="mtk1">, </span><span class="mtk12">name:</span><span class="mtk1"> </span><span class="mtk8">&#39;Dickerson&#39;</span><span class="mtk1">, </span><span class="mtk12">department:</span><span class="mtk1"> </span><span class="mtk8">&#39;Development&#39;</span><span class="mtk1">, </span><span class="mtk12">dateOfBirth:</span><span class="mtk1"> </span><span class="mtk8">&#39;1984-05-20&#39;</span><span class="mtk1"> },</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> { </span><span class="mtk12">age:</span><span class="mtk1"> </span><span class="mtk7">21</span><span class="mtk1">, </span><span class="mtk12">name:</span><span class="mtk1"> </span><span class="mtk8">&#39;Larsen&#39;</span><span class="mtk1">, </span><span class="mtk12">department:</span><span class="mtk1"> </span><span class="mtk8">&#39;Marketing&#39;</span><span class="mtk1">, </span><span class="mtk12">dateOfBirth:</span><span class="mtk1"> </span><span class="mtk8">&#39;1984-05-20&#39;</span><span class="mtk1"> },</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> { </span><span class="mtk12">age:</span><span class="mtk1"> </span><span class="mtk7">89</span><span class="mtk1">, </span><span class="mtk12">name:</span><span class="mtk1"> </span><span class="mtk8">&#39;Geneva&#39;</span><span class="mtk1">, </span><span class="mtk12">department:</span><span class="mtk1"> </span><span class="mtk8">&#39;HR&#39;</span><span class="mtk1">, </span><span class="mtk12">dateOfBirth:</span><span class="mtk1"> </span><span class="mtk8">&#39;1984-05-20&#39;</span><span class="mtk1"> },</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> { </span><span class="mtk12">age:</span><span class="mtk1"> </span><span class="mtk7">38</span><span class="mtk1">, </span><span class="mtk12">name:</span><span class="mtk1"> </span><span class="mtk8">&#39;Jami&#39;</span><span class="mtk1">, </span><span class="mtk12">department:</span><span class="mtk1"> </span><span class="mtk8">&#39;Accounting&#39;</span><span class="mtk1">, </span><span class="mtk12">dateOfBirth:</span><span class="mtk1"> </span><span class="mtk8">&#39;1984-05-20&#39;</span><span class="mtk1"> }</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> ]</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> };</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> }</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1">};</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk17">&lt;/</span><span class="mtk4">script</span><span class="mtk17">&gt;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk17">&lt;</span><span class="mtk4">style</span><span class="mtk17">&gt;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk6">#app</span><span class="mtk1"> {</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">text-align</span><span class="mtk1">: </span><span class="mtk8">center</span><span class="mtk1">;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">margin</span><span class="mtk1">: </span><span class="mtk7">60px</span><span class="mtk1">;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1">}</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk6">thead</span><span class="mtk1">, </span><span class="mtk6">tbody</span><span class="mtk1">, </span><span class="mtk6">tfoot</span><span class="mtk1">, </span><span class="mtk6">tr</span><span class="mtk1">, </span><span class="mtk6">td</span><span class="mtk1">, </span><span class="mtk6">th</span><span class="mtk1"> {</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">text-align</span><span class="mtk1">: </span><span class="mtk8">left</span><span class="mtk1">;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">width</span><span class="mtk1">: </span><span class="mtk7">100px</span><span class="mtk1">;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">vertical-align</span><span class="mtk1">: </span><span class="mtk8">middle</span><span class="mtk1">;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1">}</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk6">pre</span><span class="mtk1"> {</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">text-align</span><span class="mtk1">: </span><span class="mtk8">left</span><span class="mtk1">;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">color</span><span class="mtk1">: </span><span class="mtk8">#d63384</span><span class="mtk1"> </span><span class="mtk4">!important</span><span class="mtk1">;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1">}</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk17">&lt;/</span><span class="mtk4">style</span><span class="mtk17">&gt;</span></span></span></code></pre> <h2 id="two-way-binding" style="position:relative;"><a href="#two-way-binding" aria-label="two way binding permalink" class="anchor before"><svg aria-hidden="true" focusable="false" height="16" version="1.1" viewBox="0 0 16 16" width="16"><path fill-rule="evenodd" d="M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z"></path></svg></a>Two-way binding</h2> <p>Since we decoupled the table code and are using a new data array (<code>tableItems</code>), the consumer can’t see the updated values anymore. Luckily, Vue provides us with the option to use a <code>v-model</code> in any custom component even if it’s not solely an input element.</p> <p>To enable <code>v-model</code> in the custom table component, Vue requires us to provide a <code>value</code> as a prop and emit an <code>input</code> event with the updated value. In our case, we’ll replace <code>items</code> prop with <code>value</code>:</p> <pre class="grvsc-container default-dark" data-language="javascript" data-index="5"><code class="grvsc-code"><span class="grvsc-line"><span class="grvsc-source"><span class="mtk1">props: {</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> value: </span><span class="mtk10">Array</span><span class="mtk1">,</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> fields: </span><span class="mtk10">Array</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1">}</span></span></span></code></pre> <p>To update the value, we’ll create an <code>inputHandler</code> function that will update <code>tableItems</code> and emit the latest changes:</p> <pre class="grvsc-container default-dark" data-language="javascript" data-index="6"><code class="grvsc-code"><span class="grvsc-line"><span class="grvsc-source"><span class="mtk11">inputHandler</span><span class="mtk1">(</span><span class="mtk12">value</span><span class="mtk1">, </span><span class="mtk12">index</span><span class="mtk1">, </span><span class="mtk12">key</span><span class="mtk1">) {</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk4">this</span><span class="mtk1">.</span><span class="mtk12">tableItems</span><span class="mtk1">[</span><span class="mtk12">index</span><span class="mtk1">][</span><span class="mtk12">key</span><span class="mtk1">] = </span><span class="mtk12">value</span><span class="mtk1">;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk4">this</span><span class="mtk1">.</span><span class="mtk11">$set</span><span class="mtk1">(</span><span class="mtk4">this</span><span class="mtk1">.</span><span class="mtk12">tableItems</span><span class="mtk1">, </span><span class="mtk12">index</span><span class="mtk1">, </span><span class="mtk4">this</span><span class="mtk1">.</span><span class="mtk12">tableItems</span><span class="mtk1">[</span><span class="mtk12">index</span><span class="mtk1">]);</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk4">this</span><span class="mtk1">.</span><span class="mtk11">$emit</span><span class="mtk1">(</span><span class="mtk8">&quot;input&quot;</span><span class="mtk1">, </span><span class="mtk4">this</span><span class="mtk1">.</span><span class="mtk12">tableItems</span><span class="mtk1">);</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1">}</span></span></span></code></pre> <p>We don’t need the <code>v-model</code> in the input element anymore, we’ll add the following code instead:</p> <pre class="grvsc-container default-dark" data-language="" data-index="7"><code class="grvsc-code"><span class="grvsc-line"><span class="grvsc-source">:value=&quot;tableItems[data.index][field.key]&quot; @blur=&quot;(e) =&gt; inputHandler(e.target.value, data.index, field.key)&quot;</span></span></code></pre> <p><em>Vue 3.x introduced a breaking change when using v-model with custom components. Please refer to the <a href="https://v3.vuejs.org/guide/migration/v-model.html">official Vue documentation</a> to learn more.</em></p> <p>Lastly, in the main App component, <code>:items="items"</code> will become <code>v-model="items"</code></p> <h5 id="editabletable-component-2" style="position:relative;"><a href="#editabletable-component-2" aria-label="editabletable component 2 permalink" class="anchor before"><svg aria-hidden="true" focusable="false" height="16" version="1.1" viewBox="0 0 16 16" width="16"><path fill-rule="evenodd" d="M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z"></path></svg></a>EditableTable component</h5> <pre class="grvsc-container default-dark" data-language="html" data-index="8"><code class="grvsc-code"><span class="grvsc-line"><span class="grvsc-source"><span class="mtk17">&lt;</span><span class="mtk4">template</span><span class="mtk17">&gt;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk17">&lt;</span><span class="mtk4">b-table</span><span class="mtk1"> </span><span class="mtk12">:items</span><span class="mtk1">=</span><span class="mtk8">&quot;tableItems&quot;</span><span class="mtk1"> </span><span class="mtk12">:fields</span><span class="mtk1">=</span><span class="mtk8">&quot;fields&quot;</span><span class="mtk17">&gt;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk17">&lt;</span><span class="mtk4">template</span><span class="mtk1"> </span><span class="mtk12">v-for</span><span class="mtk1">=</span><span class="mtk8">&quot;(field, index) in fields&quot;</span><span class="mtk1"> </span><span class="mtk12">#[`cell(${field.key})`]</span><span class="mtk1">=</span><span class="mtk8">&quot;data&quot;</span><span class="mtk17">&gt;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk17">&lt;</span><span class="mtk4">b-form-datepicker</span><span class="mtk1"> </span><span class="mtk12">v-if</span><span class="mtk1">=</span><span class="mtk8">&quot;field.type === &#39;date&#39; &amp;&amp; tableItems[data.index].isEdit&quot;</span><span class="mtk1"> </span><span class="mtk12">:key</span><span class="mtk1">=</span><span class="mtk8">&quot;index&quot;</span><span class="mtk1"> </span><span class="mtk12">:type</span><span class="mtk1">=</span><span class="mtk8">&quot;field.type&quot;</span><span class="mtk1"> </span><span class="mtk12">:value</span><span class="mtk1">=</span><span class="mtk8">&quot;tableItems[data.index][field.key]&quot;</span><span class="mtk1"> </span><span class="mtk12">@input</span><span class="mtk1">=</span><span class="mtk8">&quot;(value) =&gt; inputHandler(value, data.index, field.key)&quot;</span><span class="mtk17">&gt;&lt;/</span><span class="mtk4">b-form-datepicker</span><span class="mtk17">&gt;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk17">&lt;</span><span class="mtk4">b-form-select</span><span class="mtk1"> </span><span class="mtk12">v-else-if</span><span class="mtk1">=</span><span class="mtk8">&quot;field.type === &#39;select&#39; &amp;&amp; tableItems[data.index].isEdit&quot;</span><span class="mtk1"> </span><span class="mtk12">:key</span><span class="mtk1">=</span><span class="mtk8">&quot;index&quot;</span><span class="mtk1"> </span><span class="mtk12">:value</span><span class="mtk1">=</span><span class="mtk8">&quot;tableItems[data.index][field.key]&quot;</span><span class="mtk1"> </span><span class="mtk12">@input</span><span class="mtk1">=</span><span class="mtk8">&quot;(value) =&gt; inputHandler(value, data.index, field.key)&quot;</span><span class="mtk1"> </span><span class="mtk12">:options</span><span class="mtk1">=</span><span class="mtk8">&quot;field.options&quot;</span><span class="mtk17">&gt;&lt;/</span><span class="mtk4">b-form-select</span><span class="mtk17">&gt;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk17">&lt;</span><span class="mtk4">b-button</span><span class="mtk1"> </span><span class="mtk12">:key</span><span class="mtk1">=</span><span class="mtk8">&quot;index&quot;</span><span class="mtk1"> </span><span class="mtk12">v-else-if</span><span class="mtk1">=</span><span class="mtk8">&quot;field.type === &#39;edit&#39;&quot;</span><span class="mtk1"> </span><span class="mtk12">@click</span><span class="mtk1">=</span><span class="mtk8">&quot;editRowHandler(data)&quot;</span><span class="mtk17">&gt;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk17">&lt;</span><span class="mtk4">span</span><span class="mtk1"> </span><span class="mtk12">v-if</span><span class="mtk1">=</span><span class="mtk8">&quot;!tableItems[data.index].isEdit&quot;</span><span class="mtk17">&gt;</span><span class="mtk1">Edit</span><span class="mtk17">&lt;/</span><span class="mtk4">span</span><span class="mtk17">&gt;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk17">&lt;</span><span class="mtk4">span</span><span class="mtk1"> </span><span class="mtk12">v-else</span><span class="mtk17">&gt;</span><span class="mtk1">Done</span><span class="mtk17">&lt;/</span><span class="mtk4">span</span><span class="mtk17">&gt;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk17">&lt;/</span><span class="mtk4">b-button</span><span class="mtk17">&gt;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk17">&lt;</span><span class="mtk4">b-form-input</span><span class="mtk1"> </span><span class="mtk12">v-else-if</span><span class="mtk1">=</span><span class="mtk8">&quot;field.type &amp;&amp; tableItems[data.index].isEdit&quot;</span><span class="mtk1"> </span><span class="mtk12">:key</span><span class="mtk1">=</span><span class="mtk8">&quot;index&quot;</span><span class="mtk1"> </span><span class="mtk12">:type</span><span class="mtk1">=</span><span class="mtk8">&quot;field.type&quot;</span><span class="mtk1"> </span><span class="mtk12">:value</span><span class="mtk1">=</span><span class="mtk8">&quot;tableItems[data.index][field.key]&quot;</span><span class="mtk1"> </span><span class="mtk12">@blur</span><span class="mtk1">=</span><span class="mtk8">&quot;(e) =&gt; inputHandler(e.target.value, data.index, field.key)&quot;</span><span class="mtk17">&gt;&lt;/</span><span class="mtk4">b-form-input</span><span class="mtk17">&gt;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk17">&lt;</span><span class="mtk4">span</span><span class="mtk1"> </span><span class="mtk12">:key</span><span class="mtk1">=</span><span class="mtk8">&quot;index&quot;</span><span class="mtk1"> </span><span class="mtk12">v-else</span><span class="mtk17">&gt;</span><span class="mtk1">{{data.value}}</span><span class="mtk17">&lt;/</span><span class="mtk4">span</span><span class="mtk17">&gt;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk17">&lt;/</span><span class="mtk4">template</span><span class="mtk17">&gt;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk17">&lt;/</span><span class="mtk4">b-table</span><span class="mtk17">&gt;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk17">&lt;/</span><span class="mtk4">template</span><span class="mtk17">&gt;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk17">&lt;</span><span class="mtk4">script</span><span class="mtk17">&gt;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk15">export</span><span class="mtk1"> </span><span class="mtk15">default</span><span class="mtk1"> {</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">name:</span><span class="mtk1"> </span><span class="mtk8">&quot;EditableTable&quot;</span><span class="mtk1">,</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">components:</span><span class="mtk1"> {},</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">props:</span><span class="mtk1"> {</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">value:</span><span class="mtk1"> </span><span class="mtk10">Array</span><span class="mtk1">,</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">fields:</span><span class="mtk1"> </span><span class="mtk10">Array</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> },</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk11">data</span><span class="mtk1">() {</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk15">return</span><span class="mtk1"> {</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">tableItems:</span><span class="mtk1"> </span><span class="mtk4">this</span><span class="mtk1">.</span><span class="mtk12">value</span><span class="mtk1">.</span><span class="mtk11">map</span><span class="mtk1">(</span><span class="mtk12">item</span><span class="mtk1"> </span><span class="mtk4">=&gt;</span><span class="mtk1"> ({...</span><span class="mtk12">item</span><span class="mtk1">, </span><span class="mtk12">isEdit:</span><span class="mtk1"> </span><span class="mtk4">false</span><span class="mtk1">}))</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> }</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> },</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">methods:</span><span class="mtk1"> {</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk11">editRowHandler</span><span class="mtk1">(</span><span class="mtk12">data</span><span class="mtk1">) {</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk4">this</span><span class="mtk1">.</span><span class="mtk12">tableItems</span><span class="mtk1">[</span><span class="mtk12">data</span><span class="mtk1">.</span><span class="mtk12">index</span><span class="mtk1">].</span><span class="mtk12">isEdit</span><span class="mtk1"> = !</span><span class="mtk4">this</span><span class="mtk1">.</span><span class="mtk12">tableItems</span><span class="mtk1">[</span><span class="mtk12">data</span><span class="mtk1">.</span><span class="mtk12">index</span><span class="mtk1">].</span><span class="mtk12">isEdit</span><span class="mtk1">;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> },</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk11">inputHandler</span><span class="mtk1">(</span><span class="mtk12">value</span><span class="mtk1">, </span><span class="mtk12">index</span><span class="mtk1">, </span><span class="mtk12">key</span><span class="mtk1">) {</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk4">this</span><span class="mtk1">.</span><span class="mtk12">tableItems</span><span class="mtk1">[</span><span class="mtk12">index</span><span class="mtk1">][</span><span class="mtk12">key</span><span class="mtk1">] = </span><span class="mtk12">value</span><span class="mtk1">;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk4">this</span><span class="mtk1">.</span><span class="mtk11">$set</span><span class="mtk1">(</span><span class="mtk4">this</span><span class="mtk1">.</span><span class="mtk12">tableItems</span><span class="mtk1">, </span><span class="mtk12">index</span><span class="mtk1">, </span><span class="mtk4">this</span><span class="mtk1">.</span><span class="mtk12">tableItems</span><span class="mtk1">[</span><span class="mtk12">index</span><span class="mtk1">]);</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk4">this</span><span class="mtk1">.</span><span class="mtk11">$emit</span><span class="mtk1">(</span><span class="mtk8">&quot;input&quot;</span><span class="mtk1">, </span><span class="mtk4">this</span><span class="mtk1">.</span><span class="mtk12">tableItems</span><span class="mtk1">);</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> }</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> }</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1">};</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk17">&lt;/</span><span class="mtk4">script</span><span class="mtk17">&gt;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk17">&lt;</span><span class="mtk4">style</span><span class="mtk17">&gt;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk17">&lt;/</span><span class="mtk4">style</span><span class="mtk17">&gt;</span></span></span></code></pre> <h5 id="main-app-component-2" style="position:relative;"><a href="#main-app-component-2" aria-label="main app component 2 permalink" class="anchor before"><svg aria-hidden="true" focusable="false" height="16" version="1.1" viewBox="0 0 16 16" width="16"><path fill-rule="evenodd" d="M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z"></path></svg></a>Main App component</h5> <pre class="grvsc-container default-dark" data-language="html" data-index="9"><code class="grvsc-code"><span class="grvsc-line"><span class="grvsc-source"><span class="mtk17">&lt;</span><span class="mtk4">template</span><span class="mtk17">&gt;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk17">&lt;</span><span class="mtk4">div</span><span class="mtk1"> </span><span class="mtk12">id</span><span class="mtk1">=</span><span class="mtk8">&quot;app&quot;</span><span class="mtk17">&gt;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk17">&lt;</span><span class="mtk4">EditableTable</span><span class="mtk1"> </span><span class="mtk12">v-model</span><span class="mtk1">=</span><span class="mtk8">&quot;items&quot;</span><span class="mtk1"> </span><span class="mtk12">:fields</span><span class="mtk1">=</span><span class="mtk8">&quot;fields&quot;</span><span class="mtk17">&gt;&lt;/</span><span class="mtk4">EditableTable</span><span class="mtk17">&gt;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk17">&lt;</span><span class="mtk4">pre</span><span class="mtk17">&gt;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> {{items}}</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk17">&lt;/</span><span class="mtk4">pre</span><span class="mtk17">&gt;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk17">&lt;/</span><span class="mtk4">div</span><span class="mtk17">&gt;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk17">&lt;/</span><span class="mtk4">template</span><span class="mtk17">&gt;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk17">&lt;</span><span class="mtk4">script</span><span class="mtk17">&gt;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk15">import</span><span class="mtk1"> </span><span class="mtk12">EditableTable</span><span class="mtk1"> </span><span class="mtk15">from</span><span class="mtk1"> </span><span class="mtk8">&#39;./components/EditableTable.vue&#39;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk15">export</span><span class="mtk1"> </span><span class="mtk15">default</span><span class="mtk1"> {</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">name:</span><span class="mtk1"> </span><span class="mtk8">&quot;App&quot;</span><span class="mtk1">,</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">components:</span><span class="mtk1"> {</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">EditableTable</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> },</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk11">data</span><span class="mtk1">() {</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk15">return</span><span class="mtk1"> {</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">fields:</span><span class="mtk1"> [</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> { </span><span class="mtk12">key:</span><span class="mtk1"> </span><span class="mtk8">&quot;name&quot;</span><span class="mtk1">, </span><span class="mtk12">label:</span><span class="mtk1"> </span><span class="mtk8">&quot;Name&quot;</span><span class="mtk1">, </span><span class="mtk12">type:</span><span class="mtk1"> </span><span class="mtk8">&#39;text&#39;</span><span class="mtk1"> },</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> { </span><span class="mtk12">key:</span><span class="mtk1"> </span><span class="mtk8">&quot;department&quot;</span><span class="mtk1">, </span><span class="mtk12">label:</span><span class="mtk1"> </span><span class="mtk8">&quot;Department&quot;</span><span class="mtk1">, </span><span class="mtk12">type:</span><span class="mtk1"> </span><span class="mtk8">&#39;select&#39;</span><span class="mtk1">, </span><span class="mtk12">options:</span><span class="mtk1"> [</span><span class="mtk8">&#39;Development&#39;</span><span class="mtk1">, </span><span class="mtk8">&#39;Marketing&#39;</span><span class="mtk1">, </span><span class="mtk8">&#39;HR&#39;</span><span class="mtk1">, </span><span class="mtk8">&#39;Accounting&#39;</span><span class="mtk1">] },</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> { </span><span class="mtk12">key:</span><span class="mtk1"> </span><span class="mtk8">&quot;age&quot;</span><span class="mtk1">, </span><span class="mtk12">label:</span><span class="mtk1"> </span><span class="mtk8">&quot;Age&quot;</span><span class="mtk1">, </span><span class="mtk12">type:</span><span class="mtk1"> </span><span class="mtk8">&#39;number&#39;</span><span class="mtk1"> },</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> { </span><span class="mtk12">key:</span><span class="mtk1"> </span><span class="mtk8">&quot;dateOfBirth&quot;</span><span class="mtk1">, </span><span class="mtk12">label:</span><span class="mtk1"> </span><span class="mtk8">&quot;Date Of Birth&quot;</span><span class="mtk1">, </span><span class="mtk12">type:</span><span class="mtk1"> </span><span class="mtk8">&#39;date&#39;</span><span class="mtk1"> },</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> { </span><span class="mtk12">key:</span><span class="mtk1"> </span><span class="mtk8">&quot;edit&quot;</span><span class="mtk1">, </span><span class="mtk12">label:</span><span class="mtk1"> </span><span class="mtk8">&quot;&quot;</span><span class="mtk1">, </span><span class="mtk12">type:</span><span class="mtk1"> </span><span class="mtk8">&quot;edit&quot;</span><span class="mtk1"> }</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> ],</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">items:</span><span class="mtk1"> [</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> { </span><span class="mtk12">age:</span><span class="mtk1"> </span><span class="mtk7">40</span><span class="mtk1">, </span><span class="mtk12">name:</span><span class="mtk1"> </span><span class="mtk8">&#39;Dickerson&#39;</span><span class="mtk1">, </span><span class="mtk12">department:</span><span class="mtk1"> </span><span class="mtk8">&#39;Development&#39;</span><span class="mtk1">, </span><span class="mtk12">dateOfBirth:</span><span class="mtk1"> </span><span class="mtk8">&#39;1984-05-20&#39;</span><span class="mtk1"> },</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> { </span><span class="mtk12">age:</span><span class="mtk1"> </span><span class="mtk7">21</span><span class="mtk1">, </span><span class="mtk12">name:</span><span class="mtk1"> </span><span class="mtk8">&#39;Larsen&#39;</span><span class="mtk1">, </span><span class="mtk12">department:</span><span class="mtk1"> </span><span class="mtk8">&#39;Marketing&#39;</span><span class="mtk1">, </span><span class="mtk12">dateOfBirth:</span><span class="mtk1"> </span><span class="mtk8">&#39;1984-05-20&#39;</span><span class="mtk1"> },</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> { </span><span class="mtk12">age:</span><span class="mtk1"> </span><span class="mtk7">89</span><span class="mtk1">, </span><span class="mtk12">name:</span><span class="mtk1"> </span><span class="mtk8">&#39;Geneva&#39;</span><span class="mtk1">, </span><span class="mtk12">department:</span><span class="mtk1"> </span><span class="mtk8">&#39;HR&#39;</span><span class="mtk1">, </span><span class="mtk12">dateOfBirth:</span><span class="mtk1"> </span><span class="mtk8">&#39;1984-05-20&#39;</span><span class="mtk1"> },</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> { </span><span class="mtk12">age:</span><span class="mtk1"> </span><span class="mtk7">38</span><span class="mtk1">, </span><span class="mtk12">name:</span><span class="mtk1"> </span><span class="mtk8">&#39;Jami&#39;</span><span class="mtk1">, </span><span class="mtk12">department:</span><span class="mtk1"> </span><span class="mtk8">&#39;Accounting&#39;</span><span class="mtk1">, </span><span class="mtk12">dateOfBirth:</span><span class="mtk1"> </span><span class="mtk8">&#39;1984-05-20&#39;</span><span class="mtk1"> }</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> ]</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> };</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> }</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1">};</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk17">&lt;/</span><span class="mtk4">script</span><span class="mtk17">&gt;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk17">&lt;</span><span class="mtk4">style</span><span class="mtk17">&gt;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk6">#app</span><span class="mtk1"> {</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">text-align</span><span class="mtk1">: </span><span class="mtk8">center</span><span class="mtk1">;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">margin</span><span class="mtk1">: </span><span class="mtk7">60px</span><span class="mtk1">;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1">}</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk6">thead</span><span class="mtk1">, </span><span class="mtk6">tbody</span><span class="mtk1">, </span><span class="mtk6">tfoot</span><span class="mtk1">, </span><span class="mtk6">tr</span><span class="mtk1">, </span><span class="mtk6">td</span><span class="mtk1">, </span><span class="mtk6">th</span><span class="mtk1"> {</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">text-align</span><span class="mtk1">: </span><span class="mtk8">left</span><span class="mtk1">;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">width</span><span class="mtk1">: </span><span class="mtk7">100px</span><span class="mtk1">;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">vertical-align</span><span class="mtk1">: </span><span class="mtk8">middle</span><span class="mtk1">;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1">}</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk6">pre</span><span class="mtk1"> {</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">text-align</span><span class="mtk1">: </span><span class="mtk8">left</span><span class="mtk1">;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">color</span><span class="mtk1">: </span><span class="mtk8">#d63384</span><span class="mtk1"> </span><span class="mtk4">!important</span><span class="mtk1">;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1">}</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk17">&lt;/</span><span class="mtk4">style</span><span class="mtk17">&gt;</span></span></span></code></pre> <p>By now it’s clear that this approach has less code and above everything, it’s encapsulated and can be used with different table schemas across the whole project.</p> <h2 id="final-example" style="position:relative;"><a href="#final-example" aria-label="final example permalink" class="anchor before"><svg aria-hidden="true" focusable="false" height="16" version="1.1" viewBox="0 0 16 16" width="16"><path fill-rule="evenodd" d="M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z"></path></svg></a>Final example</h2> <p>Here is an example of how we can create two different table schemas using the same component:</p> <pre class="grvsc-container default-dark" data-language="html" data-index="10"><code class="grvsc-code"><span class="grvsc-line"><span class="grvsc-source"><span class="mtk17">&lt;</span><span class="mtk4">template</span><span class="mtk17">&gt;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk17">&lt;</span><span class="mtk4">div</span><span class="mtk1"> </span><span class="mtk12">id</span><span class="mtk1">=</span><span class="mtk8">&quot;app&quot;</span><span class="mtk17">&gt;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk17">&lt;</span><span class="mtk4">article</span><span class="mtk17">&gt;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk17">&lt;</span><span class="mtk4">h3</span><span class="mtk17">&gt;</span><span class="mtk1">Employee Information</span><span class="mtk17">&lt;/</span><span class="mtk4">h3</span><span class="mtk17">&gt;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk17">&lt;</span><span class="mtk4">EditableTable</span><span class="mtk1"> </span><span class="mtk12">v-model</span><span class="mtk1">=</span><span class="mtk8">&quot;items1&quot;</span><span class="mtk1"> </span><span class="mtk12">:fields</span><span class="mtk1">=</span><span class="mtk8">&quot;fields1&quot;</span><span class="mtk17">&gt;&lt;/</span><span class="mtk4">EditableTable</span><span class="mtk17">&gt;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk17">&lt;/</span><span class="mtk4">article</span><span class="mtk17">&gt;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk17">&lt;</span><span class="mtk4">article</span><span class="mtk17">&gt;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk17">&lt;</span><span class="mtk4">h3</span><span class="mtk17">&gt;</span><span class="mtk1">Employee Contract</span><span class="mtk17">&lt;/</span><span class="mtk4">h3</span><span class="mtk17">&gt;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk17">&lt;</span><span class="mtk4">EditableTable</span><span class="mtk1"> </span><span class="mtk12">v-model</span><span class="mtk1">=</span><span class="mtk8">&quot;items2&quot;</span><span class="mtk1"> </span><span class="mtk12">:fields</span><span class="mtk1">=</span><span class="mtk8">&quot;fields2&quot;</span><span class="mtk17">&gt;&lt;/</span><span class="mtk4">EditableTable</span><span class="mtk17">&gt;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk17">&lt;/</span><span class="mtk4">article</span><span class="mtk17">&gt;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk17">&lt;/</span><span class="mtk4">div</span><span class="mtk17">&gt;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk17">&lt;/</span><span class="mtk4">template</span><span class="mtk17">&gt;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk17">&lt;</span><span class="mtk4">script</span><span class="mtk17">&gt;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk15">import</span><span class="mtk1"> </span><span class="mtk12">EditableTable</span><span class="mtk1"> </span><span class="mtk15">from</span><span class="mtk1"> </span><span class="mtk8">&#39;./components/EditableTable.vue&#39;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk15">export</span><span class="mtk1"> </span><span class="mtk15">default</span><span class="mtk1"> {</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">name:</span><span class="mtk1"> </span><span class="mtk8">&quot;App&quot;</span><span class="mtk1">,</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">components:</span><span class="mtk1"> {</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">EditableTable</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> },</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk11">data</span><span class="mtk1">() {</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk15">return</span><span class="mtk1"> {</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">fields1:</span><span class="mtk1"> [</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> { </span><span class="mtk12">key:</span><span class="mtk1"> </span><span class="mtk8">&quot;name&quot;</span><span class="mtk1">, </span><span class="mtk12">label:</span><span class="mtk1"> </span><span class="mtk8">&quot;Name&quot;</span><span class="mtk1">, </span><span class="mtk12">type:</span><span class="mtk1"> </span><span class="mtk8">&quot;text&quot;</span><span class="mtk1"> },</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> { </span><span class="mtk12">key:</span><span class="mtk1"> </span><span class="mtk8">&quot;department&quot;</span><span class="mtk1">, </span><span class="mtk12">label:</span><span class="mtk1"> </span><span class="mtk8">&quot;Department&quot;</span><span class="mtk1">, </span><span class="mtk12">type:</span><span class="mtk1"> </span><span class="mtk8">&quot;select&quot;</span><span class="mtk1">, </span><span class="mtk12">options:</span><span class="mtk1"> [</span><span class="mtk8">&#39;Development&#39;</span><span class="mtk1">, </span><span class="mtk8">&#39;Marketing&#39;</span><span class="mtk1">, </span><span class="mtk8">&#39;HR&#39;</span><span class="mtk1">, </span><span class="mtk8">&#39;Accounting&#39;</span><span class="mtk1">] },</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> { </span><span class="mtk12">key:</span><span class="mtk1"> </span><span class="mtk8">&quot;age&quot;</span><span class="mtk1">, </span><span class="mtk12">label:</span><span class="mtk1"> </span><span class="mtk8">&quot;Age&quot;</span><span class="mtk1">, </span><span class="mtk12">type:</span><span class="mtk1"> </span><span class="mtk8">&quot;number&quot;</span><span class="mtk1"> },</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> { </span><span class="mtk12">key:</span><span class="mtk1"> </span><span class="mtk8">&quot;dateOfBirth&quot;</span><span class="mtk1">, </span><span class="mtk12">label:</span><span class="mtk1"> </span><span class="mtk8">&quot;Date Of Birth&quot;</span><span class="mtk1">, </span><span class="mtk12">type:</span><span class="mtk1"> </span><span class="mtk8">&quot;date&quot;</span><span class="mtk1"> },</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> { </span><span class="mtk12">key:</span><span class="mtk1"> </span><span class="mtk8">&quot;edit&quot;</span><span class="mtk1">, </span><span class="mtk12">label:</span><span class="mtk1"> </span><span class="mtk8">&quot;&quot;</span><span class="mtk1">, </span><span class="mtk12">type:</span><span class="mtk1"> </span><span class="mtk8">&quot;edit&quot;</span><span class="mtk1"> }</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> ],</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">items1:</span><span class="mtk1"> [</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> { </span><span class="mtk12">age:</span><span class="mtk1"> </span><span class="mtk7">40</span><span class="mtk1">, </span><span class="mtk12">name:</span><span class="mtk1"> </span><span class="mtk8">&#39;Dickerson&#39;</span><span class="mtk1">, </span><span class="mtk12">department:</span><span class="mtk1"> </span><span class="mtk8">&#39;Development&#39;</span><span class="mtk1">, </span><span class="mtk12">dateOfBirth:</span><span class="mtk1"> </span><span class="mtk8">&#39;1984-05-20&#39;</span><span class="mtk1"> },</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> { </span><span class="mtk12">age:</span><span class="mtk1"> </span><span class="mtk7">21</span><span class="mtk1">, </span><span class="mtk12">name:</span><span class="mtk1"> </span><span class="mtk8">&#39;Larsen&#39;</span><span class="mtk1">, </span><span class="mtk12">department:</span><span class="mtk1"> </span><span class="mtk8">&#39;Marketing&#39;</span><span class="mtk1">, </span><span class="mtk12">dateOfBirth:</span><span class="mtk1"> </span><span class="mtk8">&#39;1984-05-20&#39;</span><span class="mtk1"> },</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> { </span><span class="mtk12">age:</span><span class="mtk1"> </span><span class="mtk7">89</span><span class="mtk1">, </span><span class="mtk12">name:</span><span class="mtk1"> </span><span class="mtk8">&#39;Geneva&#39;</span><span class="mtk1">, </span><span class="mtk12">department:</span><span class="mtk1"> </span><span class="mtk8">&#39;HR&#39;</span><span class="mtk1">, </span><span class="mtk12">dateOfBirth:</span><span class="mtk1"> </span><span class="mtk8">&#39;1984-05-20&#39;</span><span class="mtk1"> },</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> { </span><span class="mtk12">age:</span><span class="mtk1"> </span><span class="mtk7">38</span><span class="mtk1">, </span><span class="mtk12">name:</span><span class="mtk1"> </span><span class="mtk8">&#39;Jami&#39;</span><span class="mtk1">, </span><span class="mtk12">department:</span><span class="mtk1"> </span><span class="mtk8">&#39;Accounting&#39;</span><span class="mtk1">, </span><span class="mtk12">dateOfBirth:</span><span class="mtk1"> </span><span class="mtk8">&#39;1984-05-20&#39;</span><span class="mtk1"> },</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> ],</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">fields2:</span><span class="mtk1"> [</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> { </span><span class="mtk12">key:</span><span class="mtk1"> </span><span class="mtk8">&quot;id&quot;</span><span class="mtk1">, </span><span class="mtk12">label:</span><span class="mtk1"> </span><span class="mtk8">&quot;ID&quot;</span><span class="mtk1">, </span><span class="mtk12">type:</span><span class="mtk1"> </span><span class="mtk8">&quot;number&quot;</span><span class="mtk1"> },</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> { </span><span class="mtk12">key:</span><span class="mtk1"> </span><span class="mtk8">&quot;name&quot;</span><span class="mtk1">, </span><span class="mtk12">label:</span><span class="mtk1"> </span><span class="mtk8">&quot;Name&quot;</span><span class="mtk1">, </span><span class="mtk12">type:</span><span class="mtk1"> </span><span class="mtk8">&quot;text&quot;</span><span class="mtk1"> },</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> { </span><span class="mtk12">key:</span><span class="mtk1"> </span><span class="mtk8">&quot;contractEndDate&quot;</span><span class="mtk1">, </span><span class="mtk12">label:</span><span class="mtk1"> </span><span class="mtk8">&quot;Contract End Date&quot;</span><span class="mtk1">, </span><span class="mtk12">type:</span><span class="mtk1"> </span><span class="mtk8">&quot;date&quot;</span><span class="mtk1"> },</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> { </span><span class="mtk12">key:</span><span class="mtk1"> </span><span class="mtk8">&quot;edit&quot;</span><span class="mtk1">, </span><span class="mtk12">label:</span><span class="mtk1"> </span><span class="mtk8">&quot;&quot;</span><span class="mtk1">, </span><span class="mtk12">type:</span><span class="mtk1"> </span><span class="mtk8">&quot;edit&quot;</span><span class="mtk1"> }</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> ],</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">items2:</span><span class="mtk1"> [</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> { </span><span class="mtk12">id:</span><span class="mtk1"> </span><span class="mtk7">123</span><span class="mtk1">, </span><span class="mtk12">name:</span><span class="mtk1"> </span><span class="mtk8">&#39;Dickerson&#39;</span><span class="mtk1">, </span><span class="mtk12">contractEndDate:</span><span class="mtk1"> </span><span class="mtk8">&#39;2022-05-20&#39;</span><span class="mtk1"> },</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> { </span><span class="mtk12">id:</span><span class="mtk1"> </span><span class="mtk7">345</span><span class="mtk1">, </span><span class="mtk12">name:</span><span class="mtk1"> </span><span class="mtk8">&#39;Larsen&#39;</span><span class="mtk1">, </span><span class="mtk12">contractEndDate:</span><span class="mtk1"> </span><span class="mtk8">&#39;2021-05-20&#39;</span><span class="mtk1"> },</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> { </span><span class="mtk12">id:</span><span class="mtk1"> </span><span class="mtk7">456</span><span class="mtk1">, </span><span class="mtk12">name:</span><span class="mtk1"> </span><span class="mtk8">&#39;Geneva&#39;</span><span class="mtk1">, </span><span class="mtk12">contractEndDate:</span><span class="mtk1"> </span><span class="mtk8">&#39;2023-05-20&#39;</span><span class="mtk1"> },</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> { </span><span class="mtk12">id:</span><span class="mtk1"> </span><span class="mtk7">678</span><span class="mtk1">, </span><span class="mtk12">name:</span><span class="mtk1"> </span><span class="mtk8">&#39;Jami&#39;</span><span class="mtk1">, </span><span class="mtk12">contractEndDate:</span><span class="mtk1"> </span><span class="mtk8">&#39;2024-05-20&#39;</span><span class="mtk1"> }</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> ]</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> };</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> }</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1">};</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk17">&lt;/</span><span class="mtk4">script</span><span class="mtk17">&gt;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk17">&lt;</span><span class="mtk4">style</span><span class="mtk17">&gt;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk6">#app</span><span class="mtk1"> {</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">text-align</span><span class="mtk1">: </span><span class="mtk8">center</span><span class="mtk1">;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">margin</span><span class="mtk1">: </span><span class="mtk7">60px</span><span class="mtk1">;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1">}</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk6">thead</span><span class="mtk1">, </span><span class="mtk6">tbody</span><span class="mtk1">, </span><span class="mtk6">tfoot</span><span class="mtk1">, </span><span class="mtk6">tr</span><span class="mtk1">, </span><span class="mtk6">td</span><span class="mtk1">, </span><span class="mtk6">th</span><span class="mtk1"> {</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">text-align</span><span class="mtk1">: </span><span class="mtk8">left</span><span class="mtk1">;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">width</span><span class="mtk1">: </span><span class="mtk7">100px</span><span class="mtk1">;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">vertical-align</span><span class="mtk1">: </span><span class="mtk8">middle</span><span class="mtk1">;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1">}</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk6">pre</span><span class="mtk1"> {</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">text-align</span><span class="mtk1">: </span><span class="mtk8">left</span><span class="mtk1">;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">color</span><span class="mtk1">: </span><span class="mtk8">#d63384</span><span class="mtk1">;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1">}</span></span></span></code></pre> <div data-youtube="1IqBIe5y36U"> <button>Play Example</button> </div> <h2 id="summary" style="position:relative;"><a href="#summary" aria-label="summary permalink" class="anchor before"><svg aria-hidden="true" focusable="false" height="16" version="1.1" viewBox="0 0 16 16" width="16"><path fill-rule="evenodd" d="M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z"></path></svg></a>Summary</h2> <p>If you made it to this section, pat yourself on the back! You just learned how to:</p> <ul> <li>Encapsulate and reuse custom components</li> <li>Support dynamic table schema</li> <li>Enable <code>v-model</code> in a custom component</li> </ul> <p>You can access the <a href="https://github.com/muhimasri/vue-editable-table-example">complete repository here</a>.</p> <p>Bye for now 👋</p> <style class="grvsc-styles"> .grvsc-container { overflow: auto; position: relative; -webkit-overflow-scrolling: touch; padding-top: 1rem; padding-top: var(--grvsc-padding-top, var(--grvsc-padding-v, 1rem)); padding-bottom: 1rem; padding-bottom: var(--grvsc-padding-bottom, var(--grvsc-padding-v, 1rem)); border-radius: 8px; border-radius: var(--grvsc-border-radius, 8px); font-feature-settings: normal; line-height: 1.4; } .grvsc-code { display: table; } .grvsc-line { display: table-row; box-sizing: border-box; width: 100%; position: relative; } .grvsc-line > * { position: relative; } .grvsc-gutter-pad { display: table-cell; padding-left: 0.75rem; padding-left: calc(var(--grvsc-padding-left, var(--grvsc-padding-h, 1.5rem)) / 2); } .grvsc-gutter { display: table-cell; -webkit-user-select: none; -moz-user-select: none; user-select: none; } .grvsc-gutter::before { content: attr(data-content); } .grvsc-source { display: table-cell; padding-left: 1.5rem; padding-left: var(--grvsc-padding-left, var(--grvsc-padding-h, 1.5rem)); padding-right: 1.5rem; padding-right: var(--grvsc-padding-right, var(--grvsc-padding-h, 1.5rem)); } .grvsc-source:empty::after { content: ' '; -webkit-user-select: none; -moz-user-select: none; user-select: none; } .grvsc-gutter + .grvsc-source { padding-left: 0.75rem; padding-left: calc(var(--grvsc-padding-left, var(--grvsc-padding-h, 1.5rem)) / 2); } /* Line transformer styles */ .grvsc-has-line-highlighting > .grvsc-code > .grvsc-line::before { content: ' '; position: absolute; width: 100%; } .grvsc-line-diff-add::before { background-color: var(--grvsc-line-diff-add-background-color, rgba(0, 255, 60, 0.2)); } .grvsc-line-diff-del::before { background-color: var(--grvsc-line-diff-del-background-color, rgba(255, 0, 20, 0.2)); } .grvsc-line-number { padding: 0 2px; text-align: right; opacity: 0.7; } .default-dark { background-color: #1E1E1E; color: #D4D4D4; } .default-dark .mtk17 { color: #808080; } .default-dark .mtk4 { color: #569CD6; } .default-dark .mtk1 { color: #D4D4D4; } .default-dark .mtk12 { color: #9CDCFE; } .default-dark .mtk8 { color: #CE9178; } .default-dark .mtk15 { color: #C586C0; } .default-dark .mtk11 { color: #DCDCAA; } .default-dark .mtk7 { color: #B5CEA8; } .default-dark .mtk10 { color: #4EC9B0; } .default-dark .mtk6 { color: #D7BA7D; } .default-dark .grvsc-line-highlighted::before { background-color: var(--grvsc-line-highlighted-background-color, rgba(255, 255, 255, 0.1)); box-shadow: inset var(--grvsc-line-highlighted-border-width, 4px) 0 0 0 var(--grvsc-line-highlighted-border-color, rgba(255, 255, 255, 0.5)); } </style><![CDATA[[Part 3] Load, Add, Update and Delete Table Rows using API Services]]>https://muhimasri.comload-add-update-and-delete-table-rows-using-api-serviceshttps://muhimasri.comload-add-update-and-delete-table-rows-using-api-services<p>In this part of the Angular Material Table series, we take all operations we built in the <a href="https://muhimasri.com/blogs/create-an-editable-dynamic-table-using-angular-material/">first</a> and <a href="https://muhimasri.com/blogs/add-and-remove-table-rows-using-angular-material/">second</a> parts (load, add, edit and delete data) and connect them to API services.</p> <p>We won’t be building or using any custom backend solution as this is not the objective of this series. Instead, we are utilizing <a href="https://dummyjson.com/">DummyJSON</a>, which is a free fake API for testing and prototyping.</p> <p>At the end of this tutorial, we should have the following results (all video demos will have the network panel open to show API calls):</p> <div data-youtube="3uMVvVKjf4s"> <button>Play Example</button> </div> <p><em>As we continue building upon the same code from previous parts in this series, it’s recommended that you go through these tutorials from the beginning to understand how the code structure works as we will not be explaining it. You can navigate to any part using the table of contents.</em></p> <p>Before we begin, the <a href="https://github.com/muhimasri/angular-editable-table">complete repository is accessible here</a> and a working example is available below:</p> <div data-stackblitz="angular-editable-table-part-3"> <button>Run Code</button> </div> <h2 id="create-a-service-and-a-model-class" style="position:relative;"><a href="#create-a-service-and-a-model-class" aria-label="create a service and a model class permalink" class="anchor before"><svg aria-hidden="true" focusable="false" height="16" version="1.1" viewBox="0 0 16 16" width="16"><path fill-rule="evenodd" d="M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z"></path></svg></a>Create a service and a model class</h2> <p>Previously, we only had static data in the component class with no model as we were only focusing on building an editable table. Now that we are connecting operations to API services, we will add a model and a service layer.</p> <p><a href="https://dummyjson.com/">DummyJSON</a> provides us with different resources like posts, users, products, comments..etc. For simplicity purposes, we’ll pick users and create a new <code>user.ts</code> model:</p> <pre class="grvsc-container default-dark" data-language="typescript" data-index="0"><code class="grvsc-code"><span class="grvsc-line"><span class="grvsc-source"><span class="mtk15">export</span><span class="mtk1"> </span><span class="mtk4">interface</span><span class="mtk1"> </span><span class="mtk10">User</span><span class="mtk1"> {</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">isSelected</span><span class="mtk1">: </span><span class="mtk10">boolean</span><span class="mtk1">;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">id</span><span class="mtk1">: </span><span class="mtk10">number</span><span class="mtk1">;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">firstName</span><span class="mtk1">: </span><span class="mtk10">string</span><span class="mtk1">;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">lastName</span><span class="mtk1">: </span><span class="mtk10">string</span><span class="mtk1">;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">email</span><span class="mtk1">: </span><span class="mtk10">string</span><span class="mtk1">;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">birthDate</span><span class="mtk1">: </span><span class="mtk10">string</span><span class="mtk1">;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">isEdit</span><span class="mtk1">: </span><span class="mtk10">boolean</span><span class="mtk1">;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1">}</span></span></span> <span class="grvsc-line"><span class="grvsc-source"></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk15">export</span><span class="mtk1"> </span><span class="mtk4">const</span><span class="mtk1"> </span><span class="mtk12">UserColumns</span><span class="mtk1"> = [</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> {</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">key:</span><span class="mtk1"> </span><span class="mtk8">&#39;isSelected&#39;</span><span class="mtk1">,</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">type:</span><span class="mtk1"> </span><span class="mtk8">&#39;isSelected&#39;</span><span class="mtk1">,</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">label:</span><span class="mtk1"> </span><span class="mtk8">&#39;&#39;</span><span class="mtk1">,</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> },</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> {</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">key:</span><span class="mtk1"> </span><span class="mtk8">&#39;firstName&#39;</span><span class="mtk1">,</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">type:</span><span class="mtk1"> </span><span class="mtk8">&#39;text&#39;</span><span class="mtk1">,</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">label:</span><span class="mtk1"> </span><span class="mtk8">&#39;First Name&#39;</span><span class="mtk1">,</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> },</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> {</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">key:</span><span class="mtk1"> </span><span class="mtk8">&#39;lastName&#39;</span><span class="mtk1">,</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">type:</span><span class="mtk1"> </span><span class="mtk8">&#39;text&#39;</span><span class="mtk1">,</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">label:</span><span class="mtk1"> </span><span class="mtk8">&#39;Last Name&#39;</span><span class="mtk1">,</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> },</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> {</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">key:</span><span class="mtk1"> </span><span class="mtk8">&#39;email&#39;</span><span class="mtk1">,</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">type:</span><span class="mtk1"> </span><span class="mtk8">&#39;email&#39;</span><span class="mtk1">,</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">label:</span><span class="mtk1"> </span><span class="mtk8">&#39;Email&#39;</span><span class="mtk1">,</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> },</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> {</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">key:</span><span class="mtk1"> </span><span class="mtk8">&#39;birthDate&#39;</span><span class="mtk1">,</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">type:</span><span class="mtk1"> </span><span class="mtk8">&#39;date&#39;</span><span class="mtk1">,</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">label:</span><span class="mtk1"> </span><span class="mtk8">&#39;Date of Birth&#39;</span><span class="mtk1">,</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> },</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> {</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">key:</span><span class="mtk1"> </span><span class="mtk8">&#39;isEdit&#39;</span><span class="mtk1">,</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">type:</span><span class="mtk1"> </span><span class="mtk8">&#39;isEdit&#39;</span><span class="mtk1">,</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">label:</span><span class="mtk1"> </span><span class="mtk8">&#39;&#39;</span><span class="mtk1">,</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> },</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1">];</span></span></span></code></pre> <p>A quick recap from the <a href="https://muhimasri.com/blogs/create-an-editable-dynamic-table-using-angular-material/">first part</a>, <code>UserColumns</code> is used in the template to help us create dynamic input fields when editing a row. For example, the <code>firstName</code> column has a <code>text</code> type, so it should show a textbox when editing a row. If we change it to <code>date</code>, it will populate a date input field. We can use any type we’d like as long as it’s defined in the template. Another reminder; <code>isSelected</code> and <code>isEdit</code> are not part of the backend model. They are used in the view model to manage the row’s state (whether or not the row is in edit mode or is selected).</p> <p>In the <code>app.component.ts</code> class, let’s change what we had earlier to use the new <code>`UserColumns`</code> model:</p> <pre class="grvsc-container grvsc-has-line-highlighting default-dark" data-language="typescript" data-index="1"><code class="grvsc-code"><span class="grvsc-line"><span class="grvsc-source"><span class="mtk15">import</span><span class="mtk1"> { </span><span class="mtk12">Component</span><span class="mtk1"> } </span><span class="mtk15">from</span><span class="mtk1"> </span><span class="mtk8">&#39;@angular/core&#39;</span><span class="mtk1">;</span></span></span> <span class="grvsc-line grvsc-line-highlighted"><span class="grvsc-source"><span class="mtk15">import</span><span class="mtk1"> { </span><span class="mtk12">UserColumns</span><span class="mtk1"> } </span><span class="mtk15">from</span><span class="mtk1"> </span><span class="mtk8">&#39;./model/user&#39;</span><span class="mtk1">;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1">@</span><span class="mtk11">Component</span><span class="mtk1">({</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">selector:</span><span class="mtk1"> </span><span class="mtk8">&#39;app-root&#39;</span><span class="mtk1">,</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">templateUrl:</span><span class="mtk1"> </span><span class="mtk8">&#39;./app.component.html&#39;</span><span class="mtk1">,</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">styleUrls:</span><span class="mtk1"> [</span><span class="mtk8">&#39;./app.component.scss&#39;</span><span class="mtk1">],</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1">})</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk15">export</span><span class="mtk1"> </span><span class="mtk4">class</span><span class="mtk1"> </span><span class="mtk10">AppComponent</span><span class="mtk1"> {</span></span></span> <span class="grvsc-line grvsc-line-highlighted"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">displayedColumns</span><span class="mtk1">: </span><span class="mtk10">string</span><span class="mtk1">[] = </span><span class="mtk12">UserColumns</span><span class="mtk1">.</span><span class="mtk11">map</span><span class="mtk1">((</span><span class="mtk12">col</span><span class="mtk1">) </span><span class="mtk4">=&gt;</span><span class="mtk1"> </span><span class="mtk12">col</span><span class="mtk1">.</span><span class="mtk12">key</span><span class="mtk1">);</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">dataSource</span><span class="mtk1"> = </span><span class="mtk12">USER_DATA</span><span class="mtk1">;</span></span></span> <span class="grvsc-line grvsc-line-highlighted"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">columnsSchema</span><span class="mtk1">: </span><span class="mtk10">any</span><span class="mtk1"> = </span><span class="mtk12">UserColumns</span><span class="mtk1">;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1">}</span></span></span></code></pre> <p>Now, we can create a basic <code>user.service.ts</code> class with a service URL and other required imports like <code>Observable</code>, <code>HttpClient</code>, <code>User</code> model…</p> <pre class="grvsc-container default-dark" data-language="typescript" data-index="2"><code class="grvsc-code"><span class="grvsc-line"><span class="grvsc-source"><span class="mtk15">import</span><span class="mtk1"> { </span><span class="mtk12">Injectable</span><span class="mtk1"> } </span><span class="mtk15">from</span><span class="mtk1"> </span><span class="mtk8">&#39;@angular/core&#39;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk15">import</span><span class="mtk1"> { </span><span class="mtk12">HttpClient</span><span class="mtk1"> } </span><span class="mtk15">from</span><span class="mtk1"> </span><span class="mtk8">&#39;@angular/common/http&#39;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1">@</span><span class="mtk11">Injectable</span><span class="mtk1">({</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">providedIn:</span><span class="mtk1"> </span><span class="mtk8">&#39;root&#39;</span><span class="mtk1">,</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1">})</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk15">export</span><span class="mtk1"> </span><span class="mtk4">class</span><span class="mtk1"> </span><span class="mtk10">UserService</span><span class="mtk1"> {</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk4">private</span><span class="mtk1"> </span><span class="mtk12">serviceUrl</span><span class="mtk1"> = </span><span class="mtk8">&#39;https://dummyjson.com/users&#39;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk4">constructor</span><span class="mtk1">(</span><span class="mtk4">private</span><span class="mtk1"> </span><span class="mtk12">http</span><span class="mtk1">: </span><span class="mtk10">HttpClient</span><span class="mtk1">) {}</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1">}</span></span></span></code></pre> <h2 id="load-data-with-rest-api" style="position:relative;"><a href="#load-data-with-rest-api" aria-label="load data with rest api permalink" class="anchor before"><svg aria-hidden="true" focusable="false" height="16" version="1.1" viewBox="0 0 16 16" width="16"><path fill-rule="evenodd" d="M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z"></path></svg></a>Load data with REST API</h2> <p>Now that we have the model and service classes set up correctly, we can add a <code>getUsers</code> method to the service to trigger an API call and return an observable list of users:</p> <pre class="grvsc-container default-dark" data-language="typescript" data-index="3"><code class="grvsc-code"><span class="grvsc-line"><span class="grvsc-source"><span class="mtk15">import</span><span class="mtk1"> { </span><span class="mtk12">Injectable</span><span class="mtk1"> } </span><span class="mtk15">from</span><span class="mtk1"> </span><span class="mtk8">&#39;@angular/core&#39;</span><span class="mtk1">;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk15">import</span><span class="mtk1"> { </span><span class="mtk12">HttpClient</span><span class="mtk1"> } </span><span class="mtk15">from</span><span class="mtk1"> </span><span class="mtk8">&#39;@angular/common/http&#39;</span><span class="mtk1">;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk15">import</span><span class="mtk1"> { </span><span class="mtk12">Observable</span><span class="mtk1"> } </span><span class="mtk15">from</span><span class="mtk1"> </span><span class="mtk8">&#39;rxjs&#39;</span><span class="mtk1">;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk15">import</span><span class="mtk1"> { </span><span class="mtk12">User</span><span class="mtk1"> } </span><span class="mtk15">from</span><span class="mtk1"> </span><span class="mtk8">&#39;../model/user&#39;</span><span class="mtk1">;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk15">import</span><span class="mtk1"> { </span><span class="mtk12">map</span><span class="mtk1"> } </span><span class="mtk15">from</span><span class="mtk1"> </span><span class="mtk8">&#39;rxjs/operators&#39;</span><span class="mtk1">;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1">@</span><span class="mtk11">Injectable</span><span class="mtk1">({</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">providedIn:</span><span class="mtk1"> </span><span class="mtk8">&#39;root&#39;</span><span class="mtk1">,</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1">})</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk15">export</span><span class="mtk1"> </span><span class="mtk4">class</span><span class="mtk1"> </span><span class="mtk10">UserService</span><span class="mtk1"> {</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk4">private</span><span class="mtk1"> </span><span class="mtk12">serviceUrl</span><span class="mtk1"> = </span><span class="mtk8">&#39;https://dummyjson.com/users&#39;</span><span class="mtk1">;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk4">constructor</span><span class="mtk1">(</span><span class="mtk4">private</span><span class="mtk1"> </span><span class="mtk12">http</span><span class="mtk1">: </span><span class="mtk10">HttpClient</span><span class="mtk1">) {}</span></span></span> <span class="grvsc-line"><span class="grvsc-source"></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk11">getUsers</span><span class="mtk1">(): </span><span class="mtk10">Observable</span><span class="mtk1">&lt;</span><span class="mtk10">User</span><span class="mtk1">[]&gt; {</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk15">return</span><span class="mtk1"> </span><span class="mtk4">this</span><span class="mtk1">.</span><span class="mtk12">http</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> .</span><span class="mtk11">get</span><span class="mtk1">(</span><span class="mtk4">this</span><span class="mtk1">.</span><span class="mtk12">serviceUrl</span><span class="mtk1">)</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> .</span><span class="mtk11">pipe</span><span class="mtk1">&lt;</span><span class="mtk10">User</span><span class="mtk1">[]&gt;(</span><span class="mtk11">map</span><span class="mtk1">((</span><span class="mtk12">data</span><span class="mtk1">: </span><span class="mtk10">any</span><span class="mtk1">) </span><span class="mtk4">=&gt;</span><span class="mtk1"> </span><span class="mtk12">data</span><span class="mtk1">.</span><span class="mtk12">users</span><span class="mtk1">));</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> }</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1">}</span></span></span></code></pre> <p>In the <code>app.component.ts</code> class, let’s subscribe to the service method and assign the results to the <code>dataSource</code> object:</p> <pre class="grvsc-container default-dark" data-language="typescript" data-index="4"><code class="grvsc-code"><span class="grvsc-line"><span class="grvsc-source"><span class="mtk15">import</span><span class="mtk1"> { </span><span class="mtk12">Component</span><span class="mtk1">, </span><span class="mtk12">OnInit</span><span class="mtk1"> } </span><span class="mtk15">from</span><span class="mtk1"> </span><span class="mtk8">&#39;@angular/core&#39;</span><span class="mtk1">;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk15">import</span><span class="mtk1"> { </span><span class="mtk12">MatDialog</span><span class="mtk1"> } </span><span class="mtk15">from</span><span class="mtk1"> </span><span class="mtk8">&#39;@angular/material/dialog&#39;</span><span class="mtk1">;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk15">import</span><span class="mtk1"> { </span><span class="mtk12">MatTableDataSource</span><span class="mtk1"> } </span><span class="mtk15">from</span><span class="mtk1"> </span><span class="mtk8">&#39;@angular/material/table&#39;</span><span class="mtk1">;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk15">import</span><span class="mtk1"> { </span><span class="mtk12">User</span><span class="mtk1">, </span><span class="mtk12">UserColumns</span><span class="mtk1"> } </span><span class="mtk15">from</span><span class="mtk1"> </span><span class="mtk8">&#39;./model/user&#39;</span><span class="mtk1">;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk15">import</span><span class="mtk1"> { </span><span class="mtk12">UserService</span><span class="mtk1"> } </span><span class="mtk15">from</span><span class="mtk1"> </span><span class="mtk8">&#39;./services/user.service&#39;</span><span class="mtk1">;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1">@</span><span class="mtk11">Component</span><span class="mtk1">({</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">selector:</span><span class="mtk1"> </span><span class="mtk8">&#39;app-root&#39;</span><span class="mtk1">,</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">templateUrl:</span><span class="mtk1"> </span><span class="mtk8">&#39;./app.component.html&#39;</span><span class="mtk1">,</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">styleUrls:</span><span class="mtk1"> [</span><span class="mtk8">&#39;./app.component.scss&#39;</span><span class="mtk1">],</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1">})</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk15">export</span><span class="mtk1"> </span><span class="mtk4">class</span><span class="mtk1"> </span><span class="mtk10">AppComponent</span><span class="mtk1"> {</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">displayedColumns</span><span class="mtk1">: </span><span class="mtk10">string</span><span class="mtk1">[] = </span><span class="mtk12">UserColumns</span><span class="mtk1">.</span><span class="mtk11">map</span><span class="mtk1">((</span><span class="mtk12">col</span><span class="mtk1">) </span><span class="mtk4">=&gt;</span><span class="mtk1"> </span><span class="mtk12">col</span><span class="mtk1">.</span><span class="mtk12">key</span><span class="mtk1">);</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">columnsSchema</span><span class="mtk1">: </span><span class="mtk10">any</span><span class="mtk1"> = </span><span class="mtk12">UserColumns</span><span class="mtk1">;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">dataSource</span><span class="mtk1"> = </span><span class="mtk4">new</span><span class="mtk1"> </span><span class="mtk10">MatTableDataSource</span><span class="mtk1">&lt;</span><span class="mtk10">User</span><span class="mtk1">&gt;();</span></span></span> <span class="grvsc-line"><span class="grvsc-source"></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk4">constructor</span><span class="mtk1">(</span><span class="mtk4">public</span><span class="mtk1"> </span><span class="mtk12">dialog</span><span class="mtk1">: </span><span class="mtk10">MatDialog</span><span class="mtk1">, </span><span class="mtk4">private</span><span class="mtk1"> </span><span class="mtk12">userService</span><span class="mtk1">: </span><span class="mtk10">UserService</span><span class="mtk1">) {}</span></span></span> <span class="grvsc-line"><span class="grvsc-source"></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk11">ngOnInit</span><span class="mtk1">() {</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk4">this</span><span class="mtk1">.</span><span class="mtk12">userService</span><span class="mtk1">.</span><span class="mtk11">getUsers</span><span class="mtk1">().</span><span class="mtk11">subscribe</span><span class="mtk1">((</span><span class="mtk12">res</span><span class="mtk1">: </span><span class="mtk10">any</span><span class="mtk1">) </span><span class="mtk4">=&gt;</span><span class="mtk1"> {</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk4">this</span><span class="mtk1">.</span><span class="mtk12">dataSource</span><span class="mtk1">.</span><span class="mtk12">data</span><span class="mtk1"> = </span><span class="mtk12">res</span><span class="mtk1">;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> });</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> }</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1">}</span></span></span></code></pre> <p>Previously, <code>dataSource</code> used to be of type <code>Array</code>, but we are changing it to <code>MatTableDataSource</code> to leverage its features later in this series.</p> <p>Now if we run the code, we should get the following results:</p> <p><span class="gatsby-resp-image-wrapper" style="position: relative; display: block; margin-left: auto; margin-right: auto; max-width: 720px; " > <a class="gatsby-resp-image-link" href="/static/220fe3576bf642dc815428810f62343f/2bef9/image-3-1024x710.png" style="display: block" target="_blank" rel="noopener" > <span class="gatsby-resp-image-background-image" style="padding-bottom: 69.44444444444444%; position: relative; bottom: 0; left: 0; background-image: url('data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABQAAAAOCAIAAACgpqunAAAACXBIWXMAAAsTAAALEwEAmpwYAAABj0lEQVR42o2S306DMBjFeSlN9ieU0EKBFhh0sPcxRi98Ai+2ZI8xF6M+gldeeKvRS2FbsktPi2NsusTvoqG0v57T08/abrdVVa3X67quV6uVGeuj0v+rqt5svt7fPq6vXm8ubu8vXz6frfl8TinN8zyOY4xCiNFohG+xKyllrnKMIor0ZKzSspRcPj48WdPpdDAY+L7PGIvCkDhOHMs0SVzXdUzhQ0jRTh1CAs+zz88WdwtrNpvZtg0F7vthGGJTlmUQp4xRU57npWmKEUt6zhg8uL3ecrnUMLFtYBBPkgSrgJVSevceTjA2Z/2CCYkiDeNGACALnnWUcWgXxuUPYChzzmHeNcpjpSLs6CrvztLKXfjnzpzLHYzYYYSesn0IExjzOYcaNbah3IW17VPKsI3bYnfAOSIFPClLfTETb5v234G1tiMD5FlWFGN0RwsfBXYMN0/VwE1g5s3/kTaaBlEBjqVWQ1plUeCp2rTRNN0mQevSFh4Oh0EQAIZzrMam2ndm2qfYB0Yputjp9wF/A/HELC0jsKvYAAAAAElFTkSuQmCC'); background-size: cover; display: block;" ></span> <img class="gatsby-resp-image-image" alt="image 3 1024x710" title="" src="/static/220fe3576bf642dc815428810f62343f/37523/image-3-1024x710.png" srcset="/static/220fe3576bf642dc815428810f62343f/e9ff0/image-3-1024x710.png 180w, /static/220fe3576bf642dc815428810f62343f/f21e7/image-3-1024x710.png 360w, /static/220fe3576bf642dc815428810f62343f/37523/image-3-1024x710.png 720w, /static/220fe3576bf642dc815428810f62343f/2bef9/image-3-1024x710.png 1024w" sizes="(max-width: 720px) 100vw, 720px" style="width:100%;height:100%;margin:0;vertical-align:middle;position:absolute;top:0;left:0;" loading="lazy" decoding="async" /> </a> </span></p> <h2 id="update-a-row-with-rest-api" style="position:relative;"><a href="#update-a-row-with-rest-api" aria-label="update a row with rest api permalink" class="anchor before"><svg aria-hidden="true" focusable="false" height="16" version="1.1" viewBox="0 0 16 16" width="16"><path fill-rule="evenodd" d="M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z"></path></svg></a>Update a row with REST API</h2> <p>A <code>patch</code> API service is usually the most suitable operation for updating data. So let’s create a <code>updateUser</code> function, attach the user id to the service URL and pass the user object as a parameter:</p> <pre class="grvsc-container grvsc-has-line-highlighting default-dark" data-language="typescript" data-index="5"><code class="grvsc-code"><span class="grvsc-line"><span class="grvsc-source"><span class="mtk15">import</span><span class="mtk1"> { </span><span class="mtk12">Injectable</span><span class="mtk1"> } </span><span class="mtk15">from</span><span class="mtk1"> </span><span class="mtk8">&#39;@angular/core&#39;</span><span class="mtk1">;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk15">import</span><span class="mtk1"> { </span><span class="mtk12">HttpClient</span><span class="mtk1"> } </span><span class="mtk15">from</span><span class="mtk1"> </span><span class="mtk8">&#39;@angular/common/http&#39;</span><span class="mtk1">;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk15">import</span><span class="mtk1"> { </span><span class="mtk12">Observable</span><span class="mtk1"> } </span><span class="mtk15">from</span><span class="mtk1"> </span><span class="mtk8">&#39;rxjs&#39;</span><span class="mtk1">;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk15">import</span><span class="mtk1"> { </span><span class="mtk12">User</span><span class="mtk1"> } </span><span class="mtk15">from</span><span class="mtk1"> </span><span class="mtk8">&#39;../model/user&#39;</span><span class="mtk1">;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk15">import</span><span class="mtk1"> { </span><span class="mtk12">map</span><span class="mtk1"> } </span><span class="mtk15">from</span><span class="mtk1"> </span><span class="mtk8">&#39;rxjs/operators&#39;</span><span class="mtk1">;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1">@</span><span class="mtk11">Injectable</span><span class="mtk1">({</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">providedIn:</span><span class="mtk1"> </span><span class="mtk8">&#39;root&#39;</span><span class="mtk1">,</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1">})</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk15">export</span><span class="mtk1"> </span><span class="mtk4">class</span><span class="mtk1"> </span><span class="mtk10">UserService</span><span class="mtk1"> {</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk4">private</span><span class="mtk1"> </span><span class="mtk12">serviceUrl</span><span class="mtk1"> = </span><span class="mtk8">&#39;https://dummyjson.com/users&#39;</span><span class="mtk1">;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk4">constructor</span><span class="mtk1">(</span><span class="mtk4">private</span><span class="mtk1"> </span><span class="mtk12">http</span><span class="mtk1">: </span><span class="mtk10">HttpClient</span><span class="mtk1">) {}</span></span></span> <span class="grvsc-line"><span class="grvsc-source"></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk11">getUsers</span><span class="mtk1">(): </span><span class="mtk10">Observable</span><span class="mtk1">&lt;</span><span class="mtk10">User</span><span class="mtk1">[]&gt; {</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk15">return</span><span class="mtk1"> </span><span class="mtk4">this</span><span class="mtk1">.</span><span class="mtk12">http</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> .</span><span class="mtk11">get</span><span class="mtk1">(</span><span class="mtk4">this</span><span class="mtk1">.</span><span class="mtk12">serviceUrl</span><span class="mtk1">)</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> .</span><span class="mtk11">pipe</span><span class="mtk1">&lt;</span><span class="mtk10">User</span><span class="mtk1">[]&gt;(</span><span class="mtk11">map</span><span class="mtk1">((</span><span class="mtk12">data</span><span class="mtk1">: </span><span class="mtk10">any</span><span class="mtk1">) </span><span class="mtk4">=&gt;</span><span class="mtk1"> </span><span class="mtk12">data</span><span class="mtk1">.</span><span class="mtk12">users</span><span class="mtk1">));</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> }</span></span></span> <span class="grvsc-line"><span class="grvsc-source"></span></span> <span class="grvsc-line grvsc-line-highlighted"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk11">updateUser</span><span class="mtk1">(</span><span class="mtk12">user</span><span class="mtk1">: </span><span class="mtk10">User</span><span class="mtk1">): </span><span class="mtk10">Observable</span><span class="mtk1">&lt;</span><span class="mtk10">User</span><span class="mtk1">&gt; {</span></span></span> <span class="grvsc-line grvsc-line-highlighted"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk15">return</span><span class="mtk1"> </span><span class="mtk4">this</span><span class="mtk1">.</span><span class="mtk12">http</span><span class="mtk1">.</span><span class="mtk11">patch</span><span class="mtk1">&lt;</span><span class="mtk10">User</span><span class="mtk1">&gt;(</span><span class="mtk8">`</span><span class="mtk4">${this</span><span class="mtk1">.</span><span class="mtk12">serviceUrl</span><span class="mtk4">}</span><span class="mtk8">/</span><span class="mtk4">${</span><span class="mtk12">user</span><span class="mtk1">.</span><span class="mtk12">id</span><span class="mtk4">}</span><span class="mtk8">`</span><span class="mtk1">, </span><span class="mtk12">user</span><span class="mtk1">);</span></span></span> <span class="grvsc-line grvsc-line-highlighted"><span class="grvsc-source"><span class="mtk1"> }</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1">}</span></span></span></code></pre> <p>Now we can create a new <code>editRow</code> function in the <code>app.component.ts</code> class that subscribes to the <code>updateUser</code> API service:</p> <pre class="grvsc-container grvsc-has-line-highlighting default-dark" data-language="typescript" data-index="6"><code class="grvsc-code"><span class="grvsc-line"><span class="grvsc-source"><span class="mtk15">import</span><span class="mtk1"> { </span><span class="mtk12">Component</span><span class="mtk1">, </span><span class="mtk12">OnInit</span><span class="mtk1"> } </span><span class="mtk15">from</span><span class="mtk1"> </span><span class="mtk8">&#39;@angular/core&#39;</span><span class="mtk1">;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk15">import</span><span class="mtk1"> { </span><span class="mtk12">MatDialog</span><span class="mtk1"> } </span><span class="mtk15">from</span><span class="mtk1"> </span><span class="mtk8">&#39;@angular/material/dialog&#39;</span><span class="mtk1">;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk15">import</span><span class="mtk1"> { </span><span class="mtk12">MatTableDataSource</span><span class="mtk1"> } </span><span class="mtk15">from</span><span class="mtk1"> </span><span class="mtk8">&#39;@angular/material/table&#39;</span><span class="mtk1">;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk15">import</span><span class="mtk1"> { </span><span class="mtk12">User</span><span class="mtk1">, </span><span class="mtk12">UserColumns</span><span class="mtk1"> } </span><span class="mtk15">from</span><span class="mtk1"> </span><span class="mtk8">&#39;./model/user&#39;</span><span class="mtk1">;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk15">import</span><span class="mtk1"> { </span><span class="mtk12">UserService</span><span class="mtk1"> } </span><span class="mtk15">from</span><span class="mtk1"> </span><span class="mtk8">&#39;./services/user.service&#39;</span><span class="mtk1">;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1">@</span><span class="mtk11">Component</span><span class="mtk1">({</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">selector:</span><span class="mtk1"> </span><span class="mtk8">&#39;app-root&#39;</span><span class="mtk1">,</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">templateUrl:</span><span class="mtk1"> </span><span class="mtk8">&#39;./app.component.html&#39;</span><span class="mtk1">,</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">styleUrls:</span><span class="mtk1"> [</span><span class="mtk8">&#39;./app.component.scss&#39;</span><span class="mtk1">],</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1">})</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk15">export</span><span class="mtk1"> </span><span class="mtk4">class</span><span class="mtk1"> </span><span class="mtk10">AppComponent</span><span class="mtk1"> {</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">displayedColumns</span><span class="mtk1">: </span><span class="mtk10">string</span><span class="mtk1">[] = </span><span class="mtk12">UserColumns</span><span class="mtk1">.</span><span class="mtk11">map</span><span class="mtk1">((</span><span class="mtk12">col</span><span class="mtk1">) </span><span class="mtk4">=&gt;</span><span class="mtk1"> </span><span class="mtk12">col</span><span class="mtk1">.</span><span class="mtk12">key</span><span class="mtk1">);</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">columnsSchema</span><span class="mtk1">: </span><span class="mtk10">any</span><span class="mtk1"> = </span><span class="mtk12">UserColumns</span><span class="mtk1">;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">dataSource</span><span class="mtk1"> = </span><span class="mtk4">new</span><span class="mtk1"> </span><span class="mtk10">MatTableDataSource</span><span class="mtk1">&lt;</span><span class="mtk10">User</span><span class="mtk1">&gt;();</span></span></span> <span class="grvsc-line"><span class="grvsc-source"></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk4">constructor</span><span class="mtk1">(</span><span class="mtk4">public</span><span class="mtk1"> </span><span class="mtk12">dialog</span><span class="mtk1">: </span><span class="mtk10">MatDialog</span><span class="mtk1">, </span><span class="mtk4">private</span><span class="mtk1"> </span><span class="mtk12">userService</span><span class="mtk1">: </span><span class="mtk10">UserService</span><span class="mtk1">) {}</span></span></span> <span class="grvsc-line"><span class="grvsc-source"></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk11">ngOnInit</span><span class="mtk1">() {</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk4">this</span><span class="mtk1">.</span><span class="mtk12">userService</span><span class="mtk1">.</span><span class="mtk11">getUsers</span><span class="mtk1">().</span><span class="mtk11">subscribe</span><span class="mtk1">((</span><span class="mtk12">res</span><span class="mtk1">: </span><span class="mtk10">any</span><span class="mtk1">) </span><span class="mtk4">=&gt;</span><span class="mtk1"> {</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk4">this</span><span class="mtk1">.</span><span class="mtk12">dataSource</span><span class="mtk1">.</span><span class="mtk12">data</span><span class="mtk1"> = </span><span class="mtk12">res</span><span class="mtk1">;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> });</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> }</span></span></span> <span class="grvsc-line"><span class="grvsc-source"></span></span> <span class="grvsc-line grvsc-line-highlighted"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk11">editRow</span><span class="mtk1">(</span><span class="mtk12">row</span><span class="mtk1">: </span><span class="mtk10">User</span><span class="mtk1">) {</span></span></span> <span class="grvsc-line grvsc-line-highlighted"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk4">this</span><span class="mtk1">.</span><span class="mtk12">userService</span><span class="mtk1">.</span><span class="mtk11">updateUser</span><span class="mtk1">(</span><span class="mtk12">row</span><span class="mtk1">).</span><span class="mtk11">subscribe</span><span class="mtk1">(() </span><span class="mtk4">=&gt;</span><span class="mtk1"> </span><span class="mtk12">row</span><span class="mtk1">.</span><span class="mtk12">isEdit</span><span class="mtk1"> = </span><span class="mtk4">false</span><span class="mtk1">);</span></span></span> <span class="grvsc-line grvsc-line-highlighted"><span class="grvsc-source"><span class="mtk1"> }</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1">}</span></span></span></code></pre> <p>After subscribing to the service call, we can change the row to non-edit mode again <code>row.isEdit = false</code></p> <p>Lastly, in the <code>app.component.html</code> template, let’s add the <code>editRow</code> function to the button’s <code>click</code> event and pass it the element as a parameter:</p> <pre class="grvsc-container default-dark" data-language="html" data-index="7"><code class="grvsc-code"><span class="grvsc-line"><span class="grvsc-source"><span class="mtk17">&lt;</span><span class="mtk4">button</span><span class="mtk1"> </span><span class="mtk12">mat-button</span><span class="mtk1"> </span><span class="mtk12">(click)</span><span class="mtk1">=</span><span class="mtk8">&quot;editRow(element)&quot;</span><span class="mtk17">&gt;</span><span class="mtk1">Done</span><span class="mtk17">&lt;/</span><span class="mtk4">button</span><span class="mtk17">&gt;</span></span></span></code></pre> <p>Here is the final results in action:</p> <div data-youtube="OZkN7ZEqCBs"> <button>Play Example</button> </div> <h2 id="add-a-row-with-rest-api" style="position:relative;"><a href="#add-a-row-with-rest-api" aria-label="add a row with rest api permalink" class="anchor before"><svg aria-hidden="true" focusable="false" height="16" version="1.1" viewBox="0 0 16 16" width="16"><path fill-rule="evenodd" d="M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z"></path></svg></a>Add a row with REST API</h2> <p>Adding a new row requires a <code>post</code> API service with the user object passed as a parameter. Let’s add a new <code>addUser</code> function in <code>user.service.ts</code>:</p> <pre class="grvsc-container grvsc-has-line-highlighting default-dark" data-language="typescript" data-index="8"><code class="grvsc-code"><span class="grvsc-line"><span class="grvsc-source"><span class="mtk15">import</span><span class="mtk1"> { </span><span class="mtk12">Injectable</span><span class="mtk1"> } </span><span class="mtk15">from</span><span class="mtk1"> </span><span class="mtk8">&#39;@angular/core&#39;</span><span class="mtk1">;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk15">import</span><span class="mtk1"> { </span><span class="mtk12">HttpClient</span><span class="mtk1"> } </span><span class="mtk15">from</span><span class="mtk1"> </span><span class="mtk8">&#39;@angular/common/http&#39;</span><span class="mtk1">;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk15">import</span><span class="mtk1"> { </span><span class="mtk12">Observable</span><span class="mtk1"> } </span><span class="mtk15">from</span><span class="mtk1"> </span><span class="mtk8">&#39;rxjs&#39;</span><span class="mtk1">;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk15">import</span><span class="mtk1"> { </span><span class="mtk12">User</span><span class="mtk1"> } </span><span class="mtk15">from</span><span class="mtk1"> </span><span class="mtk8">&#39;../model/user&#39;</span><span class="mtk1">;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk15">import</span><span class="mtk1"> { </span><span class="mtk12">map</span><span class="mtk1"> } </span><span class="mtk15">from</span><span class="mtk1"> </span><span class="mtk8">&#39;rxjs/operators&#39;</span><span class="mtk1">;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1">@</span><span class="mtk11">Injectable</span><span class="mtk1">({</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">providedIn:</span><span class="mtk1"> </span><span class="mtk8">&#39;root&#39;</span><span class="mtk1">,</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1">})</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk15">export</span><span class="mtk1"> </span><span class="mtk4">class</span><span class="mtk1"> </span><span class="mtk10">UserService</span><span class="mtk1"> {</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk4">private</span><span class="mtk1"> </span><span class="mtk12">serviceUrl</span><span class="mtk1"> = </span><span class="mtk8">&#39;https://dummyjson.com/users&#39;</span><span class="mtk1">;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk4">constructor</span><span class="mtk1">(</span><span class="mtk4">private</span><span class="mtk1"> </span><span class="mtk12">http</span><span class="mtk1">: </span><span class="mtk10">HttpClient</span><span class="mtk1">) {}</span></span></span> <span class="grvsc-line"><span class="grvsc-source"></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk11">getUsers</span><span class="mtk1">(): </span><span class="mtk10">Observable</span><span class="mtk1">&lt;</span><span class="mtk10">User</span><span class="mtk1">[]&gt; {</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk15">return</span><span class="mtk1"> </span><span class="mtk4">this</span><span class="mtk1">.</span><span class="mtk12">http</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> .</span><span class="mtk11">get</span><span class="mtk1">(</span><span class="mtk4">this</span><span class="mtk1">.</span><span class="mtk12">serviceUrl</span><span class="mtk1">)</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> .</span><span class="mtk11">pipe</span><span class="mtk1">&lt;</span><span class="mtk10">User</span><span class="mtk1">[]&gt;(</span><span class="mtk11">map</span><span class="mtk1">((</span><span class="mtk12">data</span><span class="mtk1">: </span><span class="mtk10">any</span><span class="mtk1">) </span><span class="mtk4">=&gt;</span><span class="mtk1"> </span><span class="mtk12">data</span><span class="mtk1">.</span><span class="mtk12">users</span><span class="mtk1">));</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> }</span></span></span> <span class="grvsc-line"><span class="grvsc-source"></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk11">updateUser</span><span class="mtk1">(</span><span class="mtk12">user</span><span class="mtk1">: </span><span class="mtk10">User</span><span class="mtk1">): </span><span class="mtk10">Observable</span><span class="mtk1">&lt;</span><span class="mtk10">User</span><span class="mtk1">&gt; {</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk15">return</span><span class="mtk1"> </span><span class="mtk4">this</span><span class="mtk1">.</span><span class="mtk12">http</span><span class="mtk1">.</span><span class="mtk11">patch</span><span class="mtk1">&lt;</span><span class="mtk10">User</span><span class="mtk1">&gt;(</span><span class="mtk8">`</span><span class="mtk4">${this</span><span class="mtk1">.</span><span class="mtk12">serviceUrl</span><span class="mtk4">}</span><span class="mtk8">/</span><span class="mtk4">${</span><span class="mtk12">user</span><span class="mtk1">.</span><span class="mtk12">id</span><span class="mtk4">}</span><span class="mtk8">`</span><span class="mtk1">, </span><span class="mtk12">user</span><span class="mtk1">);</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> }</span></span></span> <span class="grvsc-line"><span class="grvsc-source"></span></span> <span class="grvsc-line grvsc-line-highlighted"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk11">addUser</span><span class="mtk1">(</span><span class="mtk12">user</span><span class="mtk1">: </span><span class="mtk10">User</span><span class="mtk1">): </span><span class="mtk10">Observable</span><span class="mtk1">&lt;</span><span class="mtk10">User</span><span class="mtk1">&gt; {</span></span></span> <span class="grvsc-line grvsc-line-highlighted"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk15">return</span><span class="mtk1"> </span><span class="mtk4">this</span><span class="mtk1">.</span><span class="mtk12">http</span><span class="mtk1">.</span><span class="mtk11">post</span><span class="mtk1">&lt;</span><span class="mtk10">User</span><span class="mtk1">&gt;(</span><span class="mtk8">`</span><span class="mtk4">${this</span><span class="mtk1">.</span><span class="mtk12">serviceUrl</span><span class="mtk4">}</span><span class="mtk8">/add`</span><span class="mtk1">, </span><span class="mtk12">user</span><span class="mtk1">);</span></span></span> <span class="grvsc-line grvsc-line-highlighted"><span class="grvsc-source"><span class="mtk1"> }</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1">}</span></span></span></code></pre> <p>In <code>app.component.ts</code>, we need to do two modifications:</p> <ol> <li>Create <code>addRow</code> function that inserts an empty object into the <code>dataSource</code> (similar to what we did in the <a href="https://muhimasri.com/blogs/add-and-remove-table-rows-using-angular-material/#add-row">second part</a>)</li> <li>Because the “Done” button will call the same function, we’ll update <code>editRow</code> function to support both adding and editing a row. We can know which service to trigger based on whether or not the id is zero.</li> </ol> <pre class="grvsc-container grvsc-has-line-highlighting default-dark" data-language="typescript" data-index="9"><code class="grvsc-code"><span class="grvsc-line"><span class="grvsc-source"><span class="mtk15">import</span><span class="mtk1"> { </span><span class="mtk12">Component</span><span class="mtk1">, </span><span class="mtk12">OnInit</span><span class="mtk1"> } </span><span class="mtk15">from</span><span class="mtk1"> </span><span class="mtk8">&#39;@angular/core&#39;</span><span class="mtk1">;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk15">import</span><span class="mtk1"> { </span><span class="mtk12">MatDialog</span><span class="mtk1"> } </span><span class="mtk15">from</span><span class="mtk1"> </span><span class="mtk8">&#39;@angular/material/dialog&#39;</span><span class="mtk1">;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk15">import</span><span class="mtk1"> { </span><span class="mtk12">MatTableDataSource</span><span class="mtk1"> } </span><span class="mtk15">from</span><span class="mtk1"> </span><span class="mtk8">&#39;@angular/material/table&#39;</span><span class="mtk1">;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk15">import</span><span class="mtk1"> { </span><span class="mtk12">User</span><span class="mtk1">, </span><span class="mtk12">UserColumns</span><span class="mtk1"> } </span><span class="mtk15">from</span><span class="mtk1"> </span><span class="mtk8">&#39;./model/user&#39;</span><span class="mtk1">;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk15">import</span><span class="mtk1"> { </span><span class="mtk12">UserService</span><span class="mtk1"> } </span><span class="mtk15">from</span><span class="mtk1"> </span><span class="mtk8">&#39;./services/user.service&#39;</span><span class="mtk1">;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1">@</span><span class="mtk11">Component</span><span class="mtk1">({</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">selector:</span><span class="mtk1"> </span><span class="mtk8">&#39;app-root&#39;</span><span class="mtk1">,</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">templateUrl:</span><span class="mtk1"> </span><span class="mtk8">&#39;./app.component.html&#39;</span><span class="mtk1">,</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">styleUrls:</span><span class="mtk1"> [</span><span class="mtk8">&#39;./app.component.scss&#39;</span><span class="mtk1">],</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1">})</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk15">export</span><span class="mtk1"> </span><span class="mtk4">class</span><span class="mtk1"> </span><span class="mtk10">AppComponent</span><span class="mtk1"> {</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">displayedColumns</span><span class="mtk1">: </span><span class="mtk10">string</span><span class="mtk1">[] = </span><span class="mtk12">UserColumns</span><span class="mtk1">.</span><span class="mtk11">map</span><span class="mtk1">((</span><span class="mtk12">col</span><span class="mtk1">) </span><span class="mtk4">=&gt;</span><span class="mtk1"> </span><span class="mtk12">col</span><span class="mtk1">.</span><span class="mtk12">key</span><span class="mtk1">);</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">columnsSchema</span><span class="mtk1">: </span><span class="mtk10">any</span><span class="mtk1"> = </span><span class="mtk12">UserColumns</span><span class="mtk1">;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">dataSource</span><span class="mtk1"> = </span><span class="mtk4">new</span><span class="mtk1"> </span><span class="mtk10">MatTableDataSource</span><span class="mtk1">&lt;</span><span class="mtk10">User</span><span class="mtk1">&gt;();</span></span></span> <span class="grvsc-line"><span class="grvsc-source"></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk4">constructor</span><span class="mtk1">(</span><span class="mtk4">public</span><span class="mtk1"> </span><span class="mtk12">dialog</span><span class="mtk1">: </span><span class="mtk10">MatDialog</span><span class="mtk1">, </span><span class="mtk4">private</span><span class="mtk1"> </span><span class="mtk12">userService</span><span class="mtk1">: </span><span class="mtk10">UserService</span><span class="mtk1">) {}</span></span></span> <span class="grvsc-line"><span class="grvsc-source"></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk11">ngOnInit</span><span class="mtk1">() {</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk4">this</span><span class="mtk1">.</span><span class="mtk12">userService</span><span class="mtk1">.</span><span class="mtk11">getUsers</span><span class="mtk1">().</span><span class="mtk11">subscribe</span><span class="mtk1">((</span><span class="mtk12">res</span><span class="mtk1">: </span><span class="mtk10">any</span><span class="mtk1">) </span><span class="mtk4">=&gt;</span><span class="mtk1"> {</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk4">this</span><span class="mtk1">.</span><span class="mtk12">dataSource</span><span class="mtk1">.</span><span class="mtk12">data</span><span class="mtk1"> = </span><span class="mtk12">res</span><span class="mtk1">;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> });</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> }</span></span></span> <span class="grvsc-line"><span class="grvsc-source"></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk11">editRow</span><span class="mtk1">(</span><span class="mtk12">row</span><span class="mtk1">: </span><span class="mtk10">User</span><span class="mtk1">) {</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk15">if</span><span class="mtk1"> (</span><span class="mtk12">row</span><span class="mtk1">.</span><span class="mtk12">id</span><span class="mtk1"> === </span><span class="mtk7">0</span><span class="mtk1">) {</span></span></span> <span class="grvsc-line grvsc-line-highlighted"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk4">this</span><span class="mtk1">.</span><span class="mtk12">userService</span><span class="mtk1">.</span><span class="mtk11">addUser</span><span class="mtk1">(</span><span class="mtk12">row</span><span class="mtk1">).</span><span class="mtk11">subscribe</span><span class="mtk1">((</span><span class="mtk12">newUser</span><span class="mtk1">: </span><span class="mtk10">User</span><span class="mtk1">) </span><span class="mtk4">=&gt;</span><span class="mtk1"> {</span></span></span> <span class="grvsc-line grvsc-line-highlighted"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">row</span><span class="mtk1">.</span><span class="mtk12">id</span><span class="mtk1"> = </span><span class="mtk12">newUser</span><span class="mtk1">.</span><span class="mtk12">id</span><span class="mtk1">;</span></span></span> <span class="grvsc-line grvsc-line-highlighted"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">row</span><span class="mtk1">.</span><span class="mtk12">isEdit</span><span class="mtk1"> = </span><span class="mtk4">false</span><span class="mtk1">;</span></span></span> <span class="grvsc-line grvsc-line-highlighted"><span class="grvsc-source"><span class="mtk1"> });</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> } </span><span class="mtk15">else</span><span class="mtk1"> {</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk4">this</span><span class="mtk1">.</span><span class="mtk12">userService</span><span class="mtk1">.</span><span class="mtk11">updateUser</span><span class="mtk1">(</span><span class="mtk12">row</span><span class="mtk1">).</span><span class="mtk11">subscribe</span><span class="mtk1">(() </span><span class="mtk4">=&gt;</span><span class="mtk1"> (</span><span class="mtk12">row</span><span class="mtk1">.</span><span class="mtk12">isEdit</span><span class="mtk1"> = </span><span class="mtk4">false</span><span class="mtk1">));</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> }</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> }</span></span></span> <span class="grvsc-line"><span class="grvsc-source"></span></span> <span class="grvsc-line grvsc-line-highlighted"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk11">addRow</span><span class="mtk1">() {</span></span></span> <span class="grvsc-line grvsc-line-highlighted"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk4">const</span><span class="mtk1"> </span><span class="mtk12">newRow</span><span class="mtk1">: </span><span class="mtk10">User</span><span class="mtk1"> = {</span></span></span> <span class="grvsc-line grvsc-line-highlighted"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">id:</span><span class="mtk1"> </span><span class="mtk7">0</span><span class="mtk1">,</span></span></span> <span class="grvsc-line grvsc-line-highlighted"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">firstName:</span><span class="mtk1"> </span><span class="mtk8">&#39;&#39;</span><span class="mtk1">,</span></span></span> <span class="grvsc-line grvsc-line-highlighted"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">lastName:</span><span class="mtk1"> </span><span class="mtk8">&#39;&#39;</span><span class="mtk1">,</span></span></span> <span class="grvsc-line grvsc-line-highlighted"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">email:</span><span class="mtk1"> </span><span class="mtk8">&#39;&#39;</span><span class="mtk1">,</span></span></span> <span class="grvsc-line grvsc-line-highlighted"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">birthDate:</span><span class="mtk1"> </span><span class="mtk8">&#39;&#39;</span><span class="mtk1">,</span></span></span> <span class="grvsc-line grvsc-line-highlighted"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">isEdit:</span><span class="mtk1"> </span><span class="mtk4">true</span><span class="mtk1">,</span></span></span> <span class="grvsc-line grvsc-line-highlighted"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">isSelected:</span><span class="mtk1"> </span><span class="mtk4">false</span><span class="mtk1">,</span></span></span> <span class="grvsc-line grvsc-line-highlighted"><span class="grvsc-source"><span class="mtk1"> };</span></span></span> <span class="grvsc-line grvsc-line-highlighted"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk4">this</span><span class="mtk1">.</span><span class="mtk12">dataSource</span><span class="mtk1">.</span><span class="mtk12">data</span><span class="mtk1"> = [</span><span class="mtk12">newRow</span><span class="mtk1">, ...</span><span class="mtk4">this</span><span class="mtk1">.</span><span class="mtk12">dataSource</span><span class="mtk1">.</span><span class="mtk12">data</span><span class="mtk1">];</span></span></span> <span class="grvsc-line grvsc-line-highlighted"><span class="grvsc-source"><span class="mtk1"> }</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1">}</span></span></span></code></pre> <p><em>After adding a row, we’re assigning it the new id to ensure that the row gets updated next time.</em></p> <p>Let’s take a look at what we have so far:</p> <div data-youtube="4qpwoC75fwE"> <button>Play Example</button> </div> <h2 id="delete-rows-with-rest-api" style="position:relative;"><a href="#delete-rows-with-rest-api" aria-label="delete rows with rest api permalink" class="anchor before"><svg aria-hidden="true" focusable="false" height="16" version="1.1" viewBox="0 0 16 16" width="16"><path fill-rule="evenodd" d="M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z"></path></svg></a>Delete rows with REST API</h2> <p>Deleting a row requires a <code>delete</code> API service with the id attached to the URL. Let’s add a new <code>deleteUser</code> function in the <code>user.service.ts</code> class:</p> <pre class="grvsc-container grvsc-has-line-highlighting default-dark" data-language="typescript" data-index="10"><code class="grvsc-code"><span class="grvsc-line"><span class="grvsc-source"><span class="mtk15">import</span><span class="mtk1"> { </span><span class="mtk12">Injectable</span><span class="mtk1"> } </span><span class="mtk15">from</span><span class="mtk1"> </span><span class="mtk8">&#39;@angular/core&#39;</span><span class="mtk1">;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk15">import</span><span class="mtk1"> { </span><span class="mtk12">HttpClient</span><span class="mtk1"> } </span><span class="mtk15">from</span><span class="mtk1"> </span><span class="mtk8">&#39;@angular/common/http&#39;</span><span class="mtk1">;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk15">import</span><span class="mtk1"> { </span><span class="mtk12">Observable</span><span class="mtk1"> } </span><span class="mtk15">from</span><span class="mtk1"> </span><span class="mtk8">&#39;rxjs&#39;</span><span class="mtk1">;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk15">import</span><span class="mtk1"> { </span><span class="mtk12">User</span><span class="mtk1"> } </span><span class="mtk15">from</span><span class="mtk1"> </span><span class="mtk8">&#39;../model/user&#39;</span><span class="mtk1">;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk15">import</span><span class="mtk1"> { </span><span class="mtk12">map</span><span class="mtk1"> } </span><span class="mtk15">from</span><span class="mtk1"> </span><span class="mtk8">&#39;rxjs/operators&#39;</span><span class="mtk1">;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1">@</span><span class="mtk11">Injectable</span><span class="mtk1">({</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">providedIn:</span><span class="mtk1"> </span><span class="mtk8">&#39;root&#39;</span><span class="mtk1">,</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1">})</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk15">export</span><span class="mtk1"> </span><span class="mtk4">class</span><span class="mtk1"> </span><span class="mtk10">UserService</span><span class="mtk1"> {</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk4">private</span><span class="mtk1"> </span><span class="mtk12">serviceUrl</span><span class="mtk1"> = </span><span class="mtk8">&#39;https://dummyjson.com/users&#39;</span><span class="mtk1">;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk4">constructor</span><span class="mtk1">(</span><span class="mtk4">private</span><span class="mtk1"> </span><span class="mtk12">http</span><span class="mtk1">: </span><span class="mtk10">HttpClient</span><span class="mtk1">) {}</span></span></span> <span class="grvsc-line"><span class="grvsc-source"></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk11">getUsers</span><span class="mtk1">(): </span><span class="mtk10">Observable</span><span class="mtk1">&lt;</span><span class="mtk10">User</span><span class="mtk1">[]&gt; {</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk15">return</span><span class="mtk1"> </span><span class="mtk4">this</span><span class="mtk1">.</span><span class="mtk12">http</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> .</span><span class="mtk11">get</span><span class="mtk1">(</span><span class="mtk4">this</span><span class="mtk1">.</span><span class="mtk12">serviceUrl</span><span class="mtk1">)</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> .</span><span class="mtk11">pipe</span><span class="mtk1">&lt;</span><span class="mtk10">User</span><span class="mtk1">[]&gt;(</span><span class="mtk11">map</span><span class="mtk1">((</span><span class="mtk12">data</span><span class="mtk1">: </span><span class="mtk10">any</span><span class="mtk1">) </span><span class="mtk4">=&gt;</span><span class="mtk1"> </span><span class="mtk12">data</span><span class="mtk1">.</span><span class="mtk12">users</span><span class="mtk1">));</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> }</span></span></span> <span class="grvsc-line"><span class="grvsc-source"></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk11">updateUser</span><span class="mtk1">(</span><span class="mtk12">user</span><span class="mtk1">: </span><span class="mtk10">User</span><span class="mtk1">): </span><span class="mtk10">Observable</span><span class="mtk1">&lt;</span><span class="mtk10">User</span><span class="mtk1">&gt; {</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk15">return</span><span class="mtk1"> </span><span class="mtk4">this</span><span class="mtk1">.</span><span class="mtk12">http</span><span class="mtk1">.</span><span class="mtk11">patch</span><span class="mtk1">&lt;</span><span class="mtk10">User</span><span class="mtk1">&gt;(</span><span class="mtk8">`</span><span class="mtk4">${this</span><span class="mtk1">.</span><span class="mtk12">serviceUrl</span><span class="mtk4">}</span><span class="mtk8">/</span><span class="mtk4">${</span><span class="mtk12">user</span><span class="mtk1">.</span><span class="mtk12">id</span><span class="mtk4">}</span><span class="mtk8">`</span><span class="mtk1">, </span><span class="mtk12">user</span><span class="mtk1">);</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> }</span></span></span> <span class="grvsc-line"><span class="grvsc-source"></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk11">addUser</span><span class="mtk1">(</span><span class="mtk12">user</span><span class="mtk1">: </span><span class="mtk10">User</span><span class="mtk1">): </span><span class="mtk10">Observable</span><span class="mtk1">&lt;</span><span class="mtk10">User</span><span class="mtk1">&gt; {</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk15">return</span><span class="mtk1"> </span><span class="mtk4">this</span><span class="mtk1">.</span><span class="mtk12">http</span><span class="mtk1">.</span><span class="mtk11">post</span><span class="mtk1">&lt;</span><span class="mtk10">User</span><span class="mtk1">&gt;(</span><span class="mtk8">`</span><span class="mtk4">${this</span><span class="mtk1">.</span><span class="mtk12">serviceUrl</span><span class="mtk4">}</span><span class="mtk8">/add`</span><span class="mtk1">, </span><span class="mtk12">user</span><span class="mtk1">);</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> }</span></span></span> <span class="grvsc-line"><span class="grvsc-source"></span></span> <span class="grvsc-line grvsc-line-highlighted"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk11">deleteUser</span><span class="mtk1">(</span><span class="mtk12">id</span><span class="mtk1">: </span><span class="mtk10">number</span><span class="mtk1">): </span><span class="mtk10">Observable</span><span class="mtk1">&lt;</span><span class="mtk10">User</span><span class="mtk1">&gt; {</span></span></span> <span class="grvsc-line grvsc-line-highlighted"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk15">return</span><span class="mtk1"> </span><span class="mtk4">this</span><span class="mtk1">.</span><span class="mtk12">http</span><span class="mtk1">.</span><span class="mtk11">delete</span><span class="mtk1">&lt;</span><span class="mtk10">User</span><span class="mtk1">&gt;(</span><span class="mtk8">`</span><span class="mtk4">${this</span><span class="mtk1">.</span><span class="mtk12">serviceUrl</span><span class="mtk4">}</span><span class="mtk8">/</span><span class="mtk4">${</span><span class="mtk12">id</span><span class="mtk4">}</span><span class="mtk8">`</span><span class="mtk1">);</span></span></span> <span class="grvsc-line grvsc-line-highlighted"><span class="grvsc-source"><span class="mtk1"> }</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1">}</span></span></span></code></pre> <p>In <code>app.component.ts</code>, we’ll create a <code>removeRow</code> function that triggers a delete service. Then, after deleting successfully, we can filter the <code>dataSource</code> to remove the deleted row from the table:</p> <pre class="grvsc-container grvsc-has-line-highlighting default-dark" data-language="typescript" data-index="11"><code class="grvsc-code"><span class="grvsc-line"><span class="grvsc-source"><span class="mtk15">import</span><span class="mtk1"> { </span><span class="mtk12">Component</span><span class="mtk1">, </span><span class="mtk12">OnInit</span><span class="mtk1"> } </span><span class="mtk15">from</span><span class="mtk1"> </span><span class="mtk8">&#39;@angular/core&#39;</span><span class="mtk1">;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk15">import</span><span class="mtk1"> { </span><span class="mtk12">MatDialog</span><span class="mtk1"> } </span><span class="mtk15">from</span><span class="mtk1"> </span><span class="mtk8">&#39;@angular/material/dialog&#39;</span><span class="mtk1">;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk15">import</span><span class="mtk1"> { </span><span class="mtk12">MatTableDataSource</span><span class="mtk1"> } </span><span class="mtk15">from</span><span class="mtk1"> </span><span class="mtk8">&#39;@angular/material/table&#39;</span><span class="mtk1">;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk15">import</span><span class="mtk1"> { </span><span class="mtk12">User</span><span class="mtk1">, </span><span class="mtk12">UserColumns</span><span class="mtk1"> } </span><span class="mtk15">from</span><span class="mtk1"> </span><span class="mtk8">&#39;./model/user&#39;</span><span class="mtk1">;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk15">import</span><span class="mtk1"> { </span><span class="mtk12">UserService</span><span class="mtk1"> } </span><span class="mtk15">from</span><span class="mtk1"> </span><span class="mtk8">&#39;./services/user.service&#39;</span><span class="mtk1">;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1">@</span><span class="mtk11">Component</span><span class="mtk1">({</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">selector:</span><span class="mtk1"> </span><span class="mtk8">&#39;app-root&#39;</span><span class="mtk1">,</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">templateUrl:</span><span class="mtk1"> </span><span class="mtk8">&#39;./app.component.html&#39;</span><span class="mtk1">,</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">styleUrls:</span><span class="mtk1"> [</span><span class="mtk8">&#39;./app.component.scss&#39;</span><span class="mtk1">],</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1">})</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk15">export</span><span class="mtk1"> </span><span class="mtk4">class</span><span class="mtk1"> </span><span class="mtk10">AppComponent</span><span class="mtk1"> {</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">displayedColumns</span><span class="mtk1">: </span><span class="mtk10">string</span><span class="mtk1">[] = </span><span class="mtk12">UserColumns</span><span class="mtk1">.</span><span class="mtk11">map</span><span class="mtk1">((</span><span class="mtk12">col</span><span class="mtk1">) </span><span class="mtk4">=&gt;</span><span class="mtk1"> </span><span class="mtk12">col</span><span class="mtk1">.</span><span class="mtk12">key</span><span class="mtk1">);</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">columnsSchema</span><span class="mtk1">: </span><span class="mtk10">any</span><span class="mtk1"> = </span><span class="mtk12">UserColumns</span><span class="mtk1">;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">dataSource</span><span class="mtk1"> = </span><span class="mtk4">new</span><span class="mtk1"> </span><span class="mtk10">MatTableDataSource</span><span class="mtk1">&lt;</span><span class="mtk10">User</span><span class="mtk1">&gt;();</span></span></span> <span class="grvsc-line"><span class="grvsc-source"></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk4">constructor</span><span class="mtk1">(</span><span class="mtk4">public</span><span class="mtk1"> </span><span class="mtk12">dialog</span><span class="mtk1">: </span><span class="mtk10">MatDialog</span><span class="mtk1">, </span><span class="mtk4">private</span><span class="mtk1"> </span><span class="mtk12">userService</span><span class="mtk1">: </span><span class="mtk10">UserService</span><span class="mtk1">) {}</span></span></span> <span class="grvsc-line"><span class="grvsc-source"></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk11">ngOnInit</span><span class="mtk1">() {</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk4">this</span><span class="mtk1">.</span><span class="mtk12">userService</span><span class="mtk1">.</span><span class="mtk11">getUsers</span><span class="mtk1">().</span><span class="mtk11">subscribe</span><span class="mtk1">((</span><span class="mtk12">res</span><span class="mtk1">: </span><span class="mtk10">any</span><span class="mtk1">) </span><span class="mtk4">=&gt;</span><span class="mtk1"> {</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk4">this</span><span class="mtk1">.</span><span class="mtk12">dataSource</span><span class="mtk1">.</span><span class="mtk12">data</span><span class="mtk1"> = </span><span class="mtk12">res</span><span class="mtk1">;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> });</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> }</span></span></span> <span class="grvsc-line"><span class="grvsc-source"></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk11">editRow</span><span class="mtk1">(</span><span class="mtk12">row</span><span class="mtk1">: </span><span class="mtk10">User</span><span class="mtk1">) {</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk15">if</span><span class="mtk1"> (</span><span class="mtk12">row</span><span class="mtk1">.</span><span class="mtk12">id</span><span class="mtk1"> === </span><span class="mtk7">0</span><span class="mtk1">) {</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk4">this</span><span class="mtk1">.</span><span class="mtk12">userService</span><span class="mtk1">.</span><span class="mtk11">addUser</span><span class="mtk1">(</span><span class="mtk12">row</span><span class="mtk1">).</span><span class="mtk11">subscribe</span><span class="mtk1">((</span><span class="mtk12">newUser</span><span class="mtk1">: </span><span class="mtk10">User</span><span class="mtk1">) </span><span class="mtk4">=&gt;</span><span class="mtk1"> {</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">row</span><span class="mtk1">.</span><span class="mtk12">id</span><span class="mtk1"> = </span><span class="mtk12">newUser</span><span class="mtk1">.</span><span class="mtk12">id</span><span class="mtk1">;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">row</span><span class="mtk1">.</span><span class="mtk12">isEdit</span><span class="mtk1"> = </span><span class="mtk4">false</span><span class="mtk1">;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> });</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> } </span><span class="mtk15">else</span><span class="mtk1"> {</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk4">this</span><span class="mtk1">.</span><span class="mtk12">userService</span><span class="mtk1">.</span><span class="mtk11">updateUser</span><span class="mtk1">(</span><span class="mtk12">row</span><span class="mtk1">).</span><span class="mtk11">subscribe</span><span class="mtk1">(() </span><span class="mtk4">=&gt;</span><span class="mtk1"> (</span><span class="mtk12">row</span><span class="mtk1">.</span><span class="mtk12">isEdit</span><span class="mtk1"> = </span><span class="mtk4">false</span><span class="mtk1">));</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> }</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> }</span></span></span> <span class="grvsc-line"><span class="grvsc-source"></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk11">addRow</span><span class="mtk1">() {</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk4">const</span><span class="mtk1"> </span><span class="mtk12">newRow</span><span class="mtk1">: </span><span class="mtk10">User</span><span class="mtk1"> = {</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">id:</span><span class="mtk1"> </span><span class="mtk7">0</span><span class="mtk1">,</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">firstName:</span><span class="mtk1"> </span><span class="mtk8">&#39;&#39;</span><span class="mtk1">,</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">lastName:</span><span class="mtk1"> </span><span class="mtk8">&#39;&#39;</span><span class="mtk1">,</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">email:</span><span class="mtk1"> </span><span class="mtk8">&#39;&#39;</span><span class="mtk1">,</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">birthDate:</span><span class="mtk1"> </span><span class="mtk8">&#39;&#39;</span><span class="mtk1">,</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">isEdit:</span><span class="mtk1"> </span><span class="mtk4">true</span><span class="mtk1">,</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">isSelected:</span><span class="mtk1"> </span><span class="mtk4">false</span><span class="mtk1">,</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> };</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk4">this</span><span class="mtk1">.</span><span class="mtk12">dataSource</span><span class="mtk1">.</span><span class="mtk12">data</span><span class="mtk1"> = [</span><span class="mtk12">newRow</span><span class="mtk1">, ...</span><span class="mtk4">this</span><span class="mtk1">.</span><span class="mtk12">dataSource</span><span class="mtk1">.</span><span class="mtk12">data</span><span class="mtk1">];</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> }</span></span></span> <span class="grvsc-line"><span class="grvsc-source"></span></span> <span class="grvsc-line grvsc-line-highlighted"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk11">removeRow</span><span class="mtk1">(</span><span class="mtk12">id</span><span class="mtk1">: </span><span class="mtk10">number</span><span class="mtk1">) {</span></span></span> <span class="grvsc-line grvsc-line-highlighted"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk4">this</span><span class="mtk1">.</span><span class="mtk12">userService</span><span class="mtk1">.</span><span class="mtk11">deleteUser</span><span class="mtk1">(</span><span class="mtk12">id</span><span class="mtk1">).</span><span class="mtk11">subscribe</span><span class="mtk1">(() </span><span class="mtk4">=&gt;</span><span class="mtk1"> {</span></span></span> <span class="grvsc-line grvsc-line-highlighted"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk4">this</span><span class="mtk1">.</span><span class="mtk12">dataSource</span><span class="mtk1">.</span><span class="mtk12">data</span><span class="mtk1"> = </span><span class="mtk4">this</span><span class="mtk1">.</span><span class="mtk12">dataSource</span><span class="mtk1">.</span><span class="mtk12">data</span><span class="mtk1">.</span><span class="mtk11">filter</span><span class="mtk1">(</span></span></span> <span class="grvsc-line grvsc-line-highlighted"><span class="grvsc-source"><span class="mtk1"> (</span><span class="mtk12">u</span><span class="mtk1">: </span><span class="mtk10">User</span><span class="mtk1">) </span><span class="mtk4">=&gt;</span><span class="mtk1"> </span><span class="mtk12">u</span><span class="mtk1">.</span><span class="mtk12">id</span><span class="mtk1"> !== </span><span class="mtk12">id</span></span></span> <span class="grvsc-line grvsc-line-highlighted"><span class="grvsc-source"><span class="mtk1"> );</span></span></span> <span class="grvsc-line grvsc-line-highlighted"><span class="grvsc-source"><span class="mtk1"> });</span></span></span> <span class="grvsc-line grvsc-line-highlighted"><span class="grvsc-source"><span class="mtk1"> }</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1">}</span></span></span></code></pre> <p>Below you can see how the <code>delete</code> REST is being triggered:</p> <div data-youtube="RggPoyuUO5Y"> <button>Play Example</button> </div> <p>We added a feature to remove multiple rows with a confirmation dialog in the <a href="https://muhimasri.com/blogs/add-and-remove-table-rows-using-angular-material/">last part</a>. Let’s modify it to make it work with an API call.</p> <p>Since <a href="https://dummyjson.com/">DummyJSON</a> doesn’t support multiple deletes (at least as far I know), we can use <code>forkJoin</code> from <code>Rxjs</code> lib to do the job. Let’s create a <code>deleteUsers</code> function that takes a list of users and generate multiple API calls:</p> <pre class="grvsc-container grvsc-has-line-highlighting default-dark" data-language="typescript" data-index="12"><code class="grvsc-code"><span class="grvsc-line"><span class="grvsc-source"><span class="mtk15">import</span><span class="mtk1"> { </span><span class="mtk12">Injectable</span><span class="mtk1"> } </span><span class="mtk15">from</span><span class="mtk1"> </span><span class="mtk8">&#39;@angular/core&#39;</span><span class="mtk1">;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk15">import</span><span class="mtk1"> { </span><span class="mtk12">HttpClient</span><span class="mtk1"> } </span><span class="mtk15">from</span><span class="mtk1"> </span><span class="mtk8">&#39;@angular/common/http&#39;</span><span class="mtk1">;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk15">import</span><span class="mtk1"> { </span><span class="mtk12">forkJoin</span><span class="mtk1">, </span><span class="mtk12">Observable</span><span class="mtk1"> } </span><span class="mtk15">from</span><span class="mtk1"> </span><span class="mtk8">&#39;rxjs&#39;</span><span class="mtk1">;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk15">import</span><span class="mtk1"> { </span><span class="mtk12">User</span><span class="mtk1"> } </span><span class="mtk15">from</span><span class="mtk1"> </span><span class="mtk8">&#39;../model/user&#39;</span><span class="mtk1">;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk15">import</span><span class="mtk1"> { </span><span class="mtk12">map</span><span class="mtk1"> } </span><span class="mtk15">from</span><span class="mtk1"> </span><span class="mtk8">&#39;rxjs/operators&#39;</span><span class="mtk1">;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1">@</span><span class="mtk11">Injectable</span><span class="mtk1">({</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">providedIn:</span><span class="mtk1"> </span><span class="mtk8">&#39;root&#39;</span><span class="mtk1">,</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1">})</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk15">export</span><span class="mtk1"> </span><span class="mtk4">class</span><span class="mtk1"> </span><span class="mtk10">UserService</span><span class="mtk1"> {</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk4">private</span><span class="mtk1"> </span><span class="mtk12">serviceUrl</span><span class="mtk1"> = </span><span class="mtk8">&#39;https://dummyjson.com/users&#39;</span><span class="mtk1">;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk4">constructor</span><span class="mtk1">(</span><span class="mtk4">private</span><span class="mtk1"> </span><span class="mtk12">http</span><span class="mtk1">: </span><span class="mtk10">HttpClient</span><span class="mtk1">) {}</span></span></span> <span class="grvsc-line"><span class="grvsc-source"></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk11">getUsers</span><span class="mtk1">(): </span><span class="mtk10">Observable</span><span class="mtk1">&lt;</span><span class="mtk10">User</span><span class="mtk1">[]&gt; {</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk15">return</span><span class="mtk1"> </span><span class="mtk4">this</span><span class="mtk1">.</span><span class="mtk12">http</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> .</span><span class="mtk11">get</span><span class="mtk1">(</span><span class="mtk4">this</span><span class="mtk1">.</span><span class="mtk12">serviceUrl</span><span class="mtk1">)</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> .</span><span class="mtk11">pipe</span><span class="mtk1">&lt;</span><span class="mtk10">User</span><span class="mtk1">[]&gt;(</span><span class="mtk11">map</span><span class="mtk1">((</span><span class="mtk12">data</span><span class="mtk1">: </span><span class="mtk10">any</span><span class="mtk1">) </span><span class="mtk4">=&gt;</span><span class="mtk1"> </span><span class="mtk12">data</span><span class="mtk1">.</span><span class="mtk12">users</span><span class="mtk1">));</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> }</span></span></span> <span class="grvsc-line"><span class="grvsc-source"></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk11">updateUser</span><span class="mtk1">(</span><span class="mtk12">user</span><span class="mtk1">: </span><span class="mtk10">User</span><span class="mtk1">): </span><span class="mtk10">Observable</span><span class="mtk1">&lt;</span><span class="mtk10">User</span><span class="mtk1">&gt; {</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk15">return</span><span class="mtk1"> </span><span class="mtk4">this</span><span class="mtk1">.</span><span class="mtk12">http</span><span class="mtk1">.</span><span class="mtk11">patch</span><span class="mtk1">&lt;</span><span class="mtk10">User</span><span class="mtk1">&gt;(</span><span class="mtk8">`</span><span class="mtk4">${this</span><span class="mtk1">.</span><span class="mtk12">serviceUrl</span><span class="mtk4">}</span><span class="mtk8">/</span><span class="mtk4">${</span><span class="mtk12">user</span><span class="mtk1">.</span><span class="mtk12">id</span><span class="mtk4">}</span><span class="mtk8">`</span><span class="mtk1">, </span><span class="mtk12">user</span><span class="mtk1">);</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> }</span></span></span> <span class="grvsc-line"><span class="grvsc-source"></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk11">addUser</span><span class="mtk1">(</span><span class="mtk12">user</span><span class="mtk1">: </span><span class="mtk10">User</span><span class="mtk1">): </span><span class="mtk10">Observable</span><span class="mtk1">&lt;</span><span class="mtk10">User</span><span class="mtk1">&gt; {</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk15">return</span><span class="mtk1"> </span><span class="mtk4">this</span><span class="mtk1">.</span><span class="mtk12">http</span><span class="mtk1">.</span><span class="mtk11">post</span><span class="mtk1">&lt;</span><span class="mtk10">User</span><span class="mtk1">&gt;(</span><span class="mtk8">`</span><span class="mtk4">${this</span><span class="mtk1">.</span><span class="mtk12">serviceUrl</span><span class="mtk4">}</span><span class="mtk8">/add`</span><span class="mtk1">, </span><span class="mtk12">user</span><span class="mtk1">);</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> }</span></span></span> <span class="grvsc-line"><span class="grvsc-source"></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk11">deleteUser</span><span class="mtk1">(</span><span class="mtk12">id</span><span class="mtk1">: </span><span class="mtk10">number</span><span class="mtk1">): </span><span class="mtk10">Observable</span><span class="mtk1">&lt;</span><span class="mtk10">User</span><span class="mtk1">&gt; {</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk15">return</span><span class="mtk1"> </span><span class="mtk4">this</span><span class="mtk1">.</span><span class="mtk12">http</span><span class="mtk1">.</span><span class="mtk11">delete</span><span class="mtk1">&lt;</span><span class="mtk10">User</span><span class="mtk1">&gt;(</span><span class="mtk8">`</span><span class="mtk4">${this</span><span class="mtk1">.</span><span class="mtk12">serviceUrl</span><span class="mtk4">}</span><span class="mtk8">/</span><span class="mtk4">${</span><span class="mtk12">id</span><span class="mtk4">}</span><span class="mtk8">`</span><span class="mtk1">);</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> }</span></span></span> <span class="grvsc-line"><span class="grvsc-source"></span></span> <span class="grvsc-line grvsc-line-highlighted"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk11">deleteUsers</span><span class="mtk1">(</span><span class="mtk12">users</span><span class="mtk1">: </span><span class="mtk10">User</span><span class="mtk1">[]): </span><span class="mtk10">Observable</span><span class="mtk1">&lt;</span><span class="mtk10">User</span><span class="mtk1">[]&gt; {</span></span></span> <span class="grvsc-line grvsc-line-highlighted"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk15">return</span><span class="mtk1"> </span><span class="mtk11">forkJoin</span><span class="mtk1">(</span></span></span> <span class="grvsc-line grvsc-line-highlighted"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">users</span><span class="mtk1">.</span><span class="mtk11">map</span><span class="mtk1">((</span><span class="mtk12">user</span><span class="mtk1">) </span><span class="mtk4">=&gt;</span></span></span> <span class="grvsc-line grvsc-line-highlighted"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk4">this</span><span class="mtk1">.</span><span class="mtk12">http</span><span class="mtk1">.</span><span class="mtk11">delete</span><span class="mtk1">&lt;</span><span class="mtk10">User</span><span class="mtk1">&gt;(</span><span class="mtk8">`</span><span class="mtk4">${this</span><span class="mtk1">.</span><span class="mtk12">serviceUrl</span><span class="mtk4">}</span><span class="mtk8">/</span><span class="mtk4">${</span><span class="mtk12">user</span><span class="mtk1">.</span><span class="mtk12">id</span><span class="mtk4">}</span><span class="mtk8">`</span><span class="mtk1">)</span></span></span> <span class="grvsc-line grvsc-line-highlighted"><span class="grvsc-source"><span class="mtk1"> )</span></span></span> <span class="grvsc-line grvsc-line-highlighted"><span class="grvsc-source"><span class="mtk1"> );</span></span></span> <span class="grvsc-line grvsc-line-highlighted"><span class="grvsc-source"><span class="mtk1"> }</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1">}</span></span></span></code></pre> <p>The function is very similar to the <code>deleteUser</code> one, except that we are using <code>map</code> to generate multiple http calls, and in return, we’ll get a list of observable users.</p> <p>In <code>app.component.ts</code>, we’ll keep the same function we did in the <a href="https://muhimasri.com/blogs/add-and-remove-table-rows-using-angular-material/#remove-multiple">last part</a> but enhance it to call the <code>deleteUsers</code> service when clicking the submit button in the dialog:</p> <pre class="grvsc-container grvsc-has-line-highlighting default-dark" data-language="typescript" data-index="13"><code class="grvsc-code"><span class="grvsc-line"><span class="grvsc-source"><span class="mtk15">import</span><span class="mtk1"> { </span><span class="mtk12">Component</span><span class="mtk1">, </span><span class="mtk12">OnInit</span><span class="mtk1"> } </span><span class="mtk15">from</span><span class="mtk1"> </span><span class="mtk8">&#39;@angular/core&#39;</span><span class="mtk1">;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk15">import</span><span class="mtk1"> { </span><span class="mtk12">MatDialog</span><span class="mtk1"> } </span><span class="mtk15">from</span><span class="mtk1"> </span><span class="mtk8">&#39;@angular/material/dialog&#39;</span><span class="mtk1">;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk15">import</span><span class="mtk1"> { </span><span class="mtk12">MatTableDataSource</span><span class="mtk1"> } </span><span class="mtk15">from</span><span class="mtk1"> </span><span class="mtk8">&#39;@angular/material/table&#39;</span><span class="mtk1">;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk15">import</span><span class="mtk1"> { </span><span class="mtk12">ConfirmDialogComponent</span><span class="mtk1"> } </span><span class="mtk15">from</span><span class="mtk1"> </span><span class="mtk8">&#39;./confirm-dialog/confirm-dialog.component&#39;</span><span class="mtk1">;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk15">import</span><span class="mtk1"> { </span><span class="mtk12">User</span><span class="mtk1">, </span><span class="mtk12">UserColumns</span><span class="mtk1"> } </span><span class="mtk15">from</span><span class="mtk1"> </span><span class="mtk8">&#39;./model/user&#39;</span><span class="mtk1">;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk15">import</span><span class="mtk1"> { </span><span class="mtk12">UserService</span><span class="mtk1"> } </span><span class="mtk15">from</span><span class="mtk1"> </span><span class="mtk8">&#39;./services/user.service&#39;</span><span class="mtk1">;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1">@</span><span class="mtk11">Component</span><span class="mtk1">({</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">selector:</span><span class="mtk1"> </span><span class="mtk8">&#39;app-root&#39;</span><span class="mtk1">,</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">templateUrl:</span><span class="mtk1"> </span><span class="mtk8">&#39;./app.component.html&#39;</span><span class="mtk1">,</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">styleUrls:</span><span class="mtk1"> [</span><span class="mtk8">&#39;./app.component.scss&#39;</span><span class="mtk1">],</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1">})</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk15">export</span><span class="mtk1"> </span><span class="mtk4">class</span><span class="mtk1"> </span><span class="mtk10">AppComponent</span><span class="mtk1"> {</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">displayedColumns</span><span class="mtk1">: </span><span class="mtk10">string</span><span class="mtk1">[] = </span><span class="mtk12">UserColumns</span><span class="mtk1">.</span><span class="mtk11">map</span><span class="mtk1">((</span><span class="mtk12">col</span><span class="mtk1">) </span><span class="mtk4">=&gt;</span><span class="mtk1"> </span><span class="mtk12">col</span><span class="mtk1">.</span><span class="mtk12">key</span><span class="mtk1">);</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">columnsSchema</span><span class="mtk1">: </span><span class="mtk10">any</span><span class="mtk1"> = </span><span class="mtk12">UserColumns</span><span class="mtk1">;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">dataSource</span><span class="mtk1"> = </span><span class="mtk4">new</span><span class="mtk1"> </span><span class="mtk10">MatTableDataSource</span><span class="mtk1">&lt;</span><span class="mtk10">User</span><span class="mtk1">&gt;();</span></span></span> <span class="grvsc-line"><span class="grvsc-source"></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk4">constructor</span><span class="mtk1">(</span><span class="mtk4">public</span><span class="mtk1"> </span><span class="mtk12">dialog</span><span class="mtk1">: </span><span class="mtk10">MatDialog</span><span class="mtk1">, </span><span class="mtk4">private</span><span class="mtk1"> </span><span class="mtk12">userService</span><span class="mtk1">: </span><span class="mtk10">UserService</span><span class="mtk1">) {}</span></span></span> <span class="grvsc-line"><span class="grvsc-source"></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk11">ngOnInit</span><span class="mtk1">() {</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk4">this</span><span class="mtk1">.</span><span class="mtk12">userService</span><span class="mtk1">.</span><span class="mtk11">getUsers</span><span class="mtk1">().</span><span class="mtk11">subscribe</span><span class="mtk1">((</span><span class="mtk12">res</span><span class="mtk1">: </span><span class="mtk10">any</span><span class="mtk1">) </span><span class="mtk4">=&gt;</span><span class="mtk1"> {</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk4">this</span><span class="mtk1">.</span><span class="mtk12">dataSource</span><span class="mtk1">.</span><span class="mtk12">data</span><span class="mtk1"> = </span><span class="mtk12">res</span><span class="mtk1">;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> });</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> }</span></span></span> <span class="grvsc-line"><span class="grvsc-source"></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk11">editRow</span><span class="mtk1">(</span><span class="mtk12">row</span><span class="mtk1">) {</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk15">if</span><span class="mtk1"> (</span><span class="mtk12">row</span><span class="mtk1">.</span><span class="mtk12">id</span><span class="mtk1"> === </span><span class="mtk7">0</span><span class="mtk1">) {</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk4">this</span><span class="mtk1">.</span><span class="mtk12">userService</span><span class="mtk1">.</span><span class="mtk11">addUser</span><span class="mtk1">(</span><span class="mtk12">row</span><span class="mtk1">).</span><span class="mtk11">subscribe</span><span class="mtk1">((</span><span class="mtk12">newUser</span><span class="mtk1">: </span><span class="mtk10">User</span><span class="mtk1">) </span><span class="mtk4">=&gt;</span><span class="mtk1"> {</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">row</span><span class="mtk1">.</span><span class="mtk12">id</span><span class="mtk1"> = </span><span class="mtk12">newUser</span><span class="mtk1">.</span><span class="mtk12">id</span><span class="mtk1">;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">row</span><span class="mtk1">.</span><span class="mtk12">isEdit</span><span class="mtk1"> = </span><span class="mtk4">false</span><span class="mtk1">;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> });</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> } </span><span class="mtk15">else</span><span class="mtk1"> {</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk4">this</span><span class="mtk1">.</span><span class="mtk12">userService</span><span class="mtk1">.</span><span class="mtk11">updateUser</span><span class="mtk1">(</span><span class="mtk12">row</span><span class="mtk1">).</span><span class="mtk11">subscribe</span><span class="mtk1">(() </span><span class="mtk4">=&gt;</span><span class="mtk1"> (</span><span class="mtk12">row</span><span class="mtk1">.</span><span class="mtk12">isEdit</span><span class="mtk1"> = </span><span class="mtk4">false</span><span class="mtk1">));</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> }</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> }</span></span></span> <span class="grvsc-line"><span class="grvsc-source"></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk11">addRow</span><span class="mtk1">() {</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk4">const</span><span class="mtk1"> </span><span class="mtk12">newRow</span><span class="mtk1">: </span><span class="mtk10">User</span><span class="mtk1"> = {</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">id:</span><span class="mtk1"> </span><span class="mtk7">0</span><span class="mtk1">,</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">firstName:</span><span class="mtk1"> </span><span class="mtk8">&#39;&#39;</span><span class="mtk1">,</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">lastName:</span><span class="mtk1"> </span><span class="mtk8">&#39;&#39;</span><span class="mtk1">,</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">email:</span><span class="mtk1"> </span><span class="mtk8">&#39;&#39;</span><span class="mtk1">,</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">birthDate:</span><span class="mtk1"> </span><span class="mtk4">null</span><span class="mtk1">,</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">isEdit:</span><span class="mtk1"> </span><span class="mtk4">true</span><span class="mtk1">,</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">isSelected:</span><span class="mtk1"> </span><span class="mtk4">false</span><span class="mtk1">,</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> };</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk4">this</span><span class="mtk1">.</span><span class="mtk12">dataSource</span><span class="mtk1">.</span><span class="mtk12">data</span><span class="mtk1"> = [</span><span class="mtk12">newRow</span><span class="mtk1">, ...</span><span class="mtk4">this</span><span class="mtk1">.</span><span class="mtk12">dataSource</span><span class="mtk1">.</span><span class="mtk12">data</span><span class="mtk1">];</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> }</span></span></span> <span class="grvsc-line"><span class="grvsc-source"></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk11">removeRow</span><span class="mtk1">(</span><span class="mtk12">id</span><span class="mtk1">) {</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk4">this</span><span class="mtk1">.</span><span class="mtk12">userService</span><span class="mtk1">.</span><span class="mtk11">deleteUser</span><span class="mtk1">(</span><span class="mtk12">id</span><span class="mtk1">).</span><span class="mtk11">subscribe</span><span class="mtk1">(() </span><span class="mtk4">=&gt;</span><span class="mtk1"> {</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk4">this</span><span class="mtk1">.</span><span class="mtk12">dataSource</span><span class="mtk1">.</span><span class="mtk12">data</span><span class="mtk1"> = </span><span class="mtk4">this</span><span class="mtk1">.</span><span class="mtk12">dataSource</span><span class="mtk1">.</span><span class="mtk12">data</span><span class="mtk1">.</span><span class="mtk11">filter</span><span class="mtk1">(</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> (</span><span class="mtk12">u</span><span class="mtk1">: </span><span class="mtk10">User</span><span class="mtk1">) </span><span class="mtk4">=&gt;</span><span class="mtk1"> </span><span class="mtk12">u</span><span class="mtk1">.</span><span class="mtk12">id</span><span class="mtk1"> !== </span><span class="mtk12">id</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> );</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> });</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> }</span></span></span> <span class="grvsc-line"><span class="grvsc-source"></span></span> <span class="grvsc-line grvsc-line-highlighted"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk11">removeSelectedRows</span><span class="mtk1">() {</span></span></span> <span class="grvsc-line grvsc-line-highlighted"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk4">const</span><span class="mtk1"> </span><span class="mtk12">users</span><span class="mtk1"> = </span><span class="mtk4">this</span><span class="mtk1">.</span><span class="mtk12">dataSource</span><span class="mtk1">.</span><span class="mtk12">data</span><span class="mtk1">.</span><span class="mtk11">filter</span><span class="mtk1">((</span><span class="mtk12">u</span><span class="mtk1">: </span><span class="mtk10">User</span><span class="mtk1">) </span><span class="mtk4">=&gt;</span><span class="mtk1"> </span><span class="mtk12">u</span><span class="mtk1">.</span><span class="mtk12">isSelected</span><span class="mtk1">);</span></span></span> <span class="grvsc-line grvsc-line-highlighted"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk4">this</span><span class="mtk1">.</span><span class="mtk12">dialog</span></span></span> <span class="grvsc-line grvsc-line-highlighted"><span class="grvsc-source"><span class="mtk1"> .</span><span class="mtk11">open</span><span class="mtk1">(</span><span class="mtk12">ConfirmDialogComponent</span><span class="mtk1">)</span></span></span> <span class="grvsc-line grvsc-line-highlighted"><span class="grvsc-source"><span class="mtk1"> .</span><span class="mtk11">afterClosed</span><span class="mtk1">()</span></span></span> <span class="grvsc-line grvsc-line-highlighted"><span class="grvsc-source"><span class="mtk1"> .</span><span class="mtk11">subscribe</span><span class="mtk1">((</span><span class="mtk12">confirm</span><span class="mtk1">) </span><span class="mtk4">=&gt;</span><span class="mtk1"> {</span></span></span> <span class="grvsc-line grvsc-line-highlighted"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk15">if</span><span class="mtk1"> (</span><span class="mtk12">confirm</span><span class="mtk1">) {</span></span></span> <span class="grvsc-line grvsc-line-highlighted"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk4">this</span><span class="mtk1">.</span><span class="mtk12">userService</span><span class="mtk1">.</span><span class="mtk11">deleteUsers</span><span class="mtk1">(</span><span class="mtk12">users</span><span class="mtk1">).</span><span class="mtk11">subscribe</span><span class="mtk1">(() </span><span class="mtk4">=&gt;</span><span class="mtk1"> {</span></span></span> <span class="grvsc-line grvsc-line-highlighted"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk4">this</span><span class="mtk1">.</span><span class="mtk12">dataSource</span><span class="mtk1">.</span><span class="mtk12">data</span><span class="mtk1"> = </span><span class="mtk4">this</span><span class="mtk1">.</span><span class="mtk12">dataSource</span><span class="mtk1">.</span><span class="mtk12">data</span><span class="mtk1">.</span><span class="mtk11">filter</span><span class="mtk1">(</span></span></span> <span class="grvsc-line grvsc-line-highlighted"><span class="grvsc-source"><span class="mtk1"> (</span><span class="mtk12">u</span><span class="mtk1">: </span><span class="mtk10">User</span><span class="mtk1">) </span><span class="mtk4">=&gt;</span><span class="mtk1"> !</span><span class="mtk12">u</span><span class="mtk1">.</span><span class="mtk12">isSelected</span></span></span> <span class="grvsc-line grvsc-line-highlighted"><span class="grvsc-source"><span class="mtk1"> );</span></span></span> <span class="grvsc-line grvsc-line-highlighted"><span class="grvsc-source"><span class="mtk1"> });</span></span></span> <span class="grvsc-line grvsc-line-highlighted"><span class="grvsc-source"><span class="mtk1"> }</span></span></span> <span class="grvsc-line grvsc-line-highlighted"><span class="grvsc-source"><span class="mtk1"> });</span></span></span> <span class="grvsc-line grvsc-line-highlighted"><span class="grvsc-source"><span class="mtk1"> }</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1">}</span></span></span></code></pre> <p>Here is how deleting multiple rows looks like:</p> <div data-youtube="Ar02RH6jhj0"> <button>Play Example</button> </div> <h2 id="summary" style="position:relative;"><a href="#summary" aria-label="summary permalink" class="anchor before"><svg aria-hidden="true" focusable="false" height="16" version="1.1" viewBox="0 0 16 16" width="16"><path fill-rule="evenodd" d="M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z"></path></svg></a>Summary</h2> <p>If you made it to this section, pat yourself on the back! You just learned how to:</p> <ul> <li>Create a User model and interface</li> <li>Create a service layer with different API calls</li> <li>Load, add, edit and delete rows with Material table and API services</li> </ul> <p>You can access the <a href="https://github.com/muhimasri/angular-editable-table">complete repository here</a>.</p> <p>Bye for now 👋</p> <style class="grvsc-styles"> .grvsc-container { overflow: auto; position: relative; -webkit-overflow-scrolling: touch; padding-top: 1rem; padding-top: var(--grvsc-padding-top, var(--grvsc-padding-v, 1rem)); padding-bottom: 1rem; padding-bottom: var(--grvsc-padding-bottom, var(--grvsc-padding-v, 1rem)); border-radius: 8px; border-radius: var(--grvsc-border-radius, 8px); font-feature-settings: normal; line-height: 1.4; } .grvsc-code { display: table; } .grvsc-line { display: table-row; box-sizing: border-box; width: 100%; position: relative; } .grvsc-line > * { position: relative; } .grvsc-gutter-pad { display: table-cell; padding-left: 0.75rem; padding-left: calc(var(--grvsc-padding-left, var(--grvsc-padding-h, 1.5rem)) / 2); } .grvsc-gutter { display: table-cell; -webkit-user-select: none; -moz-user-select: none; user-select: none; } .grvsc-gutter::before { content: attr(data-content); } .grvsc-source { display: table-cell; padding-left: 1.5rem; padding-left: var(--grvsc-padding-left, var(--grvsc-padding-h, 1.5rem)); padding-right: 1.5rem; padding-right: var(--grvsc-padding-right, var(--grvsc-padding-h, 1.5rem)); } .grvsc-source:empty::after { content: ' '; -webkit-user-select: none; -moz-user-select: none; user-select: none; } .grvsc-gutter + .grvsc-source { padding-left: 0.75rem; padding-left: calc(var(--grvsc-padding-left, var(--grvsc-padding-h, 1.5rem)) / 2); } /* Line transformer styles */ .grvsc-has-line-highlighting > .grvsc-code > .grvsc-line::before { content: ' '; position: absolute; width: 100%; } .grvsc-line-diff-add::before { background-color: var(--grvsc-line-diff-add-background-color, rgba(0, 255, 60, 0.2)); } .grvsc-line-diff-del::before { background-color: var(--grvsc-line-diff-del-background-color, rgba(255, 0, 20, 0.2)); } .grvsc-line-number { padding: 0 2px; text-align: right; opacity: 0.7; } .default-dark { background-color: #1E1E1E; color: #D4D4D4; } .default-dark .mtk15 { color: #C586C0; } .default-dark .mtk1 { color: #D4D4D4; } .default-dark .mtk4 { color: #569CD6; } .default-dark .mtk10 { color: #4EC9B0; } .default-dark .mtk12 { color: #9CDCFE; } .default-dark .mtk8 { color: #CE9178; } .default-dark .mtk11 { color: #DCDCAA; } .default-dark .mtk17 { color: #808080; } .default-dark .mtk7 { color: #B5CEA8; } .default-dark .grvsc-line-highlighted::before { background-color: var(--grvsc-line-highlighted-background-color, rgba(255, 255, 255, 0.1)); box-shadow: inset var(--grvsc-line-highlighted-border-width, 4px) 0 0 0 var(--grvsc-line-highlighted-border-color, rgba(255, 255, 255, 0.5)); } </style><![CDATA[[Part 2] Add and Remove Table Rows using Angular Material]]>https://muhimasri.comadd-and-remove-table-rows-using-angular-materialhttps://muhimasri.comadd-and-remove-table-rows-using-angular-material<p><a href="https://muhimasri.com/blogs/create-an-editable-dynamic-table-using-angular-material/">In the previous part</a>, we did a deep dive into editing a table and creating a dynamic schema to generate different form elements for the user input such as text, number, date…</p> <p>In this part, we will go through the required steps to add and remove multiple rows with a confirmation dialog. The final results will look as follows:</p> <div data-youtube="YU8p3L3VbGo"> <button>Play Example</button> </div> <p><em>As we continue building upon the same code from previous parts in this series, it’s recommended that you go through these tutorials from the beginning to understand how the code structure works as we will not be explaining it. You can navigate to any part using the table of contents.</em></p> <p>Before we begin, the <a href="https://github.com/muhimasri/angular-editable-table">complete repository is accessible here</a> and a working example is available below:</p> <div data-stackblitz="angular-editable-table-part-2"> <button>Run Code</button> </div> <h2 id="add-a-new-row" style="position:relative;"><a href="#add-a-new-row" aria-label="add a new row permalink" class="anchor before"><svg aria-hidden="true" focusable="false" height="16" version="1.1" viewBox="0 0 16 16" width="16"><path fill-rule="evenodd" d="M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z"></path></svg></a>Add a new row</h2> <p>Adding a new row is as simple as inserting a new object to the <code>dataSource</code> array.</p> <p><em>A quick recap from the previous tutorial, <code>dataSource</code> is the primary data list used in the table element. We assign it directly to the <code>USER_DATA</code> array, which is just static dummy data. That will come from the back-end via an API call in a real-life scenario.</em></p> <p>Let’s go through the steps required:</p> <ol> <li>Add a new <code>button</code> with a <code>click</code> event just before the <code>table</code> component. We will wrap it in an <code>article</code> container to be able to add more action buttons in later steps:</li> </ol> <pre class="grvsc-container grvsc-has-line-highlighting default-dark" data-language="html" data-index="0"><code class="grvsc-code"><span class="grvsc-line grvsc-line-highlighted"><span class="grvsc-source"><span class="mtk17">&lt;</span><span class="mtk4">article</span><span class="mtk1"> </span><span class="mtk12">class</span><span class="mtk1">=</span><span class="mtk8">&quot;table-header&quot;</span><span class="mtk17">&gt;</span></span></span> <span class="grvsc-line grvsc-line-highlighted"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk17">&lt;</span><span class="mtk4">button</span><span class="mtk1"> </span><span class="mtk12">class</span><span class="mtk1">=</span><span class="mtk8">&quot;button-add-row&quot;</span><span class="mtk1"> </span><span class="mtk12">mat-button</span><span class="mtk1"> </span><span class="mtk12">(click)</span><span class="mtk1">=</span><span class="mtk8">&quot;addRow()&quot;</span><span class="mtk17">&gt;</span><span class="mtk1">Add Row</span><span class="mtk17">&lt;/</span><span class="mtk4">button</span><span class="mtk17">&gt;</span></span></span> <span class="grvsc-line grvsc-line-highlighted"><span class="grvsc-source"><span class="mtk17">&lt;/</span><span class="mtk4">article</span><span class="mtk17">&gt;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk17">&lt;</span><span class="mtk4">table</span><span class="mtk1"> </span><span class="mtk12">mat-table</span><span class="mtk1"> </span><span class="mtk12">[dataSource]</span><span class="mtk1">=</span><span class="mtk8">&quot;dataSource&quot;</span><span class="mtk17">&gt;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk17">&lt;</span><span class="mtk4">ng-container</span><span class="mtk1"> </span><span class="mtk12">[matColumnDef]</span><span class="mtk1">=</span><span class="mtk8">&quot;col.key&quot;</span><span class="mtk1"> </span><span class="mtk12">*ngFor</span><span class="mtk1">=</span><span class="mtk8">&quot;let col of columnsSchema&quot;</span><span class="mtk17">&gt;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk17">&lt;</span><span class="mtk4">th</span><span class="mtk1"> </span><span class="mtk12">mat-header-cell</span><span class="mtk1"> </span><span class="mtk12">*matHeaderCellDef</span><span class="mtk17">&gt;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> {{ col.label }}</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk17">&lt;/</span><span class="mtk4">th</span><span class="mtk17">&gt;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk17">&lt;</span><span class="mtk4">td</span><span class="mtk1"> </span><span class="mtk12">mat-cell</span><span class="mtk1"> </span><span class="mtk12">*matCellDef</span><span class="mtk1">=</span><span class="mtk8">&quot;let element&quot;</span><span class="mtk17">&gt;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk17">&lt;</span><span class="mtk4">div</span><span class="mtk1"> </span><span class="mtk12">[ngSwitch]</span><span class="mtk1">=</span><span class="mtk8">&quot;col.type&quot;</span><span class="mtk1"> </span><span class="mtk12">*ngIf</span><span class="mtk1">=</span><span class="mtk8">&quot;!element.isEdit&quot;</span><span class="mtk17">&gt;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk17">&lt;</span><span class="mtk4">div</span><span class="mtk1"> </span><span class="mtk12">class</span><span class="mtk1">=</span><span class="mtk8">&quot;btn-edit&quot;</span><span class="mtk1"> </span><span class="mtk12">*ngSwitchCase</span><span class="mtk1">=</span><span class="mtk8">&quot;&#39;isEdit&#39;&quot;</span><span class="mtk17">&gt;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk17">&lt;</span><span class="mtk4">button</span><span class="mtk1"> </span><span class="mtk12">mat-button</span><span class="mtk1"> </span><span class="mtk12">(click)</span><span class="mtk1">=</span><span class="mtk8">&quot;element.isEdit = !element.isEdit&quot;</span><span class="mtk17">&gt;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> Edit</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk17">&lt;/</span><span class="mtk4">button</span><span class="mtk17">&gt;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk17">&lt;/</span><span class="mtk4">div</span><span class="mtk17">&gt;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk17">&lt;</span><span class="mtk4">span</span><span class="mtk1"> </span><span class="mtk12">*ngSwitchDefault</span><span class="mtk17">&gt;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> {{ element[col.key] }}</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk17">&lt;/</span><span class="mtk4">span</span><span class="mtk17">&gt;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk17">&lt;/</span><span class="mtk4">div</span><span class="mtk17">&gt;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk17">&lt;</span><span class="mtk4">div</span><span class="mtk1"> </span><span class="mtk12">[ngSwitch]</span><span class="mtk1">=</span><span class="mtk8">&quot;col.type&quot;</span><span class="mtk1"> </span><span class="mtk12">*ngIf</span><span class="mtk1">=</span><span class="mtk8">&quot;element.isEdit&quot;</span><span class="mtk17">&gt;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk17">&lt;</span><span class="mtk4">div</span><span class="mtk1"> </span><span class="mtk12">class</span><span class="mtk1">=</span><span class="mtk8">&quot;btn-edit&quot;</span><span class="mtk1"> </span><span class="mtk12">*ngSwitchCase</span><span class="mtk1">=</span><span class="mtk8">&quot;&#39;isEdit&#39;&quot;</span><span class="mtk17">&gt;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk17">&lt;</span><span class="mtk4">button</span><span class="mtk1"> </span><span class="mtk12">mat-button</span><span class="mtk1"> </span><span class="mtk12">(click)</span><span class="mtk1">=</span><span class="mtk8">&quot;element.isEdit = !element.isEdit&quot;</span><span class="mtk17">&gt;</span><span class="mtk1">Done</span><span class="mtk17">&lt;/</span><span class="mtk4">button</span><span class="mtk17">&gt;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk17">&lt;/</span><span class="mtk4">div</span><span class="mtk17">&gt;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk17">&lt;</span><span class="mtk4">mat-form-field</span><span class="mtk1"> </span><span class="mtk12">*ngSwitchCase</span><span class="mtk1">=</span><span class="mtk8">&quot;&#39;date&#39;&quot;</span><span class="mtk1"> </span><span class="mtk12">appearance</span><span class="mtk1">=</span><span class="mtk8">&quot;fill&quot;</span><span class="mtk17">&gt;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk17">&lt;</span><span class="mtk4">mat-label</span><span class="mtk17">&gt;</span><span class="mtk1">Choose a date</span><span class="mtk17">&lt;/</span><span class="mtk4">mat-label</span><span class="mtk17">&gt;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk17">&lt;</span><span class="mtk4">input</span><span class="mtk1"> </span><span class="mtk12">matInput</span><span class="mtk1"> </span><span class="mtk12">[matDatepicker]</span><span class="mtk1">=</span><span class="mtk8">&quot;picker&quot;</span><span class="mtk1"> </span><span class="mtk12">[(ngModel)]</span><span class="mtk1">=</span><span class="mtk8">&quot;element[col.key]&quot;</span><span class="mtk1"> </span><span class="mtk17">/&gt;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk17">&lt;</span><span class="mtk4">mat-datepicker-toggle</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">matSuffix</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">[for]</span><span class="mtk1">=</span><span class="mtk8">&quot;picker&quot;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk17">&gt;&lt;/</span><span class="mtk4">mat-datepicker-toggle</span><span class="mtk17">&gt;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk17">&lt;</span><span class="mtk4">mat-datepicker</span><span class="mtk1"> </span><span class="mtk12">#picker</span><span class="mtk17">&gt;&lt;/</span><span class="mtk4">mat-datepicker</span><span class="mtk17">&gt;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk17">&lt;/</span><span class="mtk4">mat-form-field</span><span class="mtk17">&gt;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk17">&lt;</span><span class="mtk4">mat-form-field</span><span class="mtk1"> </span><span class="mtk12">*ngSwitchDefault</span><span class="mtk17">&gt;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk17">&lt;</span><span class="mtk4">input</span><span class="mtk1"> </span><span class="mtk12">[type]</span><span class="mtk1">=</span><span class="mtk8">&quot;col.type&quot;</span><span class="mtk1"> </span><span class="mtk12">matInput</span><span class="mtk1"> </span><span class="mtk12">[(ngModel)]</span><span class="mtk1">=</span><span class="mtk8">&quot;element[col.key]&quot;</span><span class="mtk1"> </span><span class="mtk17">/&gt;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk17">&lt;/</span><span class="mtk4">mat-form-field</span><span class="mtk17">&gt;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk17">&lt;/</span><span class="mtk4">div</span><span class="mtk17">&gt;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk17">&lt;/</span><span class="mtk4">td</span><span class="mtk17">&gt;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk17">&lt;/</span><span class="mtk4">ng-container</span><span class="mtk17">&gt;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk17">&lt;</span><span class="mtk4">tr</span><span class="mtk1"> </span><span class="mtk12">mat-header-row</span><span class="mtk1"> </span><span class="mtk12">*matHeaderRowDef</span><span class="mtk1">=</span><span class="mtk8">&quot;displayedColumns&quot;</span><span class="mtk17">&gt;&lt;/</span><span class="mtk4">tr</span><span class="mtk17">&gt;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk17">&lt;</span><span class="mtk4">tr</span><span class="mtk1"> </span><span class="mtk12">mat-row</span><span class="mtk1"> </span><span class="mtk12">*matRowDef</span><span class="mtk1">=</span><span class="mtk8">&quot;let row; columns: displayedColumns&quot;</span><span class="mtk17">&gt;&lt;/</span><span class="mtk4">tr</span><span class="mtk17">&gt;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk17">&lt;/</span><span class="mtk4">table</span><span class="mtk17">&gt;</span></span></span></code></pre> <ol start="2"> <li>Implement <code>addRow</code> function to insert a new object into the <code>dataSource</code> array with empty values. Make sure it contains the <code>isEdit</code> property that is set to true to make it editable for the user:</li> </ol> <pre class="grvsc-container grvsc-has-line-highlighting default-dark" data-language="typescript" data-index="1"><code class="grvsc-code"><span class="grvsc-line"><span class="grvsc-source"><span class="mtk15">import</span><span class="mtk1"> { </span><span class="mtk12">Component</span><span class="mtk1"> } </span><span class="mtk15">from</span><span class="mtk1"> </span><span class="mtk8">&#39;@angular/core&#39;</span><span class="mtk1">;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk4">const</span><span class="mtk1"> </span><span class="mtk12">USER_DATA</span><span class="mtk1"> = [</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> {</span><span class="mtk8">&quot;name&quot;</span><span class="mtk12">:</span><span class="mtk1"> </span><span class="mtk8">&quot;John Smith&quot;</span><span class="mtk1">, </span><span class="mtk8">&quot;occupation&quot;</span><span class="mtk12">:</span><span class="mtk1"> </span><span class="mtk8">&quot;Advisor&quot;</span><span class="mtk1">, </span><span class="mtk8">&quot;dateOfBirth&quot;</span><span class="mtk12">:</span><span class="mtk1"> </span><span class="mtk8">&quot;1984-05-05&quot;</span><span class="mtk1">, </span><span class="mtk8">&quot;age&quot;</span><span class="mtk12">:</span><span class="mtk1"> </span><span class="mtk7">36</span><span class="mtk1">},</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> {</span><span class="mtk8">&quot;name&quot;</span><span class="mtk12">:</span><span class="mtk1"> </span><span class="mtk8">&quot;Muhi Masri&quot;</span><span class="mtk1">, </span><span class="mtk8">&quot;occupation&quot;</span><span class="mtk12">:</span><span class="mtk1"> </span><span class="mtk8">&quot;Developer&quot;</span><span class="mtk1">, </span><span class="mtk8">&quot;dateOfBirth&quot;</span><span class="mtk12">:</span><span class="mtk1"> </span><span class="mtk8">&quot;1992-02-02&quot;</span><span class="mtk1">, </span><span class="mtk8">&quot;age&quot;</span><span class="mtk12">:</span><span class="mtk1"> </span><span class="mtk7">28</span><span class="mtk1">},</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> {</span><span class="mtk8">&quot;name&quot;</span><span class="mtk12">:</span><span class="mtk1"> </span><span class="mtk8">&quot;Peter Adams&quot;</span><span class="mtk1">, </span><span class="mtk8">&quot;occupation&quot;</span><span class="mtk12">:</span><span class="mtk1"> </span><span class="mtk8">&quot;HR&quot;</span><span class="mtk1">, </span><span class="mtk8">&quot;dateOfBirth&quot;</span><span class="mtk12">:</span><span class="mtk1"> </span><span class="mtk8">&quot;2000-01-01&quot;</span><span class="mtk1">, </span><span class="mtk8">&quot;age&quot;</span><span class="mtk12">:</span><span class="mtk1"> </span><span class="mtk7">20</span><span class="mtk1">},</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> {</span><span class="mtk8">&quot;name&quot;</span><span class="mtk12">:</span><span class="mtk1"> </span><span class="mtk8">&quot;Lora Bay&quot;</span><span class="mtk1">, </span><span class="mtk8">&quot;occupation&quot;</span><span class="mtk12">:</span><span class="mtk1"> </span><span class="mtk8">&quot;Marketing&quot;</span><span class="mtk1">, </span><span class="mtk8">&quot;dateOfBirth&quot;</span><span class="mtk12">:</span><span class="mtk1"> </span><span class="mtk8">&quot;1977-03-03&quot;</span><span class="mtk1">, </span><span class="mtk8">&quot;age&quot;</span><span class="mtk12">:</span><span class="mtk1"> </span><span class="mtk7">43</span><span class="mtk1">},</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1">]</span></span></span> <span class="grvsc-line"><span class="grvsc-source"></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk4">const</span><span class="mtk1"> </span><span class="mtk12">COLUMNS_SCHEMA</span><span class="mtk1"> = [</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> {</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">key:</span><span class="mtk1"> </span><span class="mtk8">&quot;name&quot;</span><span class="mtk1">,</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">type:</span><span class="mtk1"> </span><span class="mtk8">&quot;text&quot;</span><span class="mtk1">,</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">label:</span><span class="mtk1"> </span><span class="mtk8">&quot;Full Name&quot;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> },</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> {</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">key:</span><span class="mtk1"> </span><span class="mtk8">&quot;occupation&quot;</span><span class="mtk1">,</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">type:</span><span class="mtk1"> </span><span class="mtk8">&quot;text&quot;</span><span class="mtk1">,</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">label:</span><span class="mtk1"> </span><span class="mtk8">&quot;Occupation&quot;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> },</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> {</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">key:</span><span class="mtk1"> </span><span class="mtk8">&quot;dateOfBirth&quot;</span><span class="mtk1">,</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">type:</span><span class="mtk1"> </span><span class="mtk8">&quot;date&quot;</span><span class="mtk1">,</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">label:</span><span class="mtk1"> </span><span class="mtk8">&quot;Date of Birth&quot;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1">},</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> {</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">key:</span><span class="mtk1"> </span><span class="mtk8">&quot;age&quot;</span><span class="mtk1">,</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">type:</span><span class="mtk1"> </span><span class="mtk8">&quot;number&quot;</span><span class="mtk1">,</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">label:</span><span class="mtk1"> </span><span class="mtk8">&quot;Age&quot;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> },</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> {</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">key:</span><span class="mtk1"> </span><span class="mtk8">&quot;isEdit&quot;</span><span class="mtk1">,</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">type:</span><span class="mtk1"> </span><span class="mtk8">&quot;isEdit&quot;</span><span class="mtk1">,</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">label:</span><span class="mtk1"> </span><span class="mtk8">&quot;&quot;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> }</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1">]</span></span></span> <span class="grvsc-line"><span class="grvsc-source"></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1">@</span><span class="mtk11">Component</span><span class="mtk1">({</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">selector:</span><span class="mtk1"> </span><span class="mtk8">&#39;app-root&#39;</span><span class="mtk1">,</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">templateUrl:</span><span class="mtk1"> </span><span class="mtk8">&#39;./app.component.html&#39;</span><span class="mtk1">,</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">styleUrls:</span><span class="mtk1"> [</span><span class="mtk8">&#39;./app.component.scss&#39;</span><span class="mtk1">]</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1">})</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk15">export</span><span class="mtk1"> </span><span class="mtk4">class</span><span class="mtk1"> </span><span class="mtk10">AppComponent</span><span class="mtk1"> {</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">displayedColumns</span><span class="mtk1">: </span><span class="mtk10">string</span><span class="mtk1">[] = </span><span class="mtk12">COLUMNS_SCHEMA</span><span class="mtk1">.</span><span class="mtk11">map</span><span class="mtk1">(</span><span class="mtk12">col</span><span class="mtk1"> </span><span class="mtk4">=&gt;</span><span class="mtk1"> </span><span class="mtk12">col</span><span class="mtk1">.</span><span class="mtk12">key</span><span class="mtk1">);</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">dataSource</span><span class="mtk1"> = </span><span class="mtk12">USER_DATA</span><span class="mtk1">;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">columnsSchema</span><span class="mtk1">: </span><span class="mtk10">any</span><span class="mtk1"> = </span><span class="mtk12">COLUMNS_SCHEMA</span><span class="mtk1">;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"></span></span> <span class="grvsc-line grvsc-line-highlighted"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk11">addRow</span><span class="mtk1">() {</span></span></span> <span class="grvsc-line grvsc-line-highlighted"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk4">const</span><span class="mtk1"> </span><span class="mtk12">newRow</span><span class="mtk1"> = {</span><span class="mtk8">&quot;name&quot;</span><span class="mtk12">:</span><span class="mtk1"> </span><span class="mtk8">&quot;&quot;</span><span class="mtk1">, </span><span class="mtk8">&quot;occupation&quot;</span><span class="mtk12">:</span><span class="mtk1"> </span><span class="mtk8">&quot;&quot;</span><span class="mtk1">, </span><span class="mtk8">&quot;dateOfBirth&quot;</span><span class="mtk12">:</span><span class="mtk1"> </span><span class="mtk8">&quot;&quot;</span><span class="mtk1">, </span><span class="mtk8">&quot;age&quot;</span><span class="mtk12">:</span><span class="mtk1"> </span><span class="mtk7">0</span><span class="mtk1">, </span><span class="mtk12">isEdit:</span><span class="mtk1"> </span><span class="mtk4">true</span><span class="mtk1">}</span></span></span> <span class="grvsc-line grvsc-line-highlighted"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk4">this</span><span class="mtk1">.</span><span class="mtk12">dataSource</span><span class="mtk1"> = [...</span><span class="mtk4">this</span><span class="mtk1">.</span><span class="mtk12">dataSource</span><span class="mtk1">, </span><span class="mtk12">newRow</span><span class="mtk1">];</span></span></span> <span class="grvsc-line grvsc-line-highlighted"><span class="grvsc-source"><span class="mtk1"> }</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1">}</span></span></span></code></pre> <p><em>For Angular to trigger the <code>OnPush</code> change detection, we need to clone the array. That’s why we are using the spread operator on the <code>dataSource</code>.</em></p> <p>In some instances, the table can be long with many rows, and adding a new entry at the bottom will require the user to scroll down every time. We can solve this matter by simply swapping the entries in the new array we just created:</p> <pre class="grvsc-container default-dark" data-language="typescript" data-index="2"><code class="grvsc-code"><span class="grvsc-line"><span class="grvsc-source"><span class="mtk4">this</span><span class="mtk1">.</span><span class="mtk12">dataSource</span><span class="mtk1"> = [</span><span class="mtk12">newRow</span><span class="mtk1">, ...</span><span class="mtk4">this</span><span class="mtk1">.</span><span class="mtk12">dataSource</span><span class="mtk1">];</span></span></span></code></pre> <p>Here is a demo to how the table behaves so far:</p> <div data-youtube="RyjLJAl7Kjk"> <button>Play Example</button> </div> <h2 id="remove-a-row" style="position:relative;"><a href="#remove-a-row" aria-label="remove a row permalink" class="anchor before"><svg aria-hidden="true" focusable="false" height="16" version="1.1" viewBox="0 0 16 16" width="16"><path fill-rule="evenodd" d="M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z"></path></svg></a>Remove a row</h2> <p>As with adding a new row, all we need to do is remove the object from the <code>sourceData</code> array but with a slight change to the model. Let’s take a closer look:</p> <ol> <li>Deleting an object requires a unique id so let’s add a new one for every object. In a real-world scenario, ids will come from the backend:</li> </ol> <pre class="grvsc-container default-dark" data-language="json" data-index="3"><code class="grvsc-code"><span class="grvsc-line"><span class="grvsc-source"><span class="mtk1">const USER_DATA = [</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> {</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk14">id</span><span class="mtk1">: </span><span class="mtk7">1</span><span class="mtk1">,</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk14">name</span><span class="mtk1">: </span><span class="mtk14">&#39;John</span><span class="mtk1"> </span><span class="mtk14">Smith&#39;</span><span class="mtk1">,</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk14">occupation</span><span class="mtk1">: </span><span class="mtk14">&#39;Advisor&#39;</span><span class="mtk1">,</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk14">dateOfBirth</span><span class="mtk1">: </span><span class="mtk14">&#39;</span><span class="mtk7">1984-05-05</span><span class="mtk14">&#39;</span><span class="mtk1">,</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk14">age</span><span class="mtk1">: </span><span class="mtk7">36</span><span class="mtk1">,</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> },</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> {</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk14">id</span><span class="mtk1">: </span><span class="mtk7">2</span><span class="mtk1">,</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk14">name</span><span class="mtk1">: </span><span class="mtk14">&#39;Muhi</span><span class="mtk1"> </span><span class="mtk14">Masri&#39;</span><span class="mtk1">,</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk14">occupation</span><span class="mtk1">: </span><span class="mtk14">&#39;Developer&#39;</span><span class="mtk1">,</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk14">dateOfBirth</span><span class="mtk1">: </span><span class="mtk14">&#39;</span><span class="mtk7">1992-02-02</span><span class="mtk14">&#39;</span><span class="mtk1">,</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk14">age</span><span class="mtk1">: </span><span class="mtk7">28</span><span class="mtk1">,</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> },</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> {</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk14">id</span><span class="mtk1">: </span><span class="mtk7">3</span><span class="mtk1">,</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk14">name</span><span class="mtk1">: </span><span class="mtk14">&#39;Peter</span><span class="mtk1"> </span><span class="mtk14">Adams&#39;</span><span class="mtk1">,</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk14">occupation</span><span class="mtk1">: </span><span class="mtk14">&#39;HR&#39;</span><span class="mtk1">,</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk14">dateOfBirth</span><span class="mtk1">: </span><span class="mtk14">&#39;</span><span class="mtk7">2000-01-01</span><span class="mtk14">&#39;</span><span class="mtk1">,</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk14">age</span><span class="mtk1">: </span><span class="mtk7">20</span><span class="mtk1">,</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> },</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> {</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk14">id</span><span class="mtk1">: </span><span class="mtk7">4</span><span class="mtk1">,</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk14">name</span><span class="mtk1">: </span><span class="mtk14">&#39;Lora</span><span class="mtk1"> </span><span class="mtk14">Bay&#39;</span><span class="mtk1">,</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk14">occupation</span><span class="mtk1">: </span><span class="mtk14">&#39;Marketing&#39;</span><span class="mtk1">,</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk14">dateOfBirth</span><span class="mtk1">: </span><span class="mtk14">&#39;</span><span class="mtk7">1977-03-03</span><span class="mtk14">&#39;</span><span class="mtk1">,</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk14">age</span><span class="mtk1">: </span><span class="mtk7">43</span><span class="mtk1">,</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> },</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1">];</span></span></span></code></pre> <ol start="2"> <li>Add a delete button with a <code>click</code> event in every row, right next to the edit button:</li> </ol> <pre class="grvsc-container grvsc-has-line-highlighting default-dark" data-language="html" data-index="4"><code class="grvsc-code"><span class="grvsc-line"><span class="grvsc-source"><span class="mtk17">&lt;</span><span class="mtk4">article</span><span class="mtk1"> </span><span class="mtk12">class</span><span class="mtk1">=</span><span class="mtk8">&quot;table-header&quot;</span><span class="mtk17">&gt;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk17">&lt;</span><span class="mtk4">button</span><span class="mtk1"> </span><span class="mtk12">class</span><span class="mtk1">=</span><span class="mtk8">&quot;button-add-row&quot;</span><span class="mtk1"> </span><span class="mtk12">mat-button</span><span class="mtk1"> </span><span class="mtk12">(click)</span><span class="mtk1">=</span><span class="mtk8">&quot;addRow()&quot;</span><span class="mtk17">&gt;</span><span class="mtk1">Add Row</span><span class="mtk17">&lt;/</span><span class="mtk4">button</span><span class="mtk17">&gt;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk17">&lt;/</span><span class="mtk4">article</span><span class="mtk17">&gt;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk17">&lt;</span><span class="mtk4">table</span><span class="mtk1"> </span><span class="mtk12">mat-table</span><span class="mtk1"> </span><span class="mtk12">[dataSource]</span><span class="mtk1">=</span><span class="mtk8">&quot;dataSource&quot;</span><span class="mtk17">&gt;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk17">&lt;</span><span class="mtk4">ng-container</span><span class="mtk1"> </span><span class="mtk12">[matColumnDef]</span><span class="mtk1">=</span><span class="mtk8">&quot;col.key&quot;</span><span class="mtk1"> </span><span class="mtk12">*ngFor</span><span class="mtk1">=</span><span class="mtk8">&quot;let col of columnsSchema&quot;</span><span class="mtk17">&gt;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk17">&lt;</span><span class="mtk4">th</span><span class="mtk1"> </span><span class="mtk12">mat-header-cell</span><span class="mtk1"> </span><span class="mtk12">*matHeaderCellDef</span><span class="mtk17">&gt;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> {{ col.label }}</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk17">&lt;/</span><span class="mtk4">th</span><span class="mtk17">&gt;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk17">&lt;</span><span class="mtk4">td</span><span class="mtk1"> </span><span class="mtk12">mat-cell</span><span class="mtk1"> </span><span class="mtk12">*matCellDef</span><span class="mtk1">=</span><span class="mtk8">&quot;let element&quot;</span><span class="mtk17">&gt;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk17">&lt;</span><span class="mtk4">div</span><span class="mtk1"> </span><span class="mtk12">[ngSwitch]</span><span class="mtk1">=</span><span class="mtk8">&quot;col.type&quot;</span><span class="mtk1"> </span><span class="mtk12">*ngIf</span><span class="mtk1">=</span><span class="mtk8">&quot;!element.isEdit&quot;</span><span class="mtk17">&gt;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk17">&lt;</span><span class="mtk4">div</span><span class="mtk1"> </span><span class="mtk12">class</span><span class="mtk1">=</span><span class="mtk8">&quot;btn-edit&quot;</span><span class="mtk1"> </span><span class="mtk12">*ngSwitchCase</span><span class="mtk1">=</span><span class="mtk8">&quot;&#39;isEdit&#39;&quot;</span><span class="mtk17">&gt;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk17">&lt;</span><span class="mtk4">button</span><span class="mtk1"> </span><span class="mtk12">mat-button</span><span class="mtk1"> </span><span class="mtk12">(click)</span><span class="mtk1">=</span><span class="mtk8">&quot;element.isEdit = !element.isEdit&quot;</span><span class="mtk17">&gt;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> Edit</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk17">&lt;/</span><span class="mtk4">button</span><span class="mtk17">&gt;</span></span></span> <span class="grvsc-line grvsc-line-highlighted"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk17">&lt;</span><span class="mtk4">button</span></span></span> <span class="grvsc-line grvsc-line-highlighted"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">mat-button</span></span></span> <span class="grvsc-line grvsc-line-highlighted"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">class</span><span class="mtk1">=</span><span class="mtk8">&quot;button-remove&quot;</span></span></span> <span class="grvsc-line grvsc-line-highlighted"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">(click)</span><span class="mtk1">=</span><span class="mtk8">&quot;removeRow(element.id)&quot;</span></span></span> <span class="grvsc-line grvsc-line-highlighted"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk17">&gt;</span></span></span> <span class="grvsc-line grvsc-line-highlighted"><span class="grvsc-source"><span class="mtk1"> Delete</span></span></span> <span class="grvsc-line grvsc-line-highlighted"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk17">&lt;/</span><span class="mtk4">button</span><span class="mtk17">&gt;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk17">&lt;/</span><span class="mtk4">div</span><span class="mtk17">&gt;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk17">&lt;</span><span class="mtk4">span</span><span class="mtk1"> </span><span class="mtk12">*ngSwitchDefault</span><span class="mtk17">&gt;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> {{ element[col.key] }}</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk17">&lt;/</span><span class="mtk4">span</span><span class="mtk17">&gt;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk17">&lt;/</span><span class="mtk4">div</span><span class="mtk17">&gt;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk17">&lt;</span><span class="mtk4">div</span><span class="mtk1"> </span><span class="mtk12">[ngSwitch]</span><span class="mtk1">=</span><span class="mtk8">&quot;col.type&quot;</span><span class="mtk1"> </span><span class="mtk12">*ngIf</span><span class="mtk1">=</span><span class="mtk8">&quot;element.isEdit&quot;</span><span class="mtk17">&gt;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk17">&lt;</span><span class="mtk4">div</span><span class="mtk1"> </span><span class="mtk12">class</span><span class="mtk1">=</span><span class="mtk8">&quot;btn-edit&quot;</span><span class="mtk1"> </span><span class="mtk12">*ngSwitchCase</span><span class="mtk1">=</span><span class="mtk8">&quot;&#39;isEdit&#39;&quot;</span><span class="mtk17">&gt;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk17">&lt;</span><span class="mtk4">button</span><span class="mtk1"> </span><span class="mtk12">mat-button</span><span class="mtk1"> </span><span class="mtk12">(click)</span><span class="mtk1">=</span><span class="mtk8">&quot;element.isEdit = !element.isEdit&quot;</span><span class="mtk17">&gt;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> Done</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk17">&lt;/</span><span class="mtk4">button</span><span class="mtk17">&gt;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk17">&lt;/</span><span class="mtk4">div</span><span class="mtk17">&gt;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk17">&lt;</span><span class="mtk4">mat-form-field</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">class</span><span class="mtk1">=</span><span class="mtk8">&quot;form-input&quot;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">*ngSwitchCase</span><span class="mtk1">=</span><span class="mtk8">&quot;&#39;date&#39;&quot;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">appearance</span><span class="mtk1">=</span><span class="mtk8">&quot;fill&quot;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk17">&gt;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk17">&lt;</span><span class="mtk4">mat-label</span><span class="mtk17">&gt;</span><span class="mtk1">Choose a date</span><span class="mtk17">&lt;/</span><span class="mtk4">mat-label</span><span class="mtk17">&gt;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk17">&lt;</span><span class="mtk4">input</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">matInput</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">[matDatepicker]</span><span class="mtk1">=</span><span class="mtk8">&quot;picker&quot;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">[(ngModel)]</span><span class="mtk1">=</span><span class="mtk8">&quot;element[col.key]&quot;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk17">/&gt;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk17">&lt;</span><span class="mtk4">mat-datepicker-toggle</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">matSuffix</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">[for]</span><span class="mtk1">=</span><span class="mtk8">&quot;picker&quot;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk17">&gt;&lt;/</span><span class="mtk4">mat-datepicker-toggle</span><span class="mtk17">&gt;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk17">&lt;</span><span class="mtk4">mat-datepicker</span><span class="mtk1"> </span><span class="mtk12">#picker</span><span class="mtk17">&gt;&lt;/</span><span class="mtk4">mat-datepicker</span><span class="mtk17">&gt;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk17">&lt;/</span><span class="mtk4">mat-form-field</span><span class="mtk17">&gt;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk17">&lt;</span><span class="mtk4">mat-form-field</span><span class="mtk1"> </span><span class="mtk12">class</span><span class="mtk1">=</span><span class="mtk8">&quot;form-input&quot;</span><span class="mtk1"> </span><span class="mtk12">*ngSwitchDefault</span><span class="mtk17">&gt;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk17">&lt;</span><span class="mtk4">input</span><span class="mtk1"> </span><span class="mtk12">[type]</span><span class="mtk1">=</span><span class="mtk8">&quot;col.type&quot;</span><span class="mtk1"> </span><span class="mtk12">matInput</span><span class="mtk1"> </span><span class="mtk12">[(ngModel)]</span><span class="mtk1">=</span><span class="mtk8">&quot;element[col.key]&quot;</span><span class="mtk1"> </span><span class="mtk17">/&gt;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk17">&lt;/</span><span class="mtk4">mat-form-field</span><span class="mtk17">&gt;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk17">&lt;/</span><span class="mtk4">div</span><span class="mtk17">&gt;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk17">&lt;/</span><span class="mtk4">td</span><span class="mtk17">&gt;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk17">&lt;/</span><span class="mtk4">ng-container</span><span class="mtk17">&gt;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk17">&lt;</span><span class="mtk4">tr</span><span class="mtk1"> </span><span class="mtk12">mat-header-row</span><span class="mtk1"> </span><span class="mtk12">*matHeaderRowDef</span><span class="mtk1">=</span><span class="mtk8">&quot;displayedColumns&quot;</span><span class="mtk17">&gt;&lt;/</span><span class="mtk4">tr</span><span class="mtk17">&gt;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk17">&lt;</span><span class="mtk4">tr</span><span class="mtk1"> </span><span class="mtk12">mat-row</span><span class="mtk1"> </span><span class="mtk12">*matRowDef</span><span class="mtk1">=</span><span class="mtk8">&quot;let row; columns: displayedColumns&quot;</span><span class="mtk17">&gt;&lt;/</span><span class="mtk4">tr</span><span class="mtk17">&gt;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk17">&lt;/</span><span class="mtk4">table</span><span class="mtk17">&gt;</span></span></span></code></pre> <ol start="3"> <li>Implement <code>removeRow</code> function that filters the <code>dataSource</code> array to take out the object we need to remove:</li> </ol> <pre class="grvsc-container grvsc-has-line-highlighting default-dark" data-language="typescript" data-index="5"><code class="grvsc-code"><span class="grvsc-line"><span class="grvsc-source"><span class="mtk15">import</span><span class="mtk1"> { </span><span class="mtk12">Component</span><span class="mtk1"> } </span><span class="mtk15">from</span><span class="mtk1"> </span><span class="mtk8">&#39;@angular/core&#39;</span><span class="mtk1">;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk4">const</span><span class="mtk1"> </span><span class="mtk12">USER_DATA</span><span class="mtk1"> = [</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> {</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">id:</span><span class="mtk1"> </span><span class="mtk7">1</span><span class="mtk1">,</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">name:</span><span class="mtk1"> </span><span class="mtk8">&#39;John Smith&#39;</span><span class="mtk1">,</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">occupation:</span><span class="mtk1"> </span><span class="mtk8">&#39;Advisor&#39;</span><span class="mtk1">,</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">dateOfBirth:</span><span class="mtk1"> </span><span class="mtk8">&#39;1984-05-05&#39;</span><span class="mtk1">,</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">age:</span><span class="mtk1"> </span><span class="mtk7">36</span><span class="mtk1">,</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> },</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> {</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">id:</span><span class="mtk1"> </span><span class="mtk7">2</span><span class="mtk1">,</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">name:</span><span class="mtk1"> </span><span class="mtk8">&#39;Muhi Masri&#39;</span><span class="mtk1">,</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">occupation:</span><span class="mtk1"> </span><span class="mtk8">&#39;Developer&#39;</span><span class="mtk1">,</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">dateOfBirth:</span><span class="mtk1"> </span><span class="mtk8">&#39;1992-02-02&#39;</span><span class="mtk1">,</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">age:</span><span class="mtk1"> </span><span class="mtk7">28</span><span class="mtk1">,</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> },</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> {</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">id:</span><span class="mtk1"> </span><span class="mtk7">3</span><span class="mtk1">,</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">name:</span><span class="mtk1"> </span><span class="mtk8">&#39;Peter Adams&#39;</span><span class="mtk1">,</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">occupation:</span><span class="mtk1"> </span><span class="mtk8">&#39;HR&#39;</span><span class="mtk1">,</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">dateOfBirth:</span><span class="mtk1"> </span><span class="mtk8">&#39;2000-01-01&#39;</span><span class="mtk1">,</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">age:</span><span class="mtk1"> </span><span class="mtk7">20</span><span class="mtk1">,</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> },</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> {</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">id:</span><span class="mtk1"> </span><span class="mtk7">4</span><span class="mtk1">,</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">name:</span><span class="mtk1"> </span><span class="mtk8">&#39;Lora Bay&#39;</span><span class="mtk1">,</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">occupation:</span><span class="mtk1"> </span><span class="mtk8">&#39;Marketing&#39;</span><span class="mtk1">,</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">dateOfBirth:</span><span class="mtk1"> </span><span class="mtk8">&#39;1977-03-03&#39;</span><span class="mtk1">,</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">age:</span><span class="mtk1"> </span><span class="mtk7">43</span><span class="mtk1">,</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> },</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1">];</span></span></span> <span class="grvsc-line"><span class="grvsc-source"></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk4">const</span><span class="mtk1"> </span><span class="mtk12">COLUMNS_SCHEMA</span><span class="mtk1"> = [</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> {</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">key:</span><span class="mtk1"> </span><span class="mtk8">&#39;name&#39;</span><span class="mtk1">,</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">type:</span><span class="mtk1"> </span><span class="mtk8">&#39;text&#39;</span><span class="mtk1">,</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">label:</span><span class="mtk1"> </span><span class="mtk8">&#39;Full Name&#39;</span><span class="mtk1">,</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> },</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> {</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">key:</span><span class="mtk1"> </span><span class="mtk8">&#39;occupation&#39;</span><span class="mtk1">,</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">type:</span><span class="mtk1"> </span><span class="mtk8">&#39;text&#39;</span><span class="mtk1">,</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">label:</span><span class="mtk1"> </span><span class="mtk8">&#39;Occupation&#39;</span><span class="mtk1">,</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> },</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> {</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">key:</span><span class="mtk1"> </span><span class="mtk8">&#39;dateOfBirth&#39;</span><span class="mtk1">,</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">type:</span><span class="mtk1"> </span><span class="mtk8">&#39;date&#39;</span><span class="mtk1">,</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">label:</span><span class="mtk1"> </span><span class="mtk8">&#39;Date of Birth&#39;</span><span class="mtk1">,</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> },</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> {</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">key:</span><span class="mtk1"> </span><span class="mtk8">&#39;age&#39;</span><span class="mtk1">,</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">type:</span><span class="mtk1"> </span><span class="mtk8">&#39;number&#39;</span><span class="mtk1">,</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">label:</span><span class="mtk1"> </span><span class="mtk8">&#39;Age&#39;</span><span class="mtk1">,</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> },</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> {</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">key:</span><span class="mtk1"> </span><span class="mtk8">&#39;isEdit&#39;</span><span class="mtk1">,</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">type:</span><span class="mtk1"> </span><span class="mtk8">&#39;isEdit&#39;</span><span class="mtk1">,</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">label:</span><span class="mtk1"> </span><span class="mtk8">&#39;&#39;</span><span class="mtk1">,</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> },</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1">];</span></span></span> <span class="grvsc-line"><span class="grvsc-source"></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1">@</span><span class="mtk11">Component</span><span class="mtk1">({</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">selector:</span><span class="mtk1"> </span><span class="mtk8">&#39;app-root&#39;</span><span class="mtk1">,</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">templateUrl:</span><span class="mtk1"> </span><span class="mtk8">&#39;./app.component.html&#39;</span><span class="mtk1">,</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">styleUrls:</span><span class="mtk1"> [</span><span class="mtk8">&#39;./app.component.scss&#39;</span><span class="mtk1">],</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1">})</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk15">export</span><span class="mtk1"> </span><span class="mtk4">class</span><span class="mtk1"> </span><span class="mtk10">AppComponent</span><span class="mtk1"> {</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">displayedColumns</span><span class="mtk1">: </span><span class="mtk10">string</span><span class="mtk1">[] = </span><span class="mtk12">COLUMNS_SCHEMA</span><span class="mtk1">.</span><span class="mtk11">map</span><span class="mtk1">((</span><span class="mtk12">col</span><span class="mtk1">) </span><span class="mtk4">=&gt;</span><span class="mtk1"> </span><span class="mtk12">col</span><span class="mtk1">.</span><span class="mtk12">key</span><span class="mtk1">);</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">dataSource</span><span class="mtk1"> = </span><span class="mtk12">USER_DATA</span><span class="mtk1">;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">columnsSchema</span><span class="mtk1">: </span><span class="mtk10">any</span><span class="mtk1"> = </span><span class="mtk12">COLUMNS_SCHEMA</span><span class="mtk1">;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk11">addRow</span><span class="mtk1">() {</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk4">const</span><span class="mtk1"> </span><span class="mtk12">newRow</span><span class="mtk1"> = {</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">id:</span><span class="mtk1"> </span><span class="mtk10">Date</span><span class="mtk1">.</span><span class="mtk11">now</span><span class="mtk1">(),</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">name:</span><span class="mtk1"> </span><span class="mtk8">&#39;&#39;</span><span class="mtk1">,</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">occupation:</span><span class="mtk1"> </span><span class="mtk8">&#39;&#39;</span><span class="mtk1">,</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">dateOfBirth:</span><span class="mtk1"> </span><span class="mtk8">&#39;&#39;</span><span class="mtk1">,</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">age:</span><span class="mtk1"> </span><span class="mtk7">0</span><span class="mtk1">,</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">isEdit:</span><span class="mtk1"> </span><span class="mtk4">true</span><span class="mtk1">,</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> };</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk4">this</span><span class="mtk1">.</span><span class="mtk12">dataSource</span><span class="mtk1"> = [</span><span class="mtk12">newRow</span><span class="mtk1">, ...</span><span class="mtk4">this</span><span class="mtk1">.</span><span class="mtk12">dataSource</span><span class="mtk1">];</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> }</span></span></span> <span class="grvsc-line"><span class="grvsc-source"></span></span> <span class="grvsc-line grvsc-line-highlighted"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk11">removeRow</span><span class="mtk1">(</span><span class="mtk12">id</span><span class="mtk1">: </span><span class="mtk10">number</span><span class="mtk1">) {</span></span></span> <span class="grvsc-line grvsc-line-highlighted"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk4">this</span><span class="mtk1">.</span><span class="mtk12">dataSource</span><span class="mtk1"> = </span><span class="mtk4">this</span><span class="mtk1">.</span><span class="mtk12">dataSource</span><span class="mtk1">.</span><span class="mtk11">filter</span><span class="mtk1">((</span><span class="mtk12">u</span><span class="mtk1">) </span><span class="mtk4">=&gt;</span><span class="mtk1"> </span><span class="mtk12">u</span><span class="mtk1">.</span><span class="mtk12">id</span><span class="mtk1"> !== </span><span class="mtk12">id</span><span class="mtk1">);</span></span></span> <span class="grvsc-line grvsc-line-highlighted"><span class="grvsc-source"><span class="mtk1"> }</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1">}</span></span></span></code></pre> <p><em>We also modified the <code>addRow</code> function to generate a random id so that the remove works on new rows.</em></p> <p>Here is a demo of the remove functionality we just did:</p> <div data-youtube="zsmhOn55WCY"> <button>Play Example</button> </div> <h2 id="remove-multiple-rows" style="position:relative;"><a href="#remove-multiple-rows" aria-label="remove multiple rows permalink" class="anchor before"><svg aria-hidden="true" focusable="false" height="16" version="1.1" viewBox="0 0 16 16" width="16"><path fill-rule="evenodd" d="M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z"></path></svg></a>Remove multiple rows</h2> <p>This section will introduce a new feature to support removing multiple rows. That requires a slight change to the model to keep track of the selected rows. Let’s go through the necessary steps:</p> <ol> <li>Add a new <code>isSelected</code> column to the <code>COLUMNS_SCHEMA</code>. That will help us determine which rows are selected:</li> </ol> <pre class="grvsc-container grvsc-has-line-highlighting default-dark" data-language="json" data-index="6"><code class="grvsc-code"><span class="grvsc-line"><span class="grvsc-source"><span class="mtk1">const COLUMNS_SCHEMA = [</span></span></span> <span class="grvsc-line grvsc-line-highlighted"><span class="grvsc-source"><span class="mtk1"> {</span></span></span> <span class="grvsc-line grvsc-line-highlighted"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk14">key</span><span class="mtk1">: </span><span class="mtk14">&#39;isSelected&#39;</span><span class="mtk1">,</span></span></span> <span class="grvsc-line grvsc-line-highlighted"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk14">type</span><span class="mtk1">: </span><span class="mtk14">&#39;isSelected&#39;</span><span class="mtk1">,</span></span></span> <span class="grvsc-line grvsc-line-highlighted"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk14">label</span><span class="mtk1">: </span><span class="mtk14">&#39;&#39;</span><span class="mtk1">,</span></span></span> <span class="grvsc-line grvsc-line-highlighted"><span class="grvsc-source"><span class="mtk1"> },</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> {</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk14">key</span><span class="mtk1">: </span><span class="mtk14">&#39;name&#39;</span><span class="mtk1">,</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk14">type</span><span class="mtk1">: </span><span class="mtk14">&#39;text&#39;</span><span class="mtk1">,</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk14">label</span><span class="mtk1">: </span><span class="mtk14">&#39;Full</span><span class="mtk1"> </span><span class="mtk14">Name&#39;</span><span class="mtk1">,</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> },</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> {</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk14">key</span><span class="mtk1">: </span><span class="mtk14">&#39;occupation&#39;</span><span class="mtk1">,</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk14">type</span><span class="mtk1">: </span><span class="mtk14">&#39;text&#39;</span><span class="mtk1">,</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk14">label</span><span class="mtk1">: </span><span class="mtk14">&#39;Occupation&#39;</span><span class="mtk1">,</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> },</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> {</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk14">key</span><span class="mtk1">: </span><span class="mtk14">&#39;dateOfBirth&#39;</span><span class="mtk1">,</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk14">type</span><span class="mtk1">: </span><span class="mtk14">&#39;date&#39;</span><span class="mtk1">,</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk14">label</span><span class="mtk1">: </span><span class="mtk14">&#39;Date</span><span class="mtk1"> </span><span class="mtk14">of</span><span class="mtk1"> </span><span class="mtk14">Birth&#39;</span><span class="mtk1">,</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> },</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> {</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk14">key</span><span class="mtk1">: </span><span class="mtk14">&#39;age&#39;</span><span class="mtk1">,</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk14">type</span><span class="mtk1">: </span><span class="mtk14">&#39;number&#39;</span><span class="mtk1">,</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk14">label</span><span class="mtk1">: </span><span class="mtk14">&#39;Age&#39;</span><span class="mtk1">,</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> },</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> {</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk14">key</span><span class="mtk1">: </span><span class="mtk14">&#39;isEdit&#39;</span><span class="mtk1">,</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk14">type</span><span class="mtk1">: </span><span class="mtk14">&#39;isEdit&#39;</span><span class="mtk1">,</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk14">label</span><span class="mtk1">: </span><span class="mtk14">&#39;&#39;</span><span class="mtk1">,</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> }</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1">];</span></span></span></code></pre> <ol start="2"> <li> <p>Add a checkbox element as a new column only within the none-edit mode section because we don’t need it to appear while editing the row</p> </li> <li> <p>Define a <code>change</code> event to insert the <code>isSelected</code> property into the row dynamically. <code>$event.checked</code> determines the value(true or false)</p> </li> </ol> <pre class="grvsc-container grvsc-has-line-highlighting default-dark" data-language="html" data-index="7"><code class="grvsc-code"><span class="grvsc-line"><span class="grvsc-source"><span class="mtk17">&lt;</span><span class="mtk4">div</span><span class="mtk1"> </span><span class="mtk12">[ngSwitch]</span><span class="mtk1">=</span><span class="mtk8">&quot;col.type&quot;</span><span class="mtk1"> </span><span class="mtk12">*ngIf</span><span class="mtk1">=</span><span class="mtk8">&quot;!element.isEdit&quot;</span><span class="mtk17">&gt;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk17">&lt;</span><span class="mtk4">ng-container</span><span class="mtk1"> </span><span class="mtk12">*ngSwitchCase</span><span class="mtk1">=</span><span class="mtk8">&quot;&#39;isSelected&#39;&quot;</span><span class="mtk17">&gt;</span></span></span> <span class="grvsc-line grvsc-line-highlighted"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk17">&lt;</span><span class="mtk4">mat-checkbox</span></span></span> <span class="grvsc-line grvsc-line-highlighted"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">(change)</span><span class="mtk1">=</span><span class="mtk8">&quot;element.isSelected = $event.checked&quot;</span></span></span> <span class="grvsc-line grvsc-line-highlighted"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">[checked]</span><span class="mtk1">=</span><span class="mtk8">&quot;element.isSelected&quot;</span><span class="mtk17">&gt;</span></span></span> <span class="grvsc-line grvsc-line-highlighted"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk17">&lt;/</span><span class="mtk4">mat-checkbox</span><span class="mtk17">&gt;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk17">&lt;/</span><span class="mtk4">ng-container</span><span class="mtk17">&gt;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk17">&lt;</span><span class="mtk4">div</span><span class="mtk1"> </span><span class="mtk12">class</span><span class="mtk1">=</span><span class="mtk8">&quot;btn-edit&quot;</span><span class="mtk1"> </span><span class="mtk12">*ngSwitchCase</span><span class="mtk1">=</span><span class="mtk8">&quot;&#39;isEdit&#39;&quot;</span><span class="mtk17">&gt;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk17">&lt;</span><span class="mtk4">button</span><span class="mtk1"> </span><span class="mtk12">mat-button</span><span class="mtk1"> </span><span class="mtk12">(click)</span><span class="mtk1">=</span><span class="mtk8">&quot;element.isEdit = !element.isEdit&quot;</span><span class="mtk17">&gt;</span><span class="mtk1">Edit</span><span class="mtk17">&lt;/</span><span class="mtk4">button</span><span class="mtk17">&gt;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk17">&lt;</span><span class="mtk4">button</span><span class="mtk1"> </span><span class="mtk12">mat-button</span><span class="mtk1"> </span><span class="mtk12">class</span><span class="mtk1">=</span><span class="mtk8">&quot;button-remove&quot;</span><span class="mtk1"> </span><span class="mtk12">(click)</span><span class="mtk1">=</span><span class="mtk8">&quot;removeRow(element.id)&quot;</span><span class="mtk17">&gt;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> Delete</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk17">&lt;/</span><span class="mtk4">button</span><span class="mtk17">&gt;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk17">&lt;/</span><span class="mtk4">div</span><span class="mtk17">&gt;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk17">&lt;</span><span class="mtk4">span</span><span class="mtk1"> </span><span class="mtk12">*ngSwitchDefault</span><span class="mtk17">&gt;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> {{ element[col.key] }}</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk17">&lt;/</span><span class="mtk4">span</span><span class="mtk17">&gt;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk17">&lt;/</span><span class="mtk4">div</span><span class="mtk17">&gt;</span></span></span></code></pre> <ol start="4"> <li>Add a new remove button with a <code>click</code> event. Let’s place it right next to the add button created earlier:</li> </ol> <pre class="grvsc-container grvsc-has-line-highlighting default-dark" data-language="html" data-index="8"><code class="grvsc-code"><span class="grvsc-line"><span class="grvsc-source"><span class="mtk17">&lt;</span><span class="mtk4">article</span><span class="mtk1"> </span><span class="mtk12">class</span><span class="mtk1">=</span><span class="mtk8">&quot;table-header&quot;</span><span class="mtk17">&gt;</span></span></span> <span class="grvsc-line grvsc-line-highlighted"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk17">&lt;</span><span class="mtk4">button</span><span class="mtk1"> </span><span class="mtk12">class</span><span class="mtk1">=</span><span class="mtk8">&quot;button-remove-rows&quot;</span><span class="mtk1"> </span><span class="mtk12">mat-button</span><span class="mtk1"> </span><span class="mtk12">(click)</span><span class="mtk1">=</span><span class="mtk8">&quot;removeSelectedRows()&quot;</span><span class="mtk17">&gt;</span></span></span> <span class="grvsc-line grvsc-line-highlighted"><span class="grvsc-source"><span class="mtk1"> Remove Rows</span></span></span> <span class="grvsc-line grvsc-line-highlighted"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk17">&lt;/</span><span class="mtk4">button</span><span class="mtk17">&gt;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk17">&lt;</span><span class="mtk4">button</span><span class="mtk1"> </span><span class="mtk12">class</span><span class="mtk1">=</span><span class="mtk8">&quot;button-add-row&quot;</span><span class="mtk1"> </span><span class="mtk12">mat-button</span><span class="mtk1"> </span><span class="mtk12">(click)</span><span class="mtk1">=</span><span class="mtk8">&quot;addRow()&quot;</span><span class="mtk17">&gt;</span><span class="mtk1">Add Row</span><span class="mtk17">&lt;/</span><span class="mtk4">button</span><span class="mtk17">&gt;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk17">&lt;/</span><span class="mtk4">article</span><span class="mtk17">&gt;</span></span></span></code></pre> <ol start="5"> <li>Create a new <code>removeSelectedRows</code> function that filters and returns the non-selected rows from the <code>sourceData</code> array:</li> </ol> <pre class="grvsc-container default-dark" data-language="typescript" data-index="9"><code class="grvsc-code"><span class="grvsc-line"><span class="grvsc-source"><span class="mtk11">removeSelectedRows</span><span class="mtk1">() {</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk4">this</span><span class="mtk1">.</span><span class="mtk12">dataSource</span><span class="mtk1"> = </span><span class="mtk4">this</span><span class="mtk1">.</span><span class="mtk12">dataSource</span><span class="mtk1">.</span><span class="mtk11">filter</span><span class="mtk1">((</span><span class="mtk12">u</span><span class="mtk1">: </span><span class="mtk10">any</span><span class="mtk1">) </span><span class="mtk4">=&gt;</span><span class="mtk1"> !</span><span class="mtk12">u</span><span class="mtk1">.</span><span class="mtk12">isSelected</span><span class="mtk1">);</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1">}</span></span></span></code></pre> <p>Let’s clarify a bit more; when the user selects a row, the object will attach <code>isSelected: true</code> to the object as follows:</p> <pre class="grvsc-container default-dark" data-language="json" data-index="10"><code class="grvsc-code"><span class="grvsc-line"><span class="grvsc-source"><span class="mtk1">{</span><span class="mtk14">id</span><span class="mtk1">: </span><span class="mtk7">1</span><span class="mtk1">, </span><span class="mtk12">&quot;name&quot;</span><span class="mtk1">: </span><span class="mtk8">&quot;John Smith&quot;</span><span class="mtk1">, </span><span class="mtk12">&quot;occupation&quot;</span><span class="mtk1">: </span><span class="mtk8">&quot;Advisor&quot;</span><span class="mtk1">, </span><span class="mtk12">&quot;dateOfBirth&quot;</span><span class="mtk1">: </span><span class="mtk8">&quot;1984-05-05&quot;</span><span class="mtk1">, </span><span class="mtk12">&quot;age&quot;</span><span class="mtk1">: </span><span class="mtk7">36</span><span class="mtk1">, </span><span class="mtk14">isSelected</span><span class="mtk1">: </span><span class="mtk4">true</span><span class="mtk1">}</span></span></span></code></pre> <p>Then we filter the <code>dataSource</code> by <code>isSelected</code> values to remove them and return a new array.</p> <p>Let’s demonstrate what we have so far:</p> <div data-youtube="jar_3LLyLj4"> <button>Play Example</button> </div> <p>What we did above does not incorporate “select/unselect all” option because the checkbox was only added to the data row.</p> <p>To support this feature, we can add a switch statement in the header cell to check for <code>isSelected</code> and display a checkbox instead of a label.</p> <pre class="grvsc-container default-dark" data-language="html" data-index="11"><code class="grvsc-code"><span class="grvsc-line"><span class="grvsc-source"><span class="mtk17">&lt;</span><span class="mtk4">th</span><span class="mtk1"> </span><span class="mtk12">mat-header-cell</span><span class="mtk1"> </span><span class="mtk12">*matHeaderCellDef</span><span class="mtk1"> </span><span class="mtk12">[ngSwitch]</span><span class="mtk1">=</span><span class="mtk8">&quot;col.key&quot;</span><span class="mtk17">&gt;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk17">&lt;</span><span class="mtk4">span</span><span class="mtk1"> </span><span class="mtk12">*ngSwitchCase</span><span class="mtk1">=</span><span class="mtk8">&quot;&#39;isSelected&#39;&quot;</span><span class="mtk17">&gt;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk17">&lt;</span><span class="mtk4">mat-checkbox</span><span class="mtk17">&gt;&lt;/</span><span class="mtk4">mat-checkbox</span><span class="mtk17">&gt;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk17">&lt;/</span><span class="mtk4">span</span><span class="mtk17">&gt;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk17">&lt;</span><span class="mtk4">span</span><span class="mtk1"> </span><span class="mtk12">*ngSwitchDefault</span><span class="mtk17">&gt;</span><span class="mtk1">{{ col.label }}</span><span class="mtk17">&lt;/</span><span class="mtk4">span</span><span class="mtk17">&gt;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk17">&lt;/</span><span class="mtk4">th</span><span class="mtk17">&gt;</span></span></span></code></pre> <p>Then we have to define three functions:</p> <ul> <li>isAllSelected - return whether every row is selected</li> <li>isAnySelected - return if any row is selected</li> <li>selectAll - select/unselect all rows</li> </ul> <pre class="grvsc-container default-dark" data-language="typescript" data-index="12"><code class="grvsc-code"><span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk11">isAllSelected</span><span class="mtk1">() {</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk15">return</span><span class="mtk1"> </span><span class="mtk4">this</span><span class="mtk1">.</span><span class="mtk12">dataSource</span><span class="mtk1">.</span><span class="mtk11">every</span><span class="mtk1">((</span><span class="mtk12">item</span><span class="mtk1">: </span><span class="mtk10">any</span><span class="mtk1">) </span><span class="mtk4">=&gt;</span><span class="mtk1"> </span><span class="mtk12">item</span><span class="mtk1">.</span><span class="mtk12">isSelected</span><span class="mtk1">);</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> }</span></span></span> <span class="grvsc-line"><span class="grvsc-source"></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk11">isAnySelected</span><span class="mtk1">() {</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk15">return</span><span class="mtk1"> </span><span class="mtk4">this</span><span class="mtk1">.</span><span class="mtk12">dataSource</span><span class="mtk1">.</span><span class="mtk11">some</span><span class="mtk1">((</span><span class="mtk12">item</span><span class="mtk1">: </span><span class="mtk10">any</span><span class="mtk1">) </span><span class="mtk4">=&gt;</span><span class="mtk1"> </span><span class="mtk12">item</span><span class="mtk1">.</span><span class="mtk12">isSelected</span><span class="mtk1">);</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> }</span></span></span> <span class="grvsc-line"><span class="grvsc-source"></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk11">selectAll</span><span class="mtk1">(</span><span class="mtk12">event</span><span class="mtk1">) {</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk4">this</span><span class="mtk1">.</span><span class="mtk12">dataSource</span><span class="mtk1"> = </span><span class="mtk4">this</span><span class="mtk1">.</span><span class="mtk12">dataSource</span><span class="mtk1">.</span><span class="mtk11">map</span><span class="mtk1">((</span><span class="mtk12">item</span><span class="mtk1">: </span><span class="mtk10">any</span><span class="mtk1">) </span><span class="mtk4">=&gt;</span><span class="mtk1"> ({</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> ...</span><span class="mtk12">item</span><span class="mtk1">,</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">isSelected:</span><span class="mtk1"> </span><span class="mtk12">event</span><span class="mtk1">.</span><span class="mtk12">checked</span><span class="mtk1">,</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> }));</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> }</span></span></span></code></pre> <p>The first two functions will determine whether or not the checkbox should have a “checked” or “indeterminate” icon. If all are selected, it’s a standard check icon, but if one or a few are selected, then it’s indeterminate. Otherwise, it’s unchecked.</p> <pre class="grvsc-container grvsc-has-line-highlighting default-dark" data-language="html" data-index="13"><code class="grvsc-code"><span class="grvsc-line"><span class="grvsc-source"><span class="mtk17">&lt;</span><span class="mtk4">th</span><span class="mtk1"> </span><span class="mtk12">mat-header-cell</span><span class="mtk1"> </span><span class="mtk12">*matHeaderCellDef</span><span class="mtk1"> </span><span class="mtk12">[ngSwitch]</span><span class="mtk1">=</span><span class="mtk8">&quot;col.key&quot;</span><span class="mtk17">&gt;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk17">&lt;</span><span class="mtk4">span</span><span class="mtk1"> </span><span class="mtk12">*ngSwitchCase</span><span class="mtk1">=</span><span class="mtk8">&quot;&#39;isSelected&#39;&quot;</span><span class="mtk17">&gt;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk17">&lt;</span><span class="mtk4">mat-checkbox</span></span></span> <span class="grvsc-line grvsc-line-highlighted"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">(change)</span><span class="mtk1">=</span><span class="mtk8">&quot;selectAll($event)&quot;</span></span></span> <span class="grvsc-line grvsc-line-highlighted"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">[checked]</span><span class="mtk1">=</span><span class="mtk8">&quot;isAllSelected()&quot;</span></span></span> <span class="grvsc-line grvsc-line-highlighted"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">[indeterminate]</span><span class="mtk1">=</span><span class="mtk8">&quot;!isAllSelected() &amp;&amp; isAnySelected()&quot;</span><span class="mtk17">&gt;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk17">&lt;/</span><span class="mtk4">mat-checkbox</span><span class="mtk17">&gt;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk17">&lt;/</span><span class="mtk4">span</span><span class="mtk17">&gt;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk17">&lt;</span><span class="mtk4">span</span><span class="mtk1"> </span><span class="mtk12">*ngSwitchDefault</span><span class="mtk17">&gt;</span><span class="mtk1">{{ col.label }}</span><span class="mtk17">&lt;/</span><span class="mtk4">span</span><span class="mtk17">&gt;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk17">&lt;/</span><span class="mtk4">th</span><span class="mtk17">&gt;</span></span></span></code></pre> <p><span class="gatsby-resp-image-wrapper" style="position: relative; display: block; margin-left: auto; margin-right: auto; max-width: 720px; " > <a class="gatsby-resp-image-link" href="/static/d83300dc8837e40cc1418b114417c5c9/4779f/select-all.png" style="display: block" target="_blank" rel="noopener" > <span class="gatsby-resp-image-background-image" style="padding-bottom: 33.33333333333333%; position: relative; bottom: 0; left: 0; background-image: url('data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABQAAAAHCAYAAAAIy204AAAACXBIWXMAABnWAAAZ1gEY0crtAAABMUlEQVR42pVOO07DQBTcK0Hj+KPIwl47thNjnLikoKGAgo6gyI6tuCAH4QzcARkSJU6BUCjT0qQmw75FtmhSsNLozc6bmV2G/57D4Xfudvi+vQEur/D8NMZ1dYePr3ewx/kceZ5jNpshyzIJ4kVRSF6WJabTHGmatlqLyQQpIUtx/zDG53YLxh0XhmGAcxuqqqLT6eDMsqBpmgTnHN1uF4qiyEn7FsJvmCZMTYd2coqXqgIbhCF8z8dwOJRh27YRxzF835f3C8GDIIAlHiGN9i1I6/cRCl9P1/G6WIDJsAgkowSe58F1XVngOI7kURShL0JU3uh/EQwGOBe+nvj923IJNkoSaaTixkS/JY0KST9aSJoojITPawo3mw3W6zWa2fC6riVv5jHQvia+WmG/3+MHdkxaJligS2UAAAAASUVORK5CYII='); background-size: cover; display: block;" ></span> <img class="gatsby-resp-image-image" alt="Select/Unselect All" title="" src="/static/d83300dc8837e40cc1418b114417c5c9/37523/select-all.png" srcset="/static/d83300dc8837e40cc1418b114417c5c9/e9ff0/select-all.png 180w, /static/d83300dc8837e40cc1418b114417c5c9/f21e7/select-all.png 360w, /static/d83300dc8837e40cc1418b114417c5c9/37523/select-all.png 720w, /static/d83300dc8837e40cc1418b114417c5c9/302a4/select-all.png 1080w, /static/d83300dc8837e40cc1418b114417c5c9/07a9c/select-all.png 1440w, /static/d83300dc8837e40cc1418b114417c5c9/4779f/select-all.png 1837w" sizes="(max-width: 720px) 100vw, 720px" style="width:100%;height:100%;margin:0;vertical-align:middle;position:absolute;top:0;left:0;" loading="lazy" decoding="async" /> </a> </span></p> <h2 id="confirmation-dialog" style="position:relative;"><a href="#confirmation-dialog" aria-label="confirmation dialog permalink" class="anchor before"><svg aria-hidden="true" focusable="false" height="16" version="1.1" viewBox="0 0 16 16" width="16"><path fill-rule="evenodd" d="M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z"></path></svg></a>Confirmation dialog</h2> <p>If the remove rows function triggers an API call to delete selected rows, it’s good to add a confirmation dialog before proceeding. That requires a few simple steps:</p> <ol> <li>Create a new <code>ConfirmDialog</code> component. We can use the CLI command:</li> </ol> <pre class="grvsc-container default-dark" data-language="" data-index="14"><code class="grvsc-code"><span class="grvsc-line"><span class="grvsc-source">ng generate component confirm-dialog</span></span></code></pre> <ol start="2"> <li>Add the required template for the confirmation dialog. In our case, it’s just a simple confirm/cancel dialog:</li> </ol> <pre class="grvsc-container default-dark" data-language="html" data-index="15"><code class="grvsc-code"><span class="grvsc-line"><span class="grvsc-source"><span class="mtk17">&lt;</span><span class="mtk4">h1</span><span class="mtk1"> </span><span class="mtk12">mat-dialog-title</span><span class="mtk17">&gt;</span><span class="mtk1">Are you sure you want to delete?</span><span class="mtk17">&lt;/</span><span class="mtk4">h1</span><span class="mtk17">&gt;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk17">&lt;</span><span class="mtk4">div</span><span class="mtk1"> </span><span class="mtk12">mat-dialog-actions</span><span class="mtk17">&gt;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk17">&lt;</span><span class="mtk4">button</span><span class="mtk1"> </span><span class="mtk12">mat-button</span><span class="mtk1"> </span><span class="mtk12">[mat-dialog-close]</span><span class="mtk17">&gt;</span><span class="mtk1">Cancel</span><span class="mtk17">&lt;/</span><span class="mtk4">button</span><span class="mtk17">&gt;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk17">&lt;</span><span class="mtk4">button</span><span class="mtk1"> </span><span class="mtk12">class</span><span class="mtk1">=</span><span class="mtk8">&quot;delete-button&quot;</span><span class="mtk1"> </span><span class="mtk12">mat-button</span><span class="mtk1"> </span><span class="mtk12">[mat-dialog-close]</span><span class="mtk1">=</span><span class="mtk8">&quot;true&quot;</span><span class="mtk17">&gt;</span><span class="mtk1">Delete</span><span class="mtk17">&lt;/</span><span class="mtk4">button</span><span class="mtk17">&gt;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk17">&lt;/</span><span class="mtk4">div</span><span class="mtk17">&gt;</span></span></span></code></pre> <ol start="3"> <li>In <code>app.component.ts</code>, subscribe to the <code>afterClosed</code> event and remove all the selected rows if the action was “Yes” otherwise just close the dialog:</li> </ol> <pre class="grvsc-container default-dark" data-language="typescript" data-index="16"><code class="grvsc-code"><span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk11">removeSelectedRows</span><span class="mtk1">() {</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk4">this</span><span class="mtk1">.</span><span class="mtk12">dialog</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> .</span><span class="mtk11">open</span><span class="mtk1">(</span><span class="mtk12">ConfirmDialogComponent</span><span class="mtk1">)</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> .</span><span class="mtk11">afterClosed</span><span class="mtk1">()</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> .</span><span class="mtk11">subscribe</span><span class="mtk1">((</span><span class="mtk12">confirm</span><span class="mtk1">) </span><span class="mtk4">=&gt;</span><span class="mtk1"> {</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk15">if</span><span class="mtk1"> (</span><span class="mtk12">confirm</span><span class="mtk1">) {</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk4">this</span><span class="mtk1">.</span><span class="mtk12">dataSource</span><span class="mtk1"> = </span><span class="mtk4">this</span><span class="mtk1">.</span><span class="mtk12">dataSource</span><span class="mtk1">.</span><span class="mtk11">filter</span><span class="mtk1">((</span><span class="mtk12">u</span><span class="mtk1">: </span><span class="mtk10">any</span><span class="mtk1">) </span><span class="mtk4">=&gt;</span><span class="mtk1"> !</span><span class="mtk12">u</span><span class="mtk1">.</span><span class="mtk12">isSelected</span><span class="mtk1">);</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> }</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> });</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> }</span></span></span></code></pre> <p>We don’t need to add any code to the <code>confirm-dialog.component.ts</code> file because the cancel/delete buttons in the confirm dialog template contain a <code>mat-dialog-close</code> directive that automatically closes the dialog for us, and that’s all that we need for now.</p> <p>Let’s take a quick look at what we have so far:</p> <div data-youtube="KQ2pC47a7v0"> <button>Play Example</button> </div> <p>Below is the complete HTML template and component class code:</p> <pre class="grvsc-container default-dark" data-language="html" data-index="17"><code class="grvsc-code"><span class="grvsc-line"><span class="grvsc-source"><span class="mtk17">&lt;</span><span class="mtk4">article</span><span class="mtk1"> </span><span class="mtk12">class</span><span class="mtk1">=</span><span class="mtk8">&quot;table-header&quot;</span><span class="mtk17">&gt;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk17">&lt;</span><span class="mtk4">button</span><span class="mtk1"> </span><span class="mtk12">class</span><span class="mtk1">=</span><span class="mtk8">&quot;button-remove-rows&quot;</span><span class="mtk1"> </span><span class="mtk12">mat-button</span><span class="mtk1"> </span><span class="mtk12">(click)</span><span class="mtk1">=</span><span class="mtk8">&quot;removeSelectedRows()&quot;</span><span class="mtk17">&gt;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> Remove Rows</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk17">&lt;/</span><span class="mtk4">button</span><span class="mtk17">&gt;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk17">&lt;</span><span class="mtk4">button</span><span class="mtk1"> </span><span class="mtk12">class</span><span class="mtk1">=</span><span class="mtk8">&quot;button-add-row&quot;</span><span class="mtk1"> </span><span class="mtk12">mat-button</span><span class="mtk1"> </span><span class="mtk12">(click)</span><span class="mtk1">=</span><span class="mtk8">&quot;addRow()&quot;</span><span class="mtk17">&gt;</span><span class="mtk1">Add Row</span><span class="mtk17">&lt;/</span><span class="mtk4">button</span><span class="mtk17">&gt;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk17">&lt;/</span><span class="mtk4">article</span><span class="mtk17">&gt;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk17">&lt;</span><span class="mtk4">table</span><span class="mtk1"> </span><span class="mtk12">mat-table</span><span class="mtk1"> </span><span class="mtk12">[dataSource]</span><span class="mtk1">=</span><span class="mtk8">&quot;dataSource&quot;</span><span class="mtk17">&gt;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk17">&lt;</span><span class="mtk4">ng-container</span><span class="mtk1"> </span><span class="mtk12">[matColumnDef]</span><span class="mtk1">=</span><span class="mtk8">&quot;col.key&quot;</span><span class="mtk1"> </span><span class="mtk12">*ngFor</span><span class="mtk1">=</span><span class="mtk8">&quot;let col of columnsSchema&quot;</span><span class="mtk17">&gt;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk17">&lt;</span><span class="mtk4">th</span><span class="mtk1"> </span><span class="mtk12">mat-header-cell</span><span class="mtk1"> </span><span class="mtk12">*matHeaderCellDef</span><span class="mtk1"> </span><span class="mtk12">[ngSwitch]</span><span class="mtk1">=</span><span class="mtk8">&quot;col.key&quot;</span><span class="mtk17">&gt;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk17">&lt;</span><span class="mtk4">span</span><span class="mtk1"> </span><span class="mtk12">*ngSwitchCase</span><span class="mtk1">=</span><span class="mtk8">&quot;&#39;isSelected&#39;&quot;</span><span class="mtk17">&gt;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk17">&lt;</span><span class="mtk4">mat-checkbox</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">(change)</span><span class="mtk1">=</span><span class="mtk8">&quot;selectAll($event)&quot;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">[checked]</span><span class="mtk1">=</span><span class="mtk8">&quot;isAllSelected()&quot;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">[indeterminate]</span><span class="mtk1">=</span><span class="mtk8">&quot;!isAllSelected() &amp;&amp; isAnySelected()&quot;</span><span class="mtk17">&gt;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk17">&lt;/</span><span class="mtk4">mat-checkbox</span><span class="mtk17">&gt;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk17">&lt;/</span><span class="mtk4">span</span><span class="mtk17">&gt;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk17">&lt;</span><span class="mtk4">span</span><span class="mtk1"> </span><span class="mtk12">*ngSwitchDefault</span><span class="mtk17">&gt;</span><span class="mtk1">{{ col.label }}</span><span class="mtk17">&lt;/</span><span class="mtk4">span</span><span class="mtk17">&gt;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk17">&lt;/</span><span class="mtk4">th</span><span class="mtk17">&gt;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk17">&lt;</span><span class="mtk4">td</span><span class="mtk1"> </span><span class="mtk12">mat-cell</span><span class="mtk1"> </span><span class="mtk12">*matCellDef</span><span class="mtk1">=</span><span class="mtk8">&quot;let element&quot;</span><span class="mtk17">&gt;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk17">&lt;</span><span class="mtk4">div</span><span class="mtk1"> </span><span class="mtk12">[ngSwitch]</span><span class="mtk1">=</span><span class="mtk8">&quot;col.type&quot;</span><span class="mtk1"> </span><span class="mtk12">*ngIf</span><span class="mtk1">=</span><span class="mtk8">&quot;!element.isEdit&quot;</span><span class="mtk17">&gt;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk17">&lt;</span><span class="mtk4">ng-container</span><span class="mtk1"> </span><span class="mtk12">*ngSwitchCase</span><span class="mtk1">=</span><span class="mtk8">&quot;&#39;isSelected&#39;&quot;</span><span class="mtk17">&gt;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk17">&lt;</span><span class="mtk4">mat-checkbox</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">(change)</span><span class="mtk1">=</span><span class="mtk8">&quot;element.isSelected = $event.checked&quot;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">[checked]</span><span class="mtk1">=</span><span class="mtk8">&quot;element.isSelected&quot;</span><span class="mtk17">&gt;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk17">&lt;/</span><span class="mtk4">mat-checkbox</span><span class="mtk17">&gt;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk17">&lt;/</span><span class="mtk4">ng-container</span><span class="mtk17">&gt;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk17">&lt;</span><span class="mtk4">div</span><span class="mtk1"> </span><span class="mtk12">class</span><span class="mtk1">=</span><span class="mtk8">&quot;btn-edit&quot;</span><span class="mtk1"> </span><span class="mtk12">*ngSwitchCase</span><span class="mtk1">=</span><span class="mtk8">&quot;&#39;isEdit&#39;&quot;</span><span class="mtk17">&gt;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk17">&lt;</span><span class="mtk4">button</span><span class="mtk1"> </span><span class="mtk12">mat-button</span><span class="mtk1"> </span><span class="mtk12">(click)</span><span class="mtk1">=</span><span class="mtk8">&quot;element.isEdit = !element.isEdit&quot;</span><span class="mtk17">&gt;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> Edit</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk17">&lt;/</span><span class="mtk4">button</span><span class="mtk17">&gt;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk17">&lt;</span><span class="mtk4">button</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">mat-button</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">class</span><span class="mtk1">=</span><span class="mtk8">&quot;button-remove&quot;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">(click)</span><span class="mtk1">=</span><span class="mtk8">&quot;removeRow(element.id)&quot;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk17">&gt;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> Delete</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk17">&lt;/</span><span class="mtk4">button</span><span class="mtk17">&gt;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk17">&lt;/</span><span class="mtk4">div</span><span class="mtk17">&gt;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk17">&lt;</span><span class="mtk4">span</span><span class="mtk1"> </span><span class="mtk12">*ngSwitchDefault</span><span class="mtk17">&gt;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> {{ element[col.key] }}</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk17">&lt;/</span><span class="mtk4">span</span><span class="mtk17">&gt;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk17">&lt;/</span><span class="mtk4">div</span><span class="mtk17">&gt;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk17">&lt;</span><span class="mtk4">div</span><span class="mtk1"> </span><span class="mtk12">[ngSwitch]</span><span class="mtk1">=</span><span class="mtk8">&quot;col.type&quot;</span><span class="mtk1"> </span><span class="mtk12">*ngIf</span><span class="mtk1">=</span><span class="mtk8">&quot;element.isEdit&quot;</span><span class="mtk17">&gt;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk17">&lt;</span><span class="mtk4">div</span><span class="mtk1"> </span><span class="mtk12">*ngSwitchCase</span><span class="mtk1">=</span><span class="mtk8">&quot;&#39;isSelected&#39;&quot;</span><span class="mtk17">&gt;&lt;/</span><span class="mtk4">div</span><span class="mtk17">&gt;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk17">&lt;</span><span class="mtk4">div</span><span class="mtk1"> </span><span class="mtk12">class</span><span class="mtk1">=</span><span class="mtk8">&quot;btn-edit&quot;</span><span class="mtk1"> </span><span class="mtk12">*ngSwitchCase</span><span class="mtk1">=</span><span class="mtk8">&quot;&#39;isEdit&#39;&quot;</span><span class="mtk17">&gt;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk17">&lt;</span><span class="mtk4">button</span><span class="mtk1"> </span><span class="mtk12">mat-button</span><span class="mtk1"> </span><span class="mtk12">(click)</span><span class="mtk1">=</span><span class="mtk8">&quot;element.isEdit = !element.isEdit&quot;</span><span class="mtk17">&gt;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> Done</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk17">&lt;/</span><span class="mtk4">button</span><span class="mtk17">&gt;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk17">&lt;/</span><span class="mtk4">div</span><span class="mtk17">&gt;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk17">&lt;</span><span class="mtk4">mat-form-field</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">class</span><span class="mtk1">=</span><span class="mtk8">&quot;form-input&quot;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">*ngSwitchCase</span><span class="mtk1">=</span><span class="mtk8">&quot;&#39;date&#39;&quot;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">appearance</span><span class="mtk1">=</span><span class="mtk8">&quot;fill&quot;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk17">&gt;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk17">&lt;</span><span class="mtk4">mat-label</span><span class="mtk17">&gt;</span><span class="mtk1">Choose a date</span><span class="mtk17">&lt;/</span><span class="mtk4">mat-label</span><span class="mtk17">&gt;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk17">&lt;</span><span class="mtk4">input</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">matInput</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">[matDatepicker]</span><span class="mtk1">=</span><span class="mtk8">&quot;picker&quot;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">[(ngModel)]</span><span class="mtk1">=</span><span class="mtk8">&quot;element[col.key]&quot;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk17">/&gt;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk17">&lt;</span><span class="mtk4">mat-datepicker-toggle</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">matSuffix</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">[for]</span><span class="mtk1">=</span><span class="mtk8">&quot;picker&quot;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk17">&gt;&lt;/</span><span class="mtk4">mat-datepicker-toggle</span><span class="mtk17">&gt;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk17">&lt;</span><span class="mtk4">mat-datepicker</span><span class="mtk1"> </span><span class="mtk12">#picker</span><span class="mtk17">&gt;&lt;/</span><span class="mtk4">mat-datepicker</span><span class="mtk17">&gt;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk17">&lt;/</span><span class="mtk4">mat-form-field</span><span class="mtk17">&gt;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk17">&lt;</span><span class="mtk4">mat-form-field</span><span class="mtk1"> </span><span class="mtk12">class</span><span class="mtk1">=</span><span class="mtk8">&quot;form-input&quot;</span><span class="mtk1"> </span><span class="mtk12">*ngSwitchDefault</span><span class="mtk17">&gt;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk17">&lt;</span><span class="mtk4">input</span><span class="mtk1"> </span><span class="mtk12">[type]</span><span class="mtk1">=</span><span class="mtk8">&quot;col.type&quot;</span><span class="mtk1"> </span><span class="mtk12">matInput</span><span class="mtk1"> </span><span class="mtk12">[(ngModel)]</span><span class="mtk1">=</span><span class="mtk8">&quot;element[col.key]&quot;</span><span class="mtk1"> </span><span class="mtk17">/&gt;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk17">&lt;/</span><span class="mtk4">mat-form-field</span><span class="mtk17">&gt;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk17">&lt;/</span><span class="mtk4">div</span><span class="mtk17">&gt;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk17">&lt;/</span><span class="mtk4">td</span><span class="mtk17">&gt;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk17">&lt;/</span><span class="mtk4">ng-container</span><span class="mtk17">&gt;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk17">&lt;</span><span class="mtk4">tr</span><span class="mtk1"> </span><span class="mtk12">mat-header-row</span><span class="mtk1"> </span><span class="mtk12">*matHeaderRowDef</span><span class="mtk1">=</span><span class="mtk8">&quot;displayedColumns&quot;</span><span class="mtk17">&gt;&lt;/</span><span class="mtk4">tr</span><span class="mtk17">&gt;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk17">&lt;</span><span class="mtk4">tr</span><span class="mtk1"> </span><span class="mtk12">mat-row</span><span class="mtk1"> </span><span class="mtk12">*matRowDef</span><span class="mtk1">=</span><span class="mtk8">&quot;let row; columns: displayedColumns&quot;</span><span class="mtk17">&gt;&lt;/</span><span class="mtk4">tr</span><span class="mtk17">&gt;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk17">&lt;/</span><span class="mtk4">table</span><span class="mtk17">&gt;</span></span></span></code></pre> <pre class="grvsc-container default-dark" data-language="typescript" data-index="18"><code class="grvsc-code"><span class="grvsc-line"><span class="grvsc-source"><span class="mtk15">import</span><span class="mtk1"> { </span><span class="mtk12">Component</span><span class="mtk1"> } </span><span class="mtk15">from</span><span class="mtk1"> </span><span class="mtk8">&#39;@angular/core&#39;</span><span class="mtk1">;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk15">import</span><span class="mtk1"> { </span><span class="mtk12">MatDialog</span><span class="mtk1"> } </span><span class="mtk15">from</span><span class="mtk1"> </span><span class="mtk8">&#39;@angular/material/dialog&#39;</span><span class="mtk1">;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk15">import</span><span class="mtk1"> { </span><span class="mtk12">ConfirmDialogComponent</span><span class="mtk1"> } </span><span class="mtk15">from</span><span class="mtk1"> </span><span class="mtk8">&#39;./confirm-dialog/confirm-dialog.component&#39;</span><span class="mtk1">;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk4">const</span><span class="mtk1"> </span><span class="mtk12">USER_DATA</span><span class="mtk1"> = [</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> {</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">id:</span><span class="mtk1"> </span><span class="mtk7">1</span><span class="mtk1">,</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">name:</span><span class="mtk1"> </span><span class="mtk8">&#39;John Smith&#39;</span><span class="mtk1">,</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">occupation:</span><span class="mtk1"> </span><span class="mtk8">&#39;Advisor&#39;</span><span class="mtk1">,</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">dateOfBirth:</span><span class="mtk1"> </span><span class="mtk8">&#39;1984-05-05&#39;</span><span class="mtk1">,</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">age:</span><span class="mtk1"> </span><span class="mtk7">36</span><span class="mtk1">,</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> },</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> {</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">id:</span><span class="mtk1"> </span><span class="mtk7">2</span><span class="mtk1">,</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">name:</span><span class="mtk1"> </span><span class="mtk8">&#39;Muhi Masri&#39;</span><span class="mtk1">,</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">occupation:</span><span class="mtk1"> </span><span class="mtk8">&#39;Developer&#39;</span><span class="mtk1">,</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">dateOfBirth:</span><span class="mtk1"> </span><span class="mtk8">&#39;1992-02-02&#39;</span><span class="mtk1">,</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">age:</span><span class="mtk1"> </span><span class="mtk7">28</span><span class="mtk1">,</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> },</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> {</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">id:</span><span class="mtk1"> </span><span class="mtk7">3</span><span class="mtk1">,</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">name:</span><span class="mtk1"> </span><span class="mtk8">&#39;Peter Adams&#39;</span><span class="mtk1">,</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">occupation:</span><span class="mtk1"> </span><span class="mtk8">&#39;HR&#39;</span><span class="mtk1">,</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">dateOfBirth:</span><span class="mtk1"> </span><span class="mtk8">&#39;2000-01-01&#39;</span><span class="mtk1">,</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">age:</span><span class="mtk1"> </span><span class="mtk7">20</span><span class="mtk1">,</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> },</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> {</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">id:</span><span class="mtk1"> </span><span class="mtk7">4</span><span class="mtk1">,</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">name:</span><span class="mtk1"> </span><span class="mtk8">&#39;Lora Bay&#39;</span><span class="mtk1">,</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">occupation:</span><span class="mtk1"> </span><span class="mtk8">&#39;Marketing&#39;</span><span class="mtk1">,</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">dateOfBirth:</span><span class="mtk1"> </span><span class="mtk8">&#39;1977-03-03&#39;</span><span class="mtk1">,</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">age:</span><span class="mtk1"> </span><span class="mtk7">43</span><span class="mtk1">,</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> },</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1">];</span></span></span> <span class="grvsc-line"><span class="grvsc-source"></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk4">const</span><span class="mtk1"> </span><span class="mtk12">COLUMNS_SCHEMA</span><span class="mtk1"> = [</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> {</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">key:</span><span class="mtk1"> </span><span class="mtk8">&#39;isSelected&#39;</span><span class="mtk1">,</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">type:</span><span class="mtk1"> </span><span class="mtk8">&#39;isSelected&#39;</span><span class="mtk1">,</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">label:</span><span class="mtk1"> </span><span class="mtk8">&#39;&#39;</span><span class="mtk1">,</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> },</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> {</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">key:</span><span class="mtk1"> </span><span class="mtk8">&#39;name&#39;</span><span class="mtk1">,</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">type:</span><span class="mtk1"> </span><span class="mtk8">&#39;text&#39;</span><span class="mtk1">,</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">label:</span><span class="mtk1"> </span><span class="mtk8">&#39;Full Name&#39;</span><span class="mtk1">,</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> },</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> {</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">key:</span><span class="mtk1"> </span><span class="mtk8">&#39;occupation&#39;</span><span class="mtk1">,</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">type:</span><span class="mtk1"> </span><span class="mtk8">&#39;text&#39;</span><span class="mtk1">,</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">label:</span><span class="mtk1"> </span><span class="mtk8">&#39;Occupation&#39;</span><span class="mtk1">,</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> },</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> {</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">key:</span><span class="mtk1"> </span><span class="mtk8">&#39;dateOfBirth&#39;</span><span class="mtk1">,</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">type:</span><span class="mtk1"> </span><span class="mtk8">&#39;date&#39;</span><span class="mtk1">,</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">label:</span><span class="mtk1"> </span><span class="mtk8">&#39;Date of Birth&#39;</span><span class="mtk1">,</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> },</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> {</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">key:</span><span class="mtk1"> </span><span class="mtk8">&#39;age&#39;</span><span class="mtk1">,</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">type:</span><span class="mtk1"> </span><span class="mtk8">&#39;number&#39;</span><span class="mtk1">,</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">label:</span><span class="mtk1"> </span><span class="mtk8">&#39;Age&#39;</span><span class="mtk1">,</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> },</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> {</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">key:</span><span class="mtk1"> </span><span class="mtk8">&#39;isEdit&#39;</span><span class="mtk1">,</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">type:</span><span class="mtk1"> </span><span class="mtk8">&#39;isEdit&#39;</span><span class="mtk1">,</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">label:</span><span class="mtk1"> </span><span class="mtk8">&#39;&#39;</span><span class="mtk1">,</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> },</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1">];</span></span></span> <span class="grvsc-line"><span class="grvsc-source"></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1">@</span><span class="mtk11">Component</span><span class="mtk1">({</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">selector:</span><span class="mtk1"> </span><span class="mtk8">&#39;app-root&#39;</span><span class="mtk1">,</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">templateUrl:</span><span class="mtk1"> </span><span class="mtk8">&#39;./app.component.html&#39;</span><span class="mtk1">,</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">styleUrls:</span><span class="mtk1"> [</span><span class="mtk8">&#39;./app.component.scss&#39;</span><span class="mtk1">],</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1">})</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk15">export</span><span class="mtk1"> </span><span class="mtk4">class</span><span class="mtk1"> </span><span class="mtk10">AppComponent</span><span class="mtk1"> {</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">displayedColumns</span><span class="mtk1">: </span><span class="mtk10">string</span><span class="mtk1">[] = </span><span class="mtk12">COLUMNS_SCHEMA</span><span class="mtk1">.</span><span class="mtk11">map</span><span class="mtk1">((</span><span class="mtk12">col</span><span class="mtk1">) </span><span class="mtk4">=&gt;</span><span class="mtk1"> </span><span class="mtk12">col</span><span class="mtk1">.</span><span class="mtk12">key</span><span class="mtk1">);</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">dataSource</span><span class="mtk1"> = </span><span class="mtk12">USER_DATA</span><span class="mtk1">;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">columnsSchema</span><span class="mtk1">: </span><span class="mtk10">any</span><span class="mtk1"> = </span><span class="mtk12">COLUMNS_SCHEMA</span><span class="mtk1">;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk4">constructor</span><span class="mtk1">(</span><span class="mtk4">public</span><span class="mtk1"> </span><span class="mtk12">dialog</span><span class="mtk1">: </span><span class="mtk10">MatDialog</span><span class="mtk1">) {}</span></span></span> <span class="grvsc-line"><span class="grvsc-source"></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk11">addRow</span><span class="mtk1">() {</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk4">const</span><span class="mtk1"> </span><span class="mtk12">newRow</span><span class="mtk1"> = {</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">id:</span><span class="mtk1"> </span><span class="mtk10">Date</span><span class="mtk1">.</span><span class="mtk11">now</span><span class="mtk1">(),</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">name:</span><span class="mtk1"> </span><span class="mtk8">&#39;&#39;</span><span class="mtk1">,</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">occupation:</span><span class="mtk1"> </span><span class="mtk8">&#39;&#39;</span><span class="mtk1">,</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">dateOfBirth:</span><span class="mtk1"> </span><span class="mtk8">&#39;&#39;</span><span class="mtk1">,</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">age:</span><span class="mtk1"> </span><span class="mtk7">0</span><span class="mtk1">,</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">isEdit:</span><span class="mtk1"> </span><span class="mtk4">true</span><span class="mtk1">,</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> };</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk4">this</span><span class="mtk1">.</span><span class="mtk12">dataSource</span><span class="mtk1"> = [</span><span class="mtk12">newRow</span><span class="mtk1">, ...</span><span class="mtk4">this</span><span class="mtk1">.</span><span class="mtk12">dataSource</span><span class="mtk1">];</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> }</span></span></span> <span class="grvsc-line"><span class="grvsc-source"></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk11">removeRow</span><span class="mtk1">(</span><span class="mtk12">id</span><span class="mtk1">: </span><span class="mtk10">number</span><span class="mtk1">) {</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk4">this</span><span class="mtk1">.</span><span class="mtk12">dataSource</span><span class="mtk1"> = </span><span class="mtk4">this</span><span class="mtk1">.</span><span class="mtk12">dataSource</span><span class="mtk1">.</span><span class="mtk11">filter</span><span class="mtk1">((</span><span class="mtk12">u</span><span class="mtk1">) </span><span class="mtk4">=&gt;</span><span class="mtk1"> </span><span class="mtk12">u</span><span class="mtk1">.</span><span class="mtk12">id</span><span class="mtk1"> !== </span><span class="mtk12">id</span><span class="mtk1">);</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> }</span></span></span> <span class="grvsc-line"><span class="grvsc-source"></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk11">removeSelectedRows</span><span class="mtk1">() {</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk4">this</span><span class="mtk1">.</span><span class="mtk12">dialog</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> .</span><span class="mtk11">open</span><span class="mtk1">(</span><span class="mtk12">ConfirmDialogComponent</span><span class="mtk1">)</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> .</span><span class="mtk11">afterClosed</span><span class="mtk1">()</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> .</span><span class="mtk11">subscribe</span><span class="mtk1">((</span><span class="mtk12">confirm</span><span class="mtk1">) </span><span class="mtk4">=&gt;</span><span class="mtk1"> {</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk15">if</span><span class="mtk1"> (</span><span class="mtk12">confirm</span><span class="mtk1">) {</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk4">this</span><span class="mtk1">.</span><span class="mtk12">dataSource</span><span class="mtk1"> = </span><span class="mtk4">this</span><span class="mtk1">.</span><span class="mtk12">dataSource</span><span class="mtk1">.</span><span class="mtk11">filter</span><span class="mtk1">((</span><span class="mtk12">u</span><span class="mtk1">: </span><span class="mtk10">any</span><span class="mtk1">) </span><span class="mtk4">=&gt;</span><span class="mtk1"> !</span><span class="mtk12">u</span><span class="mtk1">.</span><span class="mtk12">isSelected</span><span class="mtk1">);</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> }</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> });</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> }</span></span></span> <span class="grvsc-line"><span class="grvsc-source"></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk11">isAllSelected</span><span class="mtk1">() {</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk15">return</span><span class="mtk1"> </span><span class="mtk4">this</span><span class="mtk1">.</span><span class="mtk12">dataSource</span><span class="mtk1">.</span><span class="mtk11">every</span><span class="mtk1">((</span><span class="mtk12">item</span><span class="mtk1">: </span><span class="mtk10">any</span><span class="mtk1">) </span><span class="mtk4">=&gt;</span><span class="mtk1"> </span><span class="mtk12">item</span><span class="mtk1">.</span><span class="mtk12">isSelected</span><span class="mtk1">);</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> }</span></span></span> <span class="grvsc-line"><span class="grvsc-source"></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk11">isAnySelected</span><span class="mtk1">() {</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk15">return</span><span class="mtk1"> </span><span class="mtk4">this</span><span class="mtk1">.</span><span class="mtk12">dataSource</span><span class="mtk1">.</span><span class="mtk11">some</span><span class="mtk1">((</span><span class="mtk12">item</span><span class="mtk1">: </span><span class="mtk10">any</span><span class="mtk1">) </span><span class="mtk4">=&gt;</span><span class="mtk1"> </span><span class="mtk12">item</span><span class="mtk1">.</span><span class="mtk12">isSelected</span><span class="mtk1">);</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> }</span></span></span> <span class="grvsc-line"><span class="grvsc-source"></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk11">selectAll</span><span class="mtk1">(</span><span class="mtk12">event</span><span class="mtk1">) {</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk4">this</span><span class="mtk1">.</span><span class="mtk12">dataSource</span><span class="mtk1"> = </span><span class="mtk4">this</span><span class="mtk1">.</span><span class="mtk12">dataSource</span><span class="mtk1">.</span><span class="mtk11">map</span><span class="mtk1">((</span><span class="mtk12">item</span><span class="mtk1">: </span><span class="mtk10">any</span><span class="mtk1">) </span><span class="mtk4">=&gt;</span><span class="mtk1"> ({</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> ...</span><span class="mtk12">item</span><span class="mtk1">,</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">isSelected:</span><span class="mtk1"> </span><span class="mtk12">event</span><span class="mtk1">.</span><span class="mtk12">checked</span><span class="mtk1">,</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> }));</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> }</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1">}</span></span></span></code></pre> <h2 id="summary" style="position:relative;"><a href="#summary" aria-label="summary permalink" class="anchor before"><svg aria-hidden="true" focusable="false" height="16" version="1.1" viewBox="0 0 16 16" width="16"><path fill-rule="evenodd" d="M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z"></path></svg></a>Summary</h2> <p>If you made it to this section, pat yourself on the back! You just learned how to:</p> <ul> <li>Add and remove table rows with Angular Material</li> <li>Enable checkbox column for multi-row selection</li> <li>Add confirmation dialog before removing rows</li> </ul> <p>You can access the <a href="https://github.com/muhimasri/angular-editable-table">complete repository here</a>.</p> <p>Bye for now 👋</p> <style class="grvsc-styles"> .grvsc-container { overflow: auto; position: relative; -webkit-overflow-scrolling: touch; padding-top: 1rem; padding-top: var(--grvsc-padding-top, var(--grvsc-padding-v, 1rem)); padding-bottom: 1rem; padding-bottom: var(--grvsc-padding-bottom, var(--grvsc-padding-v, 1rem)); border-radius: 8px; border-radius: var(--grvsc-border-radius, 8px); font-feature-settings: normal; line-height: 1.4; } .grvsc-code { display: table; } .grvsc-line { display: table-row; box-sizing: border-box; width: 100%; position: relative; } .grvsc-line > * { position: relative; } .grvsc-gutter-pad { display: table-cell; padding-left: 0.75rem; padding-left: calc(var(--grvsc-padding-left, var(--grvsc-padding-h, 1.5rem)) / 2); } .grvsc-gutter { display: table-cell; -webkit-user-select: none; -moz-user-select: none; user-select: none; } .grvsc-gutter::before { content: attr(data-content); } .grvsc-source { display: table-cell; padding-left: 1.5rem; padding-left: var(--grvsc-padding-left, var(--grvsc-padding-h, 1.5rem)); padding-right: 1.5rem; padding-right: var(--grvsc-padding-right, var(--grvsc-padding-h, 1.5rem)); } .grvsc-source:empty::after { content: ' '; -webkit-user-select: none; -moz-user-select: none; user-select: none; } .grvsc-gutter + .grvsc-source { padding-left: 0.75rem; padding-left: calc(var(--grvsc-padding-left, var(--grvsc-padding-h, 1.5rem)) / 2); } /* Line transformer styles */ .grvsc-has-line-highlighting > .grvsc-code > .grvsc-line::before { content: ' '; position: absolute; width: 100%; } .grvsc-line-diff-add::before { background-color: var(--grvsc-line-diff-add-background-color, rgba(0, 255, 60, 0.2)); } .grvsc-line-diff-del::before { background-color: var(--grvsc-line-diff-del-background-color, rgba(255, 0, 20, 0.2)); } .grvsc-line-number { padding: 0 2px; text-align: right; opacity: 0.7; } .default-dark { background-color: #1E1E1E; color: #D4D4D4; } .default-dark .mtk17 { color: #808080; } .default-dark .mtk4 { color: #569CD6; } .default-dark .mtk1 { color: #D4D4D4; } .default-dark .mtk12 { color: #9CDCFE; } .default-dark .mtk8 { color: #CE9178; } .default-dark .mtk15 { color: #C586C0; } .default-dark .mtk7 { color: #B5CEA8; } .default-dark .mtk11 { color: #DCDCAA; } .default-dark .mtk10 { color: #4EC9B0; } .default-dark .mtk14 { color: #F44747; } .default-dark .grvsc-line-highlighted::before { background-color: var(--grvsc-line-highlighted-background-color, rgba(255, 255, 255, 0.1)); box-shadow: inset var(--grvsc-line-highlighted-border-width, 4px) 0 0 0 var(--grvsc-line-highlighted-border-color, rgba(255, 255, 255, 0.5)); } </style><![CDATA[How to Use Emojis with CSS and Sass 💅]]>https://muhimasri.comhow-to-use-emojis-with-css-and-sasshttps://muhimasri.comhow-to-use-emojis-with-css-and-sass<p>I love emojis!💘 I mean, who doesn’t 😃</p> <p>Luckily, you can use them in all major browsers and operating systems. Emojis are unique characters from the UTF-8 (Unicode) character set. So all you need to do is copy and paste the emoji code in your HTML and you’re all done ✔</p> <p>But hang on, why am I writing this article then?🤔 Well, if you are using them extensively in your app and especially when providing an emoji list picker for users, you’ll need to keep a list of CSS emojis with unique names (just like what we do with icons).</p> <p>In this article, we will go through how you can use an emoji with CSS and do more complex automation using <a href="https://sass-lang.com/">Sass</a> (CSS preprocessor)</p> <h2 id="create-an-emoji-using-a-css-class" style="position:relative;"><a href="#create-an-emoji-using-a-css-class" aria-label="create an emoji using a css class permalink" class="anchor before"><svg aria-hidden="true" focusable="false" height="16" version="1.1" viewBox="0 0 16 16" width="16"><path fill-rule="evenodd" d="M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z"></path></svg></a>Create an emoji using a CSS class</h2> <p>Let’s create a plain HTML page with a CSS class:</p> <ul> <li>Create two classes, <code>em</code> for generic styling of the element and <code>emoji-name</code> for the specific emoji we need</li> <li>Use <code>:after</code> selector to add the emoji code in the <code>content</code> property</li> </ul> <pre class="grvsc-container default-dark" data-language="html" data-index="0"><code class="grvsc-code"><span class="grvsc-line"><span class="grvsc-source"><span class="mtk17">&lt;!</span><span class="mtk4">DOCTYPE</span><span class="mtk1"> </span><span class="mtk12">html</span><span class="mtk17">&gt;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk17">&lt;</span><span class="mtk4">html</span><span class="mtk17">&gt;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk17">&lt;</span><span class="mtk4">style</span><span class="mtk17">&gt;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk6">.em</span><span class="mtk1"> {</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">display</span><span class="mtk1">: </span><span class="mtk8">inline-block</span><span class="mtk1">;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> }</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk6">.grinning-face:after</span><span class="mtk1"> {</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">content</span><span class="mtk1">: </span><span class="mtk8">&quot;</span><span class="mtk6">\1F600</span><span class="mtk8">&quot;</span><span class="mtk1">;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> }</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk17">&lt;/</span><span class="mtk4">style</span><span class="mtk17">&gt;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk17">&lt;</span><span class="mtk4">body</span><span class="mtk17">&gt;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk17">&lt;</span><span class="mtk4">div</span><span class="mtk17">&gt;</span><span class="mtk1">Grinning Face: </span><span class="mtk17">&lt;</span><span class="mtk4">span</span><span class="mtk1"> </span><span class="mtk12">class</span><span class="mtk1">=</span><span class="mtk8">&quot;em grinning-face&quot;</span><span class="mtk17">&gt;&lt;/</span><span class="mtk4">span</span><span class="mtk17">&gt;&lt;/</span><span class="mtk4">div</span><span class="mtk17">&gt;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk17">&lt;</span><span class="mtk4">br</span><span class="mtk1"> </span><span class="mtk17">/&gt;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> Button Grinning Face:</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk17">&lt;</span><span class="mtk4">button</span><span class="mtk17">&gt;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk17">&lt;</span><span class="mtk4">span</span><span class="mtk1"> </span><span class="mtk12">class</span><span class="mtk1">=</span><span class="mtk8">&quot;em grinning-face&quot;</span><span class="mtk17">&gt;&lt;/</span><span class="mtk4">span</span><span class="mtk17">&gt;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> Click!</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk17">&lt;/</span><span class="mtk4">button</span><span class="mtk17">&gt;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk17">&lt;/</span><span class="mtk4">body</span><span class="mtk17">&gt;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk17">&lt;/</span><span class="mtk4">html</span><span class="mtk17">&gt;</span></span></span></code></pre> <p><code>em</code> class applies an inline display style to keep the emoji always aligned with the element it’s used with.</p> <p>Yes, it’s that simple! Here is what we should see when running the HTML page:</p> <p><span class="gatsby-resp-image-wrapper" style="position: relative; display: block; margin-left: auto; margin-right: auto; max-width: 417px; " > <span class="gatsby-resp-image-background-image" style="padding-bottom: 32.77777777777778%; position: relative; bottom: 0; left: 0; background-image: url('data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABQAAAAHCAIAAACHqfpvAAAACXBIWXMAAAsTAAALEwEAmpwYAAABEklEQVR42o2Ry06DUBCGeSmfz2VfxJ0PYExcqaktdyil3A6WSyFCY4UAB84FOrhiURP/1ZxJ/vN/MyMQSgkhjDFK6Thy3HVQj+OEu/poP+H2ZwLB+5YETdU/1mtd095f3w723rIsRZIDFEWB8rC6y8Lt7OXsthlj3DRN27Z1VV2+LxALHQI8lJwilwz9b/AieVEK0z/EOesHMtAJJqTwL6PDMHDOhd1uf0rTJEnP5zJEYRKn8TFOkrj4KuIoSpO0LIuq7j49WXxeBb5nqIZpmAghABRkSXEd1zKtPMuQj7yDp6ua49iSKOV57jkuCgIwI2f78ngf+K60kcSNGIbhbP4LdTknEAJ2T8Z5FUDNGBwImlcLIYdP1RQEFAAAAABJRU5ErkJggg=='); background-size: cover; display: block;" ></span> <img class="gatsby-resp-image-image" alt="CSS Emojis" title="" src="/static/984a31f659f3293cf0730636f0cc8781/f27fb/image-1.png" srcset="/static/984a31f659f3293cf0730636f0cc8781/e9ff0/image-1.png 180w, /static/984a31f659f3293cf0730636f0cc8781/f21e7/image-1.png 360w, /static/984a31f659f3293cf0730636f0cc8781/f27fb/image-1.png 417w" sizes="(max-width: 417px) 100vw, 417px" style="width:100%;height:100%;margin:0;vertical-align:middle;position:absolute;top:0;left:0;" loading="lazy" decoding="async" /> </span></p> <h2 id="add-multiple-emojis-using-css-variables" style="position:relative;"><a href="#add-multiple-emojis-using-css-variables" aria-label="add multiple emojis using css variables permalink" class="anchor before"><svg aria-hidden="true" focusable="false" height="16" version="1.1" viewBox="0 0 16 16" width="16"><path fill-rule="evenodd" d="M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z"></path></svg></a>Add multiple emojis using CSS variables</h2> <p>Let’s add few more emojis, but this time we will use CSS variables to store them. This approach will enable us to make the code more modular by managing variables independently from classes.</p> <pre class="grvsc-container default-dark" data-language="html" data-index="1"><code class="grvsc-code"><span class="grvsc-line"><span class="grvsc-source"><span class="mtk17">&lt;!</span><span class="mtk4">DOCTYPE</span><span class="mtk1"> </span><span class="mtk12">html</span><span class="mtk17">&gt;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk17">&lt;</span><span class="mtk4">html</span><span class="mtk17">&gt;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk17">&lt;</span><span class="mtk4">style</span><span class="mtk17">&gt;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk6">:root</span><span class="mtk1"> {</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">--grinning-face</span><span class="mtk1">: </span><span class="mtk8">&quot;</span><span class="mtk6">\1F600</span><span class="mtk8">&quot;</span><span class="mtk1">;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">--smiling-face-halo</span><span class="mtk1">: </span><span class="mtk8">&quot;</span><span class="mtk6">\1F607</span><span class="mtk8">&quot;</span><span class="mtk1">;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">--grinning-face-horns</span><span class="mtk1">: </span><span class="mtk8">&quot;</span><span class="mtk6">\1F608</span><span class="mtk8">&quot;</span><span class="mtk1">;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">--winking-face</span><span class="mtk1">: </span><span class="mtk8">&quot;</span><span class="mtk6">\1F609</span><span class="mtk8">&quot;</span><span class="mtk1">;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> }</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk6">.em</span><span class="mtk1"> {</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">display</span><span class="mtk1">: </span><span class="mtk8">inline-block</span><span class="mtk1">;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> }</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk6">.grinning-face:after</span><span class="mtk1"> {</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">content</span><span class="mtk1">: </span><span class="mtk11">var</span><span class="mtk1">(</span><span class="mtk12">--grinning-face</span><span class="mtk1">);</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> }</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk6">.smiling-face-halo:after</span><span class="mtk1"> {</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">content</span><span class="mtk1">: </span><span class="mtk11">var</span><span class="mtk1">(</span><span class="mtk12">--smiling-face-halo</span><span class="mtk1">);</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> }</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk6">.grinning-face-horns:after</span><span class="mtk1"> {</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">content</span><span class="mtk1">: </span><span class="mtk11">var</span><span class="mtk1">(</span><span class="mtk12">--grinning-face-horns</span><span class="mtk1">);</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> }</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk6">.winking-face:after</span><span class="mtk1"> {</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">content</span><span class="mtk1">: </span><span class="mtk11">var</span><span class="mtk1">(</span><span class="mtk12">--winking-face</span><span class="mtk1">);</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> }</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk17">&lt;/</span><span class="mtk4">style</span><span class="mtk17">&gt;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk17">&lt;</span><span class="mtk4">body</span><span class="mtk17">&gt;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk17">&lt;</span><span class="mtk4">span</span><span class="mtk1"> </span><span class="mtk12">class</span><span class="mtk1">=</span><span class="mtk8">&quot;em grinning-face&quot;</span><span class="mtk17">&gt;&lt;/</span><span class="mtk4">span</span><span class="mtk17">&gt;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk17">&lt;</span><span class="mtk4">span</span><span class="mtk1"> </span><span class="mtk12">class</span><span class="mtk1">=</span><span class="mtk8">&quot;em smiling-face-halo&quot;</span><span class="mtk17">&gt;&lt;/</span><span class="mtk4">span</span><span class="mtk17">&gt;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk17">&lt;</span><span class="mtk4">span</span><span class="mtk1"> </span><span class="mtk12">class</span><span class="mtk1">=</span><span class="mtk8">&quot;em grinning-face-horns&quot;</span><span class="mtk17">&gt;&lt;/</span><span class="mtk4">span</span><span class="mtk17">&gt;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk17">&lt;</span><span class="mtk4">span</span><span class="mtk1"> </span><span class="mtk12">class</span><span class="mtk1">=</span><span class="mtk8">&quot;em winking-face&quot;</span><span class="mtk17">&gt;&lt;/</span><span class="mtk4">span</span><span class="mtk17">&gt;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk17">&lt;/</span><span class="mtk4">body</span><span class="mtk17">&gt;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk17">&lt;/</span><span class="mtk4">html</span><span class="mtk17">&gt;</span></span></span></code></pre> <p>Now, we should see the following emojis updated on the page:</p> <p><span class="gatsby-resp-image-wrapper" style="position: relative; display: block; margin-left: auto; margin-right: auto; max-width: 210px; " > <span class="gatsby-resp-image-background-image" style="padding-bottom: 31.11111111111111%; position: relative; bottom: 0; left: 0; background-image: url('data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABQAAAAGCAIAAABM9SnKAAAACXBIWXMAAAsTAAALEwEAmpwYAAABEUlEQVR42mP4////v3///oMBnIEVYCpjAOLff/9fOr3t5L65Hz58BHL3nzh+dN+MgyeO//n///yxY8dmT947b+ajBw+BUhdPbj5zcAFEGdAIkObrl44dX2p7dZ3Zmb2TXr7+unRB2r5NkXOmJ7z/8Wtdae5ODZ5FSlyX9u57+PDS/plGl1caHtnWD9T19+8fkOb7t07Nb3OeVGF1au/krz/+718StXOq5u6FEb/+/z8wpWuOAvscfclHV68+fXxl61TTHVN1Tu2dDrIZovkv0Hkn9x7Yuvjzl89A7qOHd07uX/D40V0g+/Pnz3sXzzu7dxeQ/efP/yvn9585surzl68IZyOF0z8IgArC2P+R2UjqAZFVMWOACe1CAAAAAElFTkSuQmCC'); background-size: cover; display: block;" ></span> <img class="gatsby-resp-image-image" alt="CSS Emojis" title="" src="/static/d6f8322fa2f59226b7b6bd8a3d1b8f02/65ed1/image-2.png" srcset="/static/d6f8322fa2f59226b7b6bd8a3d1b8f02/e9ff0/image-2.png 180w, /static/d6f8322fa2f59226b7b6bd8a3d1b8f02/65ed1/image-2.png 210w" sizes="(max-width: 210px) 100vw, 210px" style="width:100%;height:100%;margin:0;vertical-align:middle;position:absolute;top:0;left:0;" loading="lazy" decoding="async" /> </span></p> <h2 id="autogenerate-classes-using-sass" style="position:relative;"><a href="#autogenerate-classes-using-sass" aria-label="autogenerate classes using sass permalink" class="anchor before"><svg aria-hidden="true" focusable="false" height="16" version="1.1" viewBox="0 0 16 16" width="16"><path fill-rule="evenodd" d="M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z"></path></svg></a>Autogenerate classes using Sass</h2> <p>Creating so many CSS classes can be a bit cumbersome and that’s why we have tools like Sass that can help simplify the process by extending CSS with extensive features. In this example, we are making use of maps and loops.</p> <p>Let’s take a closer look:</p> <ul> <li>Create a <code>map</code> of all the emoji names and codes we need. A <code>map</code> allows us to add a key/value pair</li> <li>Loop through the map using <code>@each</code> to generate classes</li> </ul> <pre class="grvsc-container default-dark" data-language="css" data-index="2"><code class="grvsc-code"><span class="grvsc-line"><span class="grvsc-source"><span class="mtk1">$emojis: (</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> &quot;</span><span class="mtk4">grinning-face</span><span class="mtk1">&quot;: &quot;</span><span class="mtk6">\1F600</span><span class="mtk1">&quot;,</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> &quot;</span><span class="mtk4">smiling-face-halo</span><span class="mtk1">&quot;: &quot;</span><span class="mtk6">\1F607</span><span class="mtk1">&quot;,</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> &quot;</span><span class="mtk4">grinning-face-horns</span><span class="mtk1">&quot;: &quot;</span><span class="mtk6">\1F608</span><span class="mtk1">&quot;,</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> &quot;</span><span class="mtk4">winking-face</span><span class="mtk1">&quot;: &quot;</span><span class="mtk6">\1F609</span><span class="mtk1">&quot;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1">);</span></span></span> <span class="grvsc-line"><span class="grvsc-source"></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk15">@each</span><span class="mtk1"> $name, $chars in $emojis {</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk6">.em-</span><span class="mtk1">#{$</span><span class="mtk12">name</span><span class="mtk1">}</span><span class="mtk6">:before</span><span class="mtk1"> {</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">display</span><span class="mtk1">: </span><span class="mtk8">inline-block</span><span class="mtk1">;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">content</span><span class="mtk1">: $chars;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> }</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1">}</span></span></span></code></pre> <p>The Sass code above will compile to the following CSS code:</p> <pre class="grvsc-container default-dark" data-language="css" data-index="3"><code class="grvsc-code"><span class="grvsc-line"><span class="grvsc-source"><span class="mtk15">@charset</span><span class="mtk1"> </span><span class="mtk8">&quot;UTF-8&quot;</span><span class="mtk1">;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk6">.em-grinning-face:before</span><span class="mtk1"> {</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">display</span><span class="mtk1">: </span><span class="mtk8">inline-block</span><span class="mtk1">;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">content</span><span class="mtk1">: </span><span class="mtk8">&quot;😀&quot;</span><span class="mtk1">;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1">}</span></span></span> <span class="grvsc-line"><span class="grvsc-source"></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk6">.em-smiling-face-halo:before</span><span class="mtk1"> {</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">display</span><span class="mtk1">: </span><span class="mtk8">inline-block</span><span class="mtk1">;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">content</span><span class="mtk1">: </span><span class="mtk8">&quot;😇&quot;</span><span class="mtk1">;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1">}</span></span></span> <span class="grvsc-line"><span class="grvsc-source"></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk6">.em-grinning-face-horns:before</span><span class="mtk1"> {</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">display</span><span class="mtk1">: </span><span class="mtk8">inline-block</span><span class="mtk1">;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">content</span><span class="mtk1">: </span><span class="mtk8">&quot;😈&quot;</span><span class="mtk1">;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1">}</span></span></span> <span class="grvsc-line"><span class="grvsc-source"></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk6">.em-winking-face:before</span><span class="mtk1"> {</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">display</span><span class="mtk1">: </span><span class="mtk8">inline-block</span><span class="mtk1">;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">content</span><span class="mtk1">: </span><span class="mtk8">&quot;😉&quot;</span><span class="mtk1">;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1">}</span></span></span></code></pre> <p><em>For simplicity purposes, we removed the <code>em</code> class and added the inline display style to each emoji</em></p> <h2 id="demo-example" style="position:relative;"><a href="#demo-example" aria-label="demo example permalink" class="anchor before"><svg aria-hidden="true" focusable="false" height="16" version="1.1" viewBox="0 0 16 16" width="16"><path fill-rule="evenodd" d="M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z"></path></svg></a>Demo example</h2> <iframe height="300" style="width: 100%;" scrolling="no" title="CSS Emojis" src="https://codepen.io/muhimasri/embed/zYwMGwr?default-tab=html%2Cresult" frameborder="no" loading="lazy" allowtransparency="true" allowfullscreen="true"> See the Pen <a href="https://codepen.io/muhimasri/pen/zYwMGwr"> CSS Emojis</a> by Muhi Masri (<a href="https://codepen.io/muhimasri">@muhimasri</a>) on <a href="https://codepen.io">CodePen</a>. </iframe> <h2 id="emoji-resources" style="position:relative;"><a href="#emoji-resources" aria-label="emoji resources permalink" class="anchor before"><svg aria-hidden="true" focusable="false" height="16" version="1.1" viewBox="0 0 16 16" width="16"><path fill-rule="evenodd" d="M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z"></path></svg></a>Emoji resources</h2> <p>Here are some useful resources I came across:</p> <ul> <li>A full emoji list (more than 3000) from <a href="https://unicode.org/emoji/charts/full-emoji-list.html">Unicode</a></li> <li>An <a href="https://www.npmjs.com/package/emojis-list">NPM package</a> with a complete list of emojis</li> </ul> <h2 id="final-thoughts" style="position:relative;"><a href="#final-thoughts" aria-label="final thoughts permalink" class="anchor before"><svg aria-hidden="true" focusable="false" height="16" version="1.1" viewBox="0 0 16 16" width="16"><path fill-rule="evenodd" d="M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z"></path></svg></a>Final thoughts</h2> <p>The technique used above is typically associated with generating icons but can be fully utilized for emojis or any Unicode based characters 🚀</p> <p>Bye for now 👋</p> <style class="grvsc-styles"> .grvsc-container { overflow: auto; position: relative; -webkit-overflow-scrolling: touch; padding-top: 1rem; padding-top: var(--grvsc-padding-top, var(--grvsc-padding-v, 1rem)); padding-bottom: 1rem; padding-bottom: var(--grvsc-padding-bottom, var(--grvsc-padding-v, 1rem)); border-radius: 8px; border-radius: var(--grvsc-border-radius, 8px); font-feature-settings: normal; line-height: 1.4; } .grvsc-code { display: table; } .grvsc-line { display: table-row; box-sizing: border-box; width: 100%; position: relative; } .grvsc-line > * { position: relative; } .grvsc-gutter-pad { display: table-cell; padding-left: 0.75rem; padding-left: calc(var(--grvsc-padding-left, var(--grvsc-padding-h, 1.5rem)) / 2); } .grvsc-gutter { display: table-cell; -webkit-user-select: none; -moz-user-select: none; user-select: none; } .grvsc-gutter::before { content: attr(data-content); } .grvsc-source { display: table-cell; padding-left: 1.5rem; padding-left: var(--grvsc-padding-left, var(--grvsc-padding-h, 1.5rem)); padding-right: 1.5rem; padding-right: var(--grvsc-padding-right, var(--grvsc-padding-h, 1.5rem)); } .grvsc-source:empty::after { content: ' '; -webkit-user-select: none; -moz-user-select: none; user-select: none; } .grvsc-gutter + .grvsc-source { padding-left: 0.75rem; padding-left: calc(var(--grvsc-padding-left, var(--grvsc-padding-h, 1.5rem)) / 2); } /* Line transformer styles */ .grvsc-has-line-highlighting > .grvsc-code > .grvsc-line::before { content: ' '; position: absolute; width: 100%; } .grvsc-line-diff-add::before { background-color: var(--grvsc-line-diff-add-background-color, rgba(0, 255, 60, 0.2)); } .grvsc-line-diff-del::before { background-color: var(--grvsc-line-diff-del-background-color, rgba(255, 0, 20, 0.2)); } .grvsc-line-number { padding: 0 2px; text-align: right; opacity: 0.7; } .default-dark { background-color: #1E1E1E; color: #D4D4D4; } .default-dark .mtk17 { color: #808080; } .default-dark .mtk4 { color: #569CD6; } .default-dark .mtk1 { color: #D4D4D4; } .default-dark .mtk12 { color: #9CDCFE; } .default-dark .mtk6 { color: #D7BA7D; } .default-dark .mtk8 { color: #CE9178; } .default-dark .mtk11 { color: #DCDCAA; } .default-dark .mtk15 { color: #C586C0; } .default-dark .grvsc-line-highlighted::before { background-color: var(--grvsc-line-highlighted-background-color, rgba(255, 255, 255, 0.1)); box-shadow: inset var(--grvsc-line-highlighted-border-width, 4px) 0 0 0 var(--grvsc-line-highlighted-border-color, rgba(255, 255, 255, 0.5)); } </style><![CDATA[How to Export HTML Table to Excel and CSV File]]>https://muhimasri.comhow-to-export-html-table-to-a-csv-filehttps://muhimasri.comhow-to-export-html-table-to-a-csv-file<p>Exporting data to Excel or CSV using the browser can sometimes be challenging, especially when creating a link element and mimicking a download click.</p> <p>In this tutorial, we will learn a simple approach to exporting an HTML table to Excel and CSV files using a couple of handy libraries.</p> <h2 id="initialize-project" style="position:relative;"><a href="#initialize-project" aria-label="initialize project permalink" class="anchor before"><svg aria-hidden="true" focusable="false" height="16" version="1.1" viewBox="0 0 16 16" width="16"><path fill-rule="evenodd" d="M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z"></path></svg></a>Initialize Project</h2> <p>The project will be vanilla Javascript using Vite as a build tool.</p> <p>Let’s create a new folder called “export-html-table”, navigate to it and run the following command to create a new package.json file:</p> <pre class="grvsc-container default-dark" data-language="" data-index="0"><code class="grvsc-code"><span class="grvsc-line"><span class="grvsc-source">npm init</span></span></code></pre> <p>A <code>package.json</code> file will be generated. Let’s replace it with the following:</p> <pre class="grvsc-container default-dark" data-language="json" data-index="1"><code class="grvsc-code"><span class="grvsc-line"><span class="grvsc-source"><span class="mtk1">{</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">&quot;name&quot;</span><span class="mtk1">: </span><span class="mtk8">&quot;export-html-table&quot;</span><span class="mtk1">,</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">&quot;version&quot;</span><span class="mtk1">: </span><span class="mtk8">&quot;1.0.0&quot;</span><span class="mtk1">,</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">&quot;scripts&quot;</span><span class="mtk1">: {</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">&quot;dev&quot;</span><span class="mtk1">: </span><span class="mtk8">&quot;vite&quot;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> },</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">&quot;dependencies&quot;</span><span class="mtk1">: {</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">&quot;file-saver&quot;</span><span class="mtk1">: </span><span class="mtk8">&quot;2.0.5&quot;</span><span class="mtk1">,</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">&quot;xlsx&quot;</span><span class="mtk1">: </span><span class="mtk8">&quot;^0.18.5&quot;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> },</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">&quot;devDependencies&quot;</span><span class="mtk1">: {</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">&quot;vite&quot;</span><span class="mtk1">: </span><span class="mtk8">&quot;^5.0.2&quot;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> }</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1">}</span></span></span></code></pre> <p>We added the dependencies for the project and configured the <code>dev</code> to use Vite.</p> <p>Here are more details about the dependencies we added:</p> <ul> <li><a href="https://vitejs.dev/">Vite</a>: A fast build tool that significantly improves the frontend development experience.</li> <li><a href="https://www.npmjs.com/package/file-saver">file-saver</a>: an excellent tool for saving files on the client side, especially if we generate a Blob object dynamically.</li> <li><a href="https://www.npmjs.com/package/xlsx">xlsx</a>: A library for reading and writing Excel files.</li> </ul> <p>Let’s install the dependencies by running the following command:</p> <pre class="grvsc-container default-dark" data-language="" data-index="2"><code class="grvsc-code"><span class="grvsc-line"><span class="grvsc-source">npm install</span></span></code></pre> <p>Lastly, we will add an <code>index.html</code> file and a <code>main.js</code> file.</p> <p>Here is how the project structure should look so far:</p> <p><span class="gatsby-resp-image-wrapper" style="position: relative; display: block; margin-left: auto; margin-right: auto; max-width: 525px; " > <a class="gatsby-resp-image-link" href="/static/654f98febd8926f2d9d2c1e9c7698c22/52211/project-structure.png" style="display: block" target="_blank" rel="noopener" > <span class="gatsby-resp-image-background-image" style="padding-bottom: 74.44444444444443%; position: relative; bottom: 0; left: 0; background-image: url('data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABQAAAAPCAYAAADkmO9VAAAACXBIWXMAACToAAAk6AGCYwUcAAAB/UlEQVR42qVTTXeaQBTNbwgoCA4UREX8wiCCfGgENNFqWv//qtuu200XvX0zJietrSbndHGZ9x7M5c59b25sy8JoNMbhcBB4+vQZy0WOoiiw3z/h8eEBQRBgt93heDziLriDoihQVfV3/OQr1b/eGAZDp9PFIs8RhiHieUI/GGIy8RFMQySUu66LeRxjvV5jPB5BqdcvE9bpZbPZhK7rcNptDIcDeF4Plm2j73kYDgbwfR+9Xg+yLEOS5HOyPwm5/CYz8IEf3R8jiiKEsxBev4/pdIrZLEKWZUjTFKZp/Ou454QqHEODxTShynW7aLUcoajb7VBsQ7q9FbhAdkZIgUNkNtMRkrqyXCGnpoTkX06+xlEoNjUajUtk5x4q6LgM7Q6jTTpMwwTjnjZ11Go1gStEfxPKsoJZZGES2LQm+LjbY5kvRNefP3rFc/6mh5alwyAfVbUBPkamSSoZE93nqwDFmqZTTX9bYRxbCEKHvFths65QViUN+Z7qMdIkw2pVorhfYbm8pzwlAuW6QtPUCFylQWq4KgNtmkk+m5qu0VgxOoUllHKVVxVKkoI0s2n2HMyTBTabClVVYbt9JDUJyqJEnuWwLftag14JeaBpqvDGbrWEfxwe3ZIW5RwnZdr7unwKTuDX8KWjXA3PX2rvHht6fP9fENk3Wn8QvvwC0xOdFYVzIP4AAAAASUVORK5CYII='); background-size: cover; display: block;" ></span> <img class="gatsby-resp-image-image" alt="project structure" title="" src="/static/654f98febd8926f2d9d2c1e9c7698c22/52211/project-structure.png" srcset="/static/654f98febd8926f2d9d2c1e9c7698c22/e9ff0/project-structure.png 180w, /static/654f98febd8926f2d9d2c1e9c7698c22/f21e7/project-structure.png 360w, /static/654f98febd8926f2d9d2c1e9c7698c22/52211/project-structure.png 525w" sizes="(max-width: 525px) 100vw, 525px" style="width:100%;height:100%;margin:0;vertical-align:middle;position:absolute;top:0;left:0;" loading="lazy" decoding="async" /> </a> </span></p> <h2 id="export-html-table-to-csv-file" style="position:relative;"><a href="#export-html-table-to-csv-file" aria-label="export html table to csv file permalink" class="anchor before"><svg aria-hidden="true" focusable="false" height="16" version="1.1" viewBox="0 0 16 16" width="16"><path fill-rule="evenodd" d="M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z"></path></svg></a>Export HTML Table to CSV File</h2> <p>To export an HTML table to a CSV file, we need to read all the content of the cells and convert them to CSV format.</p> <p>Let’s create a new function called <code>exportTable</code> in the <code>main.js</code> file and add the following code.</p> <pre class="grvsc-container default-dark" data-language="javascript" data-index="3"><code class="grvsc-code"><span class="grvsc-line"><span class="grvsc-source"><span class="mtk15">import</span><span class="mtk1"> { </span><span class="mtk12">saveAs</span><span class="mtk1"> } </span><span class="mtk15">from</span><span class="mtk1"> </span><span class="mtk8">&quot;file-saver&quot;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk15">export</span><span class="mtk1"> </span><span class="mtk4">const</span><span class="mtk1"> </span><span class="mtk11">exportTable</span><span class="mtk1"> = () </span><span class="mtk4">=&gt;</span><span class="mtk1"> {</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk4">const</span><span class="mtk1"> </span><span class="mtk12">rows</span><span class="mtk1"> = </span><span class="mtk12">document</span><span class="mtk1">.</span><span class="mtk11">querySelectorAll</span><span class="mtk1">(</span><span class="mtk8">&quot;table tr&quot;</span><span class="mtk1">)</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk4">let</span><span class="mtk1"> </span><span class="mtk12">csv</span><span class="mtk1"> = []</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk15">for</span><span class="mtk1"> (</span><span class="mtk4">const</span><span class="mtk1"> </span><span class="mtk12">row</span><span class="mtk1"> </span><span class="mtk4">of</span><span class="mtk1"> </span><span class="mtk12">rows</span><span class="mtk1">) {</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk4">const</span><span class="mtk1"> </span><span class="mtk12">cells</span><span class="mtk1"> = </span><span class="mtk12">row</span><span class="mtk1">.</span><span class="mtk11">querySelectorAll</span><span class="mtk1">(</span><span class="mtk8">&quot;td, th&quot;</span><span class="mtk1">)</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk4">const</span><span class="mtk1"> </span><span class="mtk12">rowText</span><span class="mtk1"> = </span><span class="mtk10">Array</span><span class="mtk1">.</span><span class="mtk11">from</span><span class="mtk1">(</span><span class="mtk12">cells</span><span class="mtk1">).</span><span class="mtk11">map</span><span class="mtk1">(</span><span class="mtk12">cell</span><span class="mtk1"> </span><span class="mtk4">=&gt;</span><span class="mtk1"> </span><span class="mtk12">cell</span><span class="mtk1">.</span><span class="mtk12">innerText</span><span class="mtk1">)</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">csv</span><span class="mtk1">.</span><span class="mtk11">push</span><span class="mtk1">(</span><span class="mtk12">rowText</span><span class="mtk1">.</span><span class="mtk11">join</span><span class="mtk1">(</span><span class="mtk8">&quot;,&quot;</span><span class="mtk1">))</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> }</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk4">const</span><span class="mtk1"> </span><span class="mtk12">csvFile</span><span class="mtk1"> = </span><span class="mtk4">new</span><span class="mtk1"> </span><span class="mtk10">Blob</span><span class="mtk1">([</span><span class="mtk12">csv</span><span class="mtk1">.</span><span class="mtk11">join</span><span class="mtk1">(</span><span class="mtk8">&quot;</span><span class="mtk6">\n</span><span class="mtk8">&quot;</span><span class="mtk1">)], {</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">type:</span><span class="mtk1"> </span><span class="mtk8">&quot;text/csv;charset=utf-8;&quot;</span><span class="mtk1">,</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> })</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk11">saveAs</span><span class="mtk1">(</span><span class="mtk12">csvFile</span><span class="mtk1">, </span><span class="mtk8">&quot;data.csv&quot;</span><span class="mtk1">)</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1">}</span></span></span></code></pre> <p>Here are more details of the code above:</p> <ul> <li>Get and loop through all the rows in the <code>table</code> element</li> <li>Within the loop, we are getting all the row’s cells and mapping them to a new <code>rowText</code> array with the <code>innerText</code> value</li> <li><code>rowText</code> is then converted to a text separated with a comma and pushed into the <code>csv</code> array (a list of all the final CSV rows)</li> <li>Finally, we are creating a <code>Blob</code> file and triggering the <code>saveAs</code> function that downloads the CSV file</li> </ul> <p>In the HTML file, we will add a basic table with some styles and a button to trigger the export function.</p> <pre class="grvsc-container default-dark" data-language="html" data-index="4"><code class="grvsc-code"><span class="grvsc-line"><span class="grvsc-source"><span class="mtk17">&lt;!</span><span class="mtk4">DOCTYPE</span><span class="mtk1"> </span><span class="mtk12">html</span><span class="mtk17">&gt;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk17">&lt;</span><span class="mtk4">html</span><span class="mtk17">&gt;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk17">&lt;</span><span class="mtk4">style</span><span class="mtk17">&gt;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk6">table</span><span class="mtk1"> {</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">text-align</span><span class="mtk1">: </span><span class="mtk8">left</span><span class="mtk1">;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">border-spacing</span><span class="mtk1">: </span><span class="mtk7">0</span><span class="mtk1">;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> }</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk6">table</span><span class="mtk1"> </span><span class="mtk6">th</span><span class="mtk1">,</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk6">td</span><span class="mtk1"> {</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">border</span><span class="mtk1">: </span><span class="mtk7">1px</span><span class="mtk1"> </span><span class="mtk8">solid</span><span class="mtk1"> </span><span class="mtk8">#ccc</span><span class="mtk1">;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> }</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk17">&lt;/</span><span class="mtk4">style</span><span class="mtk17">&gt;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk17">&lt;</span><span class="mtk4">body</span><span class="mtk17">&gt;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk17">&lt;</span><span class="mtk4">button</span><span class="mtk1"> </span><span class="mtk12">id</span><span class="mtk1">=</span><span class="mtk8">&quot;csvButton&quot;</span><span class="mtk17">&gt;</span><span class="mtk1">Export to CSV</span><span class="mtk17">&lt;/</span><span class="mtk4">button</span><span class="mtk17">&gt;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk17">&lt;</span><span class="mtk4">table</span><span class="mtk17">&gt;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk17">&lt;</span><span class="mtk4">tr</span><span class="mtk17">&gt;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk17">&lt;</span><span class="mtk4">th</span><span class="mtk17">&gt;</span><span class="mtk1">Name</span><span class="mtk17">&lt;/</span><span class="mtk4">th</span><span class="mtk17">&gt;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk17">&lt;</span><span class="mtk4">th</span><span class="mtk17">&gt;</span><span class="mtk1">Position</span><span class="mtk17">&lt;/</span><span class="mtk4">th</span><span class="mtk17">&gt;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk17">&lt;</span><span class="mtk4">th</span><span class="mtk17">&gt;</span><span class="mtk1">Experience</span><span class="mtk17">&lt;/</span><span class="mtk4">th</span><span class="mtk17">&gt;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk17">&lt;/</span><span class="mtk4">tr</span><span class="mtk17">&gt;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk17">&lt;</span><span class="mtk4">tr</span><span class="mtk17">&gt;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk17">&lt;</span><span class="mtk4">td</span><span class="mtk17">&gt;</span><span class="mtk1">John Smith</span><span class="mtk17">&lt;/</span><span class="mtk4">td</span><span class="mtk17">&gt;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk17">&lt;</span><span class="mtk4">td</span><span class="mtk17">&gt;</span><span class="mtk1">Marketing</span><span class="mtk17">&lt;/</span><span class="mtk4">td</span><span class="mtk17">&gt;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk17">&lt;</span><span class="mtk4">td</span><span class="mtk17">&gt;</span><span class="mtk1">5 Years</span><span class="mtk17">&lt;/</span><span class="mtk4">td</span><span class="mtk17">&gt;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk17">&lt;/</span><span class="mtk4">tr</span><span class="mtk17">&gt;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk17">&lt;</span><span class="mtk4">tr</span><span class="mtk17">&gt;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk17">&lt;</span><span class="mtk4">td</span><span class="mtk17">&gt;</span><span class="mtk1">Adam Kenneth</span><span class="mtk17">&lt;/</span><span class="mtk4">td</span><span class="mtk17">&gt;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk17">&lt;</span><span class="mtk4">td</span><span class="mtk17">&gt;</span><span class="mtk1">Development</span><span class="mtk17">&lt;/</span><span class="mtk4">td</span><span class="mtk17">&gt;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk17">&lt;</span><span class="mtk4">td</span><span class="mtk17">&gt;</span><span class="mtk1">3 Years</span><span class="mtk17">&lt;/</span><span class="mtk4">td</span><span class="mtk17">&gt;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk17">&lt;/</span><span class="mtk4">tr</span><span class="mtk17">&gt;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk17">&lt;</span><span class="mtk4">tr</span><span class="mtk17">&gt;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk17">&lt;</span><span class="mtk4">td</span><span class="mtk17">&gt;</span><span class="mtk1">Julia Williams</span><span class="mtk17">&lt;/</span><span class="mtk4">td</span><span class="mtk17">&gt;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk17">&lt;</span><span class="mtk4">td</span><span class="mtk17">&gt;</span><span class="mtk1">HR</span><span class="mtk17">&lt;/</span><span class="mtk4">td</span><span class="mtk17">&gt;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk17">&lt;</span><span class="mtk4">td</span><span class="mtk17">&gt;</span><span class="mtk1">12 Years</span><span class="mtk17">&lt;/</span><span class="mtk4">td</span><span class="mtk17">&gt;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk17">&lt;/</span><span class="mtk4">tr</span><span class="mtk17">&gt;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk17">&lt;/</span><span class="mtk4">table</span><span class="mtk17">&gt;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk17">&lt;/</span><span class="mtk4">body</span><span class="mtk17">&gt;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk17">&lt;</span><span class="mtk4">script</span><span class="mtk1"> </span><span class="mtk12">type</span><span class="mtk1">=</span><span class="mtk8">&quot;module&quot;</span><span class="mtk17">&gt;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk15">import</span><span class="mtk1"> { </span><span class="mtk12">exportTable</span><span class="mtk1"> } </span><span class="mtk15">from</span><span class="mtk1"> </span><span class="mtk8">&quot;./main.js&quot;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">document</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> .</span><span class="mtk11">querySelector</span><span class="mtk1">(</span><span class="mtk8">&quot;#csvButton&quot;</span><span class="mtk1">)</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> .</span><span class="mtk11">addEventListener</span><span class="mtk1">(</span><span class="mtk8">&quot;click&quot;</span><span class="mtk1">, () </span><span class="mtk4">=&gt;</span><span class="mtk1"> </span><span class="mtk11">exportTable</span><span class="mtk1">(</span><span class="mtk8">&quot;csv&quot;</span><span class="mtk1">))</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk17">&lt;/</span><span class="mtk4">script</span><span class="mtk17">&gt;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk17">&lt;/</span><span class="mtk4">html</span><span class="mtk17">&gt;</span></span></span></code></pre> <p>Additionally, we are importing the <code>exportTable</code> function from the <code>main.js</code> file and adding a <code>click</code> event listener to the button to trigger the export function.</p> <p>At this point, we can run the project using the following command:</p> <pre class="grvsc-container default-dark" data-language="" data-index="5"><code class="grvsc-code"><span class="grvsc-line"><span class="grvsc-source">npm run dev</span></span></code></pre> <p>And now we should be able to export the table to a CSV file.</p> <h2 id="export-html-table-to-excel-file" style="position:relative;"><a href="#export-html-table-to-excel-file" aria-label="export html table to excel file permalink" class="anchor before"><svg aria-hidden="true" focusable="false" height="16" version="1.1" viewBox="0 0 16 16" width="16"><path fill-rule="evenodd" d="M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z"></path></svg></a>Export HTML Table to Excel File</h2> <p>Exporting to an Excel file requires an additional library called “xlsx”, which we installed earlier. Let’s import it in the <code>main.js</code> file and update the <code>exportTable</code> function to support an Excel file.</p> <pre class="grvsc-container grvsc-has-line-highlighting default-dark" data-language="javascript" data-index="6"><code class="grvsc-code"><span class="grvsc-line"><span class="grvsc-source"><span class="mtk15">import</span><span class="mtk1"> { </span><span class="mtk12">saveAs</span><span class="mtk1"> } </span><span class="mtk15">from</span><span class="mtk1"> </span><span class="mtk8">&quot;file-saver&quot;</span></span></span> <span class="grvsc-line grvsc-line-highlighted"><span class="grvsc-source"><span class="mtk15">import</span><span class="mtk1"> </span><span class="mtk4">*</span><span class="mtk1"> </span><span class="mtk15">as</span><span class="mtk1"> </span><span class="mtk12">XLSX</span><span class="mtk1"> </span><span class="mtk15">from</span><span class="mtk1"> </span><span class="mtk8">&quot;xlsx&quot;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk15">export</span><span class="mtk1"> </span><span class="mtk4">const</span><span class="mtk1"> </span><span class="mtk11">exportTable</span><span class="mtk1"> = </span><span class="mtk12">format</span><span class="mtk1"> </span><span class="mtk4">=&gt;</span><span class="mtk1"> {</span></span></span> <span class="grvsc-line grvsc-line-highlighted"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk4">const</span><span class="mtk1"> </span><span class="mtk12">table</span><span class="mtk1"> = </span><span class="mtk12">document</span><span class="mtk1">.</span><span class="mtk11">querySelector</span><span class="mtk1">(</span><span class="mtk8">&quot;table&quot;</span><span class="mtk1">)</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk4">const</span><span class="mtk1"> </span><span class="mtk12">rows</span><span class="mtk1"> = </span><span class="mtk12">document</span><span class="mtk1">.</span><span class="mtk11">querySelectorAll</span><span class="mtk1">(</span><span class="mtk8">&quot;table tr&quot;</span><span class="mtk1">)</span></span></span> <span class="grvsc-line"><span class="grvsc-source"></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk15">if</span><span class="mtk1"> (</span><span class="mtk12">format</span><span class="mtk1"> === </span><span class="mtk8">&quot;csv&quot;</span><span class="mtk1">) {</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk4">let</span><span class="mtk1"> </span><span class="mtk12">csv</span><span class="mtk1"> = []</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk15">for</span><span class="mtk1"> (</span><span class="mtk4">const</span><span class="mtk1"> </span><span class="mtk12">row</span><span class="mtk1"> </span><span class="mtk4">of</span><span class="mtk1"> </span><span class="mtk12">rows</span><span class="mtk1">) {</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk4">const</span><span class="mtk1"> </span><span class="mtk12">cells</span><span class="mtk1"> = </span><span class="mtk12">row</span><span class="mtk1">.</span><span class="mtk11">querySelectorAll</span><span class="mtk1">(</span><span class="mtk8">&quot;td, th&quot;</span><span class="mtk1">)</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk4">const</span><span class="mtk1"> </span><span class="mtk12">rowText</span><span class="mtk1"> = </span><span class="mtk10">Array</span><span class="mtk1">.</span><span class="mtk11">from</span><span class="mtk1">(</span><span class="mtk12">cells</span><span class="mtk1">).</span><span class="mtk11">map</span><span class="mtk1">(</span><span class="mtk12">cell</span><span class="mtk1"> </span><span class="mtk4">=&gt;</span><span class="mtk1"> </span><span class="mtk12">cell</span><span class="mtk1">.</span><span class="mtk12">innerText</span><span class="mtk1">)</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">csv</span><span class="mtk1">.</span><span class="mtk11">push</span><span class="mtk1">(</span><span class="mtk12">rowText</span><span class="mtk1">.</span><span class="mtk11">join</span><span class="mtk1">(</span><span class="mtk8">&quot;,&quot;</span><span class="mtk1">))</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> }</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk4">const</span><span class="mtk1"> </span><span class="mtk12">csvFile</span><span class="mtk1"> = </span><span class="mtk4">new</span><span class="mtk1"> </span><span class="mtk10">Blob</span><span class="mtk1">([</span><span class="mtk12">csv</span><span class="mtk1">.</span><span class="mtk11">join</span><span class="mtk1">(</span><span class="mtk8">&quot;</span><span class="mtk6">\n</span><span class="mtk8">&quot;</span><span class="mtk1">)], {</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">type:</span><span class="mtk1"> </span><span class="mtk8">&quot;text/csv;charset=utf-8;&quot;</span><span class="mtk1">,</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> })</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk11">saveAs</span><span class="mtk1">(</span><span class="mtk12">csvFile</span><span class="mtk1">, </span><span class="mtk8">&quot;data.csv&quot;</span><span class="mtk1">)</span></span></span> <span class="grvsc-line grvsc-line-highlighted"><span class="grvsc-source"><span class="mtk1"> } </span><span class="mtk15">else</span><span class="mtk1"> </span><span class="mtk15">if</span><span class="mtk1"> (</span><span class="mtk12">format</span><span class="mtk1"> === </span><span class="mtk8">&quot;excel&quot;</span><span class="mtk1">) {</span></span></span> <span class="grvsc-line grvsc-line-highlighted"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk4">const</span><span class="mtk1"> </span><span class="mtk12">workbook</span><span class="mtk1"> = </span><span class="mtk12">XLSX</span><span class="mtk1">.</span><span class="mtk12">utils</span><span class="mtk1">.</span><span class="mtk11">table_to_book</span><span class="mtk1">(</span><span class="mtk12">table</span><span class="mtk1">)</span></span></span> <span class="grvsc-line grvsc-line-highlighted"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk4">const</span><span class="mtk1"> </span><span class="mtk12">options</span><span class="mtk1"> = { </span><span class="mtk12">bookType:</span><span class="mtk1"> </span><span class="mtk8">&quot;xlsx&quot;</span><span class="mtk1">, </span><span class="mtk12">bookSST:</span><span class="mtk1"> </span><span class="mtk4">false</span><span class="mtk1">, </span><span class="mtk12">type:</span><span class="mtk1"> </span><span class="mtk8">&quot;array&quot;</span><span class="mtk1"> }</span></span></span> <span class="grvsc-line grvsc-line-highlighted"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk4">const</span><span class="mtk1"> </span><span class="mtk12">output</span><span class="mtk1"> = </span><span class="mtk12">XLSX</span><span class="mtk1">.</span><span class="mtk11">write</span><span class="mtk1">(</span><span class="mtk12">workbook</span><span class="mtk1">, </span><span class="mtk12">options</span><span class="mtk1">)</span></span></span> <span class="grvsc-line grvsc-line-highlighted"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk11">saveAs</span><span class="mtk1">(</span></span></span> <span class="grvsc-line grvsc-line-highlighted"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk4">new</span><span class="mtk1"> </span><span class="mtk10">Blob</span><span class="mtk1">([</span><span class="mtk12">output</span><span class="mtk1">], { </span><span class="mtk12">type:</span><span class="mtk1"> </span><span class="mtk8">&quot;application/octet-stream&quot;</span><span class="mtk1"> }),</span></span></span> <span class="grvsc-line grvsc-line-highlighted"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk8">&quot;data.xlsx&quot;</span></span></span> <span class="grvsc-line grvsc-line-highlighted"><span class="grvsc-source"><span class="mtk1"> )</span></span></span> <span class="grvsc-line grvsc-line-highlighted"><span class="grvsc-source"><span class="mtk1"> } </span><span class="mtk15">else</span><span class="mtk1"> {</span></span></span> <span class="grvsc-line grvsc-line-highlighted"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk15">throw</span><span class="mtk1"> </span><span class="mtk4">new</span><span class="mtk1"> </span><span class="mtk10">Error</span><span class="mtk1">(</span><span class="mtk8">&quot;Unsupported format&quot;</span><span class="mtk1">)</span></span></span> <span class="grvsc-line grvsc-line-highlighted"><span class="grvsc-source"><span class="mtk1"> }</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1">}</span></span></span></code></pre> <p>In the code above, we check if the format is <code>csv</code> or <code>excel</code> and execute the appropriate code. For the Excel file, we use the <code>table_to_book</code> function to convert the table to a workbook and then the <code>write</code> function to convert the workbook to an Excel file.</p> <p>Now, we can update the HTML file to support the Excel export.</p> <pre class="grvsc-container grvsc-has-line-highlighting default-dark" data-language="html" data-index="7"><code class="grvsc-code"><span class="grvsc-line"><span class="grvsc-source"><span class="mtk17">&lt;!</span><span class="mtk4">DOCTYPE</span><span class="mtk1"> </span><span class="mtk12">html</span><span class="mtk17">&gt;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk17">&lt;</span><span class="mtk4">html</span><span class="mtk17">&gt;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk17">&lt;</span><span class="mtk4">style</span><span class="mtk17">&gt;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk6">table</span><span class="mtk1"> {</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">text-align</span><span class="mtk1">: </span><span class="mtk8">left</span><span class="mtk1">;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">border-spacing</span><span class="mtk1">: </span><span class="mtk7">0</span><span class="mtk1">;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> }</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk6">table</span><span class="mtk1"> </span><span class="mtk6">th</span><span class="mtk1">, </span><span class="mtk6">td</span><span class="mtk1"> {</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">border</span><span class="mtk1">: </span><span class="mtk7">1px</span><span class="mtk1"> </span><span class="mtk8">solid</span><span class="mtk1"> </span><span class="mtk8">#ccc</span><span class="mtk1">;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> }</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk17">&lt;/</span><span class="mtk4">style</span><span class="mtk17">&gt;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk17">&lt;</span><span class="mtk4">body</span><span class="mtk17">&gt;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk17">&lt;</span><span class="mtk4">button</span><span class="mtk1"> </span><span class="mtk12">id</span><span class="mtk1">=</span><span class="mtk8">&quot;csvButton&quot;</span><span class="mtk17">&gt;</span><span class="mtk1">Export to CSV</span><span class="mtk17">&lt;/</span><span class="mtk4">button</span><span class="mtk17">&gt;</span></span></span> <span class="grvsc-line grvsc-line-highlighted"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk17">&lt;</span><span class="mtk4">button</span><span class="mtk1"> </span><span class="mtk12">id</span><span class="mtk1">=</span><span class="mtk8">&quot;excelButton&quot;</span><span class="mtk17">&gt;</span><span class="mtk1">Export to Excel</span><span class="mtk17">&lt;/</span><span class="mtk4">button</span><span class="mtk17">&gt;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk17">&lt;</span><span class="mtk4">table</span><span class="mtk17">&gt;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk17">&lt;</span><span class="mtk4">tr</span><span class="mtk17">&gt;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk17">&lt;</span><span class="mtk4">th</span><span class="mtk17">&gt;</span><span class="mtk1">Name</span><span class="mtk17">&lt;/</span><span class="mtk4">th</span><span class="mtk17">&gt;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk17">&lt;</span><span class="mtk4">th</span><span class="mtk17">&gt;</span><span class="mtk1">Position</span><span class="mtk17">&lt;/</span><span class="mtk4">th</span><span class="mtk17">&gt;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk17">&lt;</span><span class="mtk4">th</span><span class="mtk17">&gt;</span><span class="mtk1">Experience</span><span class="mtk17">&lt;/</span><span class="mtk4">th</span><span class="mtk17">&gt;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk17">&lt;/</span><span class="mtk4">tr</span><span class="mtk17">&gt;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk17">&lt;</span><span class="mtk4">tr</span><span class="mtk17">&gt;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk17">&lt;</span><span class="mtk4">td</span><span class="mtk17">&gt;</span><span class="mtk1">John Smith</span><span class="mtk17">&lt;/</span><span class="mtk4">td</span><span class="mtk17">&gt;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk17">&lt;</span><span class="mtk4">td</span><span class="mtk17">&gt;</span><span class="mtk1">Marketing</span><span class="mtk17">&lt;/</span><span class="mtk4">td</span><span class="mtk17">&gt;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk17">&lt;</span><span class="mtk4">td</span><span class="mtk17">&gt;</span><span class="mtk1">5 Years</span><span class="mtk17">&lt;/</span><span class="mtk4">td</span><span class="mtk17">&gt;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk17">&lt;/</span><span class="mtk4">tr</span><span class="mtk17">&gt;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk17">&lt;</span><span class="mtk4">tr</span><span class="mtk17">&gt;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk17">&lt;</span><span class="mtk4">td</span><span class="mtk17">&gt;</span><span class="mtk1">Adam Kenneth</span><span class="mtk17">&lt;/</span><span class="mtk4">td</span><span class="mtk17">&gt;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk17">&lt;</span><span class="mtk4">td</span><span class="mtk17">&gt;</span><span class="mtk1">Development</span><span class="mtk17">&lt;/</span><span class="mtk4">td</span><span class="mtk17">&gt;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk17">&lt;</span><span class="mtk4">td</span><span class="mtk17">&gt;</span><span class="mtk1">3 Years</span><span class="mtk17">&lt;/</span><span class="mtk4">td</span><span class="mtk17">&gt;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk17">&lt;/</span><span class="mtk4">tr</span><span class="mtk17">&gt;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk17">&lt;</span><span class="mtk4">tr</span><span class="mtk17">&gt;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk17">&lt;</span><span class="mtk4">td</span><span class="mtk17">&gt;</span><span class="mtk1">Julia Williams</span><span class="mtk17">&lt;/</span><span class="mtk4">td</span><span class="mtk17">&gt;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk17">&lt;</span><span class="mtk4">td</span><span class="mtk17">&gt;</span><span class="mtk1">HR</span><span class="mtk17">&lt;/</span><span class="mtk4">td</span><span class="mtk17">&gt;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk17">&lt;</span><span class="mtk4">td</span><span class="mtk17">&gt;</span><span class="mtk1">12 Years</span><span class="mtk17">&lt;/</span><span class="mtk4">td</span><span class="mtk17">&gt;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk17">&lt;/</span><span class="mtk4">tr</span><span class="mtk17">&gt;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk17">&lt;/</span><span class="mtk4">table</span><span class="mtk17">&gt;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk17">&lt;/</span><span class="mtk4">body</span><span class="mtk17">&gt;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk17">&lt;</span><span class="mtk4">script</span><span class="mtk1"> </span><span class="mtk12">type</span><span class="mtk1">=</span><span class="mtk8">&quot;module&quot;</span><span class="mtk17">&gt;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk15">import</span><span class="mtk1"> { </span><span class="mtk12">exportTable</span><span class="mtk1"> } </span><span class="mtk15">from</span><span class="mtk1"> </span><span class="mtk8">&#39;./main.js&#39;</span><span class="mtk1">;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">document</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> .</span><span class="mtk11">querySelector</span><span class="mtk1">(</span><span class="mtk8">&#39;#csvButton&#39;</span><span class="mtk1">)</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> .</span><span class="mtk11">addEventListener</span><span class="mtk1">(</span><span class="mtk8">&#39;click&#39;</span><span class="mtk1">, () </span><span class="mtk4">=&gt;</span><span class="mtk1"> </span><span class="mtk11">exportTable</span><span class="mtk1">(</span><span class="mtk8">&#39;csv&#39;</span><span class="mtk1">));</span></span></span> <span class="grvsc-line"><span class="grvsc-source"></span></span> <span class="grvsc-line grvsc-line-highlighted"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">document</span></span></span> <span class="grvsc-line grvsc-line-highlighted"><span class="grvsc-source"><span class="mtk1"> .</span><span class="mtk11">querySelector</span><span class="mtk1">(</span><span class="mtk8">&#39;#excelButton&#39;</span><span class="mtk1">)</span></span></span> <span class="grvsc-line grvsc-line-highlighted"><span class="grvsc-source"><span class="mtk1"> .</span><span class="mtk11">addEventListener</span><span class="mtk1">(</span><span class="mtk8">&#39;click&#39;</span><span class="mtk1">, () </span><span class="mtk4">=&gt;</span><span class="mtk1"> </span><span class="mtk11">exportTable</span><span class="mtk1">(</span><span class="mtk8">&#39;excel&#39;</span><span class="mtk1">));</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk17">&lt;/</span><span class="mtk4">script</span><span class="mtk17">&gt;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk17">&lt;/</span><span class="mtk4">html</span><span class="mtk17">&gt;</span></span></span></code></pre> <p>And that’s it! We can now export the table to an Excel file.</p> <h2 id="summary" style="position:relative;"><a href="#summary" aria-label="summary permalink" class="anchor before"><svg aria-hidden="true" focusable="false" height="16" version="1.1" viewBox="0 0 16 16" width="16"><path fill-rule="evenodd" d="M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z"></path></svg></a>Summary</h2> <p>In this tutorial, we learned how to export an HTML table to CSV and Excel with one function that accepts a format parameter. The project is configured with Vite and has two dependencies: <code>file-saver</code> and <code>xlsx</code>, but it’s using vanilla Javascript and doesn’t require any additional frameworks like React or Vue.</p> <p>The complete code is available in <a href="https://github.com/muhimasri/export-csv-excel">this repository</a>.</p> <p>Bye for now 👋</p> <style class="grvsc-styles"> .grvsc-container { overflow: auto; position: relative; -webkit-overflow-scrolling: touch; padding-top: 1rem; padding-top: var(--grvsc-padding-top, var(--grvsc-padding-v, 1rem)); padding-bottom: 1rem; padding-bottom: var(--grvsc-padding-bottom, var(--grvsc-padding-v, 1rem)); border-radius: 8px; border-radius: var(--grvsc-border-radius, 8px); font-feature-settings: normal; line-height: 1.4; } .grvsc-code { display: table; } .grvsc-line { display: table-row; box-sizing: border-box; width: 100%; position: relative; } .grvsc-line > * { position: relative; } .grvsc-gutter-pad { display: table-cell; padding-left: 0.75rem; padding-left: calc(var(--grvsc-padding-left, var(--grvsc-padding-h, 1.5rem)) / 2); } .grvsc-gutter { display: table-cell; -webkit-user-select: none; -moz-user-select: none; user-select: none; } .grvsc-gutter::before { content: attr(data-content); } .grvsc-source { display: table-cell; padding-left: 1.5rem; padding-left: var(--grvsc-padding-left, var(--grvsc-padding-h, 1.5rem)); padding-right: 1.5rem; padding-right: var(--grvsc-padding-right, var(--grvsc-padding-h, 1.5rem)); } .grvsc-source:empty::after { content: ' '; -webkit-user-select: none; -moz-user-select: none; user-select: none; } .grvsc-gutter + .grvsc-source { padding-left: 0.75rem; padding-left: calc(var(--grvsc-padding-left, var(--grvsc-padding-h, 1.5rem)) / 2); } /* Line transformer styles */ .grvsc-has-line-highlighting > .grvsc-code > .grvsc-line::before { content: ' '; position: absolute; width: 100%; } .grvsc-line-diff-add::before { background-color: var(--grvsc-line-diff-add-background-color, rgba(0, 255, 60, 0.2)); } .grvsc-line-diff-del::before { background-color: var(--grvsc-line-diff-del-background-color, rgba(255, 0, 20, 0.2)); } .grvsc-line-number { padding: 0 2px; text-align: right; opacity: 0.7; } .default-dark { background-color: #1E1E1E; color: #D4D4D4; } .default-dark .mtk1 { color: #D4D4D4; } .default-dark .mtk12 { color: #9CDCFE; } .default-dark .mtk8 { color: #CE9178; } .default-dark .mtk15 { color: #C586C0; } .default-dark .mtk4 { color: #569CD6; } .default-dark .mtk11 { color: #DCDCAA; } .default-dark .mtk10 { color: #4EC9B0; } .default-dark .mtk6 { color: #D7BA7D; } .default-dark .mtk17 { color: #808080; } .default-dark .mtk7 { color: #B5CEA8; } .default-dark .grvsc-line-highlighted::before { background-color: var(--grvsc-line-highlighted-background-color, rgba(255, 255, 255, 0.1)); box-shadow: inset var(--grvsc-line-highlighted-border-width, 4px) 0 0 0 var(--grvsc-line-highlighted-border-color, rgba(255, 255, 255, 0.5)); } </style><![CDATA[Finally, a Custom File Upload that Works Everywhere!]]>https://muhimasri.comfinally-a-file-upload-component-that-works-everywherehttps://muhimasri.comfinally-a-file-upload-component-that-works-everywhere<p>I love JavaScript and all the amazing engineers who helped to make Web Development simpler and more joyful. But, as a consultant and UI engineer, I always ask myself the same question “why do I have to write the same exact custom element every time I start a new project?” Whether it’s Vue, React, Angular… I always end up writing the same code again and again and again.</p> <h3 id="web-components-to-the-rescue" style="position:relative;"><a href="#web-components-to-the-rescue" aria-label="web components to the rescue permalink" class="anchor before"><svg aria-hidden="true" focusable="false" height="16" version="1.1" viewBox="0 0 16 16" width="16"><path fill-rule="evenodd" d="M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z"></path></svg></a>Web Components to the rescue!</h3> <p><img src="/a5cf24de241cd16d491a7cbcf1dd2fbc/main.html-Google-Chrome-2021-07-11-10-01-31_Trim.gif" alt="Upload File Component"></p> <p>I’ve always been a big fan of Web Components since <a href="https://polymer-library.polymer-project.org/">Polymer</a> took the initiative to simplify and make it more declarative. The fact that you can write it once and use it anywhere is just so appealing to me as a UI architect. I’m not saying that Web Components is the way to go and will replace frameworks in the future. I just think it will coexist with other frameworks as a base layer for more generic custom elements such as buttons, checkboxes, file uploaders…etc. It is a perfect solution to build a design system that can be used across the whole organization, even if the tech stack is different.</p> <p>OK, let’s cut to the chase…</p> <p><img src="https://media1.giphy.com/media/GB6UYNtzn5XuE/giphy.gif?cid=ecf05e47d9tz0rcxj7cvm340a8ar7shm1a32gws2cswbwl96&#x26;rid=giphy.gif&#x26;ct=g" alt="talking john cage GIF"></p> <p>The reason why I’m writing this article is to show you how to create a custom file upload element in vanilla JavaScript that can be used in any library/framework. I decided for the first time to take the step and create a Web Component and successfully use it in multiple different real-world projects without having to write the same code ever again.</p> <h2 id="initialize-a-web-component" style="position:relative;"><a href="#initialize-a-web-component" aria-label="initialize a web component permalink" class="anchor before"><svg aria-hidden="true" focusable="false" height="16" version="1.1" viewBox="0 0 16 16" width="16"><path fill-rule="evenodd" d="M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z"></path></svg></a>Initialize a Web Component</h2> <p>Open your favorite JavaScript editor or simply create a folder with just two Notepad files!</p> <ul> <li><code>file-upload.js</code> file for the File Upload Component.</li> <li><code>main.html</code> file to consume the web component.</li> </ul> <p><span class="gatsby-resp-image-wrapper" style="position: relative; display: block; margin-left: auto; margin-right: auto; max-width: 720px; " > <a class="gatsby-resp-image-link" href="/static/3b1aa5e68a25ab3130728de145ddbf61/2bef9/image-1024x561.png" style="display: block" target="_blank" rel="noopener" > <span class="gatsby-resp-image-background-image" style="padding-bottom: 55.00000000000001%; position: relative; bottom: 0; left: 0; background-image: url('data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABQAAAALCAYAAAB/Ca1DAAAACXBIWXMAAAsTAAALEwEAmpwYAAABl0lEQVR42o2S626CQBCFeQgvMd5AQUAUtILGu7H6o2nap/KNDEkt6nOZCpmeWV2VpIn9cTLDzOznWXeU9fp1M5/PD7PZbLtYLELkIUeZTyYTIVlbLtN11nQ63aJ2RNwo7x+f+/F4TL4fxJ7XoU6nS93uC7muS7Ztk2VZQq1W6ybHcW71q+JrLVL6/f43foVWq/WPbTcTy7KTdttNVE1LisViUiqVLkIuv3O5XJLJZB77P+VymRB3ShAEked51Ha92DQtajRMMi2bNK1GPFSpVIQ4LxQKlM/nRQSUAKRqtcr9mCMUKYPBIGo2HarV6rFhNOgik1RVw2AayLBsNitAnP8JHI1GkeO0SNeNp0ApCcYVZf8OHA6H/wI+ghnE7h7qd2Cv1xNXfgbkA/V6HXM6+gb+64a8bhro+/4Or4th4wToWUpV1TMGU8IB9PQzgEL8fe2drsAvBQu9x5qwM/HKLKwOHql2cyadsDPeO3anadqtB8UwcHE4nr9tgsHogNXZmqYZ4oAQrhdiKCW4CwETEcDH3hY6Qptf8aYrPeE3tlYAAAAASUVORK5CYII='); background-size: cover; display: block;" ></span> <img class="gatsby-resp-image-image" alt="Upload File Component" title="" src="/static/3b1aa5e68a25ab3130728de145ddbf61/37523/image-1024x561.png" srcset="/static/3b1aa5e68a25ab3130728de145ddbf61/e9ff0/image-1024x561.png 180w, /static/3b1aa5e68a25ab3130728de145ddbf61/f21e7/image-1024x561.png 360w, /static/3b1aa5e68a25ab3130728de145ddbf61/37523/image-1024x561.png 720w, /static/3b1aa5e68a25ab3130728de145ddbf61/2bef9/image-1024x561.png 1024w" sizes="(max-width: 720px) 100vw, 720px" style="width:100%;height:100%;margin:0;vertical-align:middle;position:absolute;top:0;left:0;" loading="lazy" decoding="async" /> </a> </span></p> <p>In <code>file-upload.js</code>, will initialize and define a custom element with a simple file upload element:</p> <ul> <li><code>document.createElement</code> enable us to create a template that will not yet be rendered in the DOM</li> <li>In the <code>constructor</code>, we will call the super class since we are extending and inheriting from <code>HTMLElement</code></li> <li><code>this.attachShadow()</code> attaches a shadow DOM tree to the specified element.</li> <li>Finally, will append the template to the <code>shadowRoot</code></li> </ul> <pre class="grvsc-container default-dark" data-language="javascript" data-index="0"><code class="grvsc-code"><span class="grvsc-line"><span class="grvsc-source"></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk3">// Create template</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk4">const</span><span class="mtk1"> </span><span class="mtk12">template</span><span class="mtk1"> = </span><span class="mtk12">document</span><span class="mtk1">.</span><span class="mtk11">createElement</span><span class="mtk1">(</span><span class="mtk8">&#39;template&#39;</span><span class="mtk1">);</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk12">template</span><span class="mtk1">.</span><span class="mtk12">innerHTML</span><span class="mtk1"> = </span><span class="mtk3">/*html*/</span><span class="mtk8">`</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk8"> &lt;style&gt;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk8"> &lt;/style&gt;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk8"> &lt;input type=&quot;file&quot; /&gt;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk8">`</span><span class="mtk1">;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk4">class</span><span class="mtk1"> </span><span class="mtk10">FileUpload</span><span class="mtk1"> </span><span class="mtk4">extends</span><span class="mtk1"> </span><span class="mtk10">HTMLElement</span><span class="mtk1"> {</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk4">constructor</span><span class="mtk1">() {</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk3">// Inititialize custom component</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk4">super</span><span class="mtk1">();</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk4">this</span><span class="mtk1">.</span><span class="mtk11">attachShadow</span><span class="mtk1">({ </span><span class="mtk12">mode:</span><span class="mtk1"> </span><span class="mtk8">&#39;open&#39;</span><span class="mtk1"> });</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk4">this</span><span class="mtk1">.</span><span class="mtk12">shadowRoot</span><span class="mtk1">.</span><span class="mtk11">appendChild</span><span class="mtk1">(</span><span class="mtk12">template</span><span class="mtk1">.</span><span class="mtk12">content</span><span class="mtk1">.</span><span class="mtk11">cloneNode</span><span class="mtk1">(</span><span class="mtk4">true</span><span class="mtk1">));</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> }</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1">}</span></span></span> <span class="grvsc-line"><span class="grvsc-source"></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk12">window</span><span class="mtk1">.</span><span class="mtk12">customElements</span><span class="mtk1">.</span><span class="mtk11">define</span><span class="mtk1">(</span><span class="mtk8">&#39;file-upload&#39;</span><span class="mtk1">, </span><span class="mtk12">FileUpload</span><span class="mtk1">);</span></span></span></code></pre> <p><em>To understand Custom Elements, Shadow DOM and HTML Templates in more details, please visit <a href="https://developer.mozilla.org/en-US/docs/Web/Web_Components">MDN Web Docs</a></em></p> <p>Now, we can import the component in <code>main.html</code> and use it.</p> <pre class="grvsc-container default-dark" data-language="html" data-index="1"><code class="grvsc-code"><span class="grvsc-line"><span class="grvsc-source"><span class="mtk17">&lt;!</span><span class="mtk4">DOCTYPE</span><span class="mtk1"> </span><span class="mtk12">html</span><span class="mtk17">&gt;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk17">&lt;</span><span class="mtk4">html</span><span class="mtk17">&gt;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk17">&lt;</span><span class="mtk4">script</span><span class="mtk1"> </span><span class="mtk12">src</span><span class="mtk1">=</span><span class="mtk8">&quot;./file-upload.js&quot;</span><span class="mtk17">&gt;&lt;/</span><span class="mtk4">script</span><span class="mtk17">&gt;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk17">&lt;</span><span class="mtk4">body</span><span class="mtk17">&gt;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk17">&lt;</span><span class="mtk4">file-upload</span><span class="mtk17">&gt;&lt;/</span><span class="mtk4">file-upload</span><span class="mtk17">&gt;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk17">&lt;/</span><span class="mtk4">body</span><span class="mtk17">&gt;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk17">&lt;/</span><span class="mtk4">html</span><span class="mtk17">&gt;</span></span></span></code></pre> <p>So far nothing special, just a normal native-looking file upload element:</p> <p><span class="gatsby-resp-image-wrapper" style="position: relative; display: block; margin-left: auto; margin-right: auto; max-width: 720px; " > <a class="gatsby-resp-image-link" href="/static/402dfb2bc37046d246e6fd009950bc4a/2bef9/image-1-1024x401.png" style="display: block" target="_blank" rel="noopener" > <span class="gatsby-resp-image-background-image" style="padding-bottom: 38.888888888888886%; position: relative; bottom: 0; left: 0; background-image: url('data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABQAAAAICAYAAAD5nd/tAAAACXBIWXMAAAsTAAALEwEAmpwYAAAA1UlEQVR42q2PsQ6CMBCG+3DQsjiYuLk6+CSGxeDms2jsO9AKGCCOwkQCW4uFegUCmjgY4iVf/rvc9b8rWq/IZrF0Dhg7O0KIa9v2xFgT1/T6/nvez2GMd6CeZVkbdE9imucPHQSh8hnTnF+177MOxviojPNOgzDUSZr2JD1xnKgsy3UU3SgSQpw0RC2lqOv6CekchPFomuaMlFIXU7Rtq/SPAbMfgFH3Fo6jswy/LJgM4Zvn4VxpNs1EDobdl+m/LpRSUlSW5baqqiPoHvBmsjceRVFsX2RqLfPl0NYcAAAAAElFTkSuQmCC'); background-size: cover; display: block;" ></span> <img class="gatsby-resp-image-image" alt="Upload File Component" title="" src="/static/402dfb2bc37046d246e6fd009950bc4a/37523/image-1-1024x401.png" srcset="/static/402dfb2bc37046d246e6fd009950bc4a/e9ff0/image-1-1024x401.png 180w, /static/402dfb2bc37046d246e6fd009950bc4a/f21e7/image-1-1024x401.png 360w, /static/402dfb2bc37046d246e6fd009950bc4a/37523/image-1-1024x401.png 720w, /static/402dfb2bc37046d246e6fd009950bc4a/2bef9/image-1-1024x401.png 1024w" sizes="(max-width: 720px) 100vw, 720px" style="width:100%;height:100%;margin:0;vertical-align:middle;position:absolute;top:0;left:0;" loading="lazy" decoding="async" /> </a> </span></p> <h2 id="create-a-custom-file-upload" style="position:relative;"><a href="#create-a-custom-file-upload" aria-label="create a custom file upload permalink" class="anchor before"><svg aria-hidden="true" focusable="false" height="16" version="1.1" viewBox="0 0 16 16" width="16"><path fill-rule="evenodd" d="M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z"></path></svg></a>Create a Custom File Upload</h2> <p>The easiest way to customize a native file input is to do the following steps:</p> <ul> <li>Hide the file <code>input</code> using the <code>hidden</code> attribute.</li> <li>Use a <code>label</code> element as a replacement with a <code>for</code> attribute to indicate which element you’d like to trigger</li> <li>Finally, customize the <code>label</code> element however you like using CSS</li> </ul> <pre class="grvsc-container default-dark" data-language="javascript" data-index="2"><code class="grvsc-code"><span class="grvsc-line"><span class="grvsc-source"><span class="mtk3">// Create template</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk4">const</span><span class="mtk1"> </span><span class="mtk12">template</span><span class="mtk1"> = </span><span class="mtk12">document</span><span class="mtk1">.</span><span class="mtk11">createElement</span><span class="mtk1">(</span><span class="mtk8">&#39;template&#39;</span><span class="mtk1">);</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk12">template</span><span class="mtk1">.</span><span class="mtk12">innerHTML</span><span class="mtk1"> = </span><span class="mtk3">/*html*/</span><span class="mtk8">`</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk8"> &lt;style&gt;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk8"> &lt;/style&gt;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk8"> &lt;article&gt;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk8"> &lt;label for=&quot;fileUpload&quot;&gt;Upload&lt;/label&gt;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk8"> &lt;section&gt;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk8"> &lt;span&gt;&lt;/span&gt;&lt;button&gt;Remove&lt;/button&gt;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk8"> &lt;/section&gt;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk8"> &lt;/article&gt;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk8"> &lt;input hidden id=&quot;fileUpload&quot; type=&quot;file&quot; /&gt;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk8">`</span><span class="mtk1">;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk4">class</span><span class="mtk1"> </span><span class="mtk10">FileUpload</span><span class="mtk1"> </span><span class="mtk4">extends</span><span class="mtk1"> </span><span class="mtk10">HTMLElement</span><span class="mtk1"> {</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk4">constructor</span><span class="mtk1">() {</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk3">// Inititialize custom component</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk4">super</span><span class="mtk1">();</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk4">this</span><span class="mtk1">.</span><span class="mtk11">attachShadow</span><span class="mtk1">({ </span><span class="mtk12">mode:</span><span class="mtk1"> </span><span class="mtk8">&#39;open&#39;</span><span class="mtk1"> });</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk4">this</span><span class="mtk1">.</span><span class="mtk12">shadowRoot</span><span class="mtk1">.</span><span class="mtk11">appendChild</span><span class="mtk1">(</span><span class="mtk12">template</span><span class="mtk1">.</span><span class="mtk12">content</span><span class="mtk1">.</span><span class="mtk11">cloneNode</span><span class="mtk1">(</span><span class="mtk4">true</span><span class="mtk1">));</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> }</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1">}</span></span></span> <span class="grvsc-line"><span class="grvsc-source"></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk12">window</span><span class="mtk1">.</span><span class="mtk12">customElements</span><span class="mtk1">.</span><span class="mtk11">define</span><span class="mtk1">(</span><span class="mtk8">&#39;file-upload&#39;</span><span class="mtk1">, </span><span class="mtk12">FileUpload</span><span class="mtk1">);</span></span></span></code></pre> <p>You’ll notice that we added a <code>span</code> and <code>button</code> elements. Those will be used in the next step to display and remove the currently uploaded file.</p> <h2 id="implement-event-listeners" style="position:relative;"><a href="#implement-event-listeners" aria-label="implement event listeners permalink" class="anchor before"><svg aria-hidden="true" focusable="false" height="16" version="1.1" viewBox="0 0 16 16" width="16"><path fill-rule="evenodd" d="M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z"></path></svg></a>Implement event listeners</h2> <p>In this step, we will implement the logic associated with showing and removing the selected file:</p> <ul> <li>The file input <code>onchange</code> event listener is used to update the selected file and display the proper name on the screen. Also, we are dispatching a custom event with the deleted file. The developer can subscribe and apply a custom logic if required</li> <li>The delete button <code>onclick</code> event listener is used to delete the selected file and remove it from the DOM. Also, we are dispatching a custom event with the deleted file</li> <li>We added a helper <code>dispatch</code> function and <code>select</code> getter to have a neater syntax.</li> </ul> <pre class="grvsc-container default-dark" data-language="javascript" data-index="3"><code class="grvsc-code"><span class="grvsc-line"><span class="grvsc-source"><span class="mtk3">// Create template</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk4">const</span><span class="mtk1"> </span><span class="mtk12">template</span><span class="mtk1"> = </span><span class="mtk12">document</span><span class="mtk1">.</span><span class="mtk11">createElement</span><span class="mtk1">(</span><span class="mtk8">&#39;template&#39;</span><span class="mtk1">);</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk12">template</span><span class="mtk1">.</span><span class="mtk12">innerHTML</span><span class="mtk1"> = </span><span class="mtk3">/*html*/</span><span class="mtk8">`</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk8"> &lt;style&gt;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk8"> &lt;/style&gt;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk8"> &lt;article&gt;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk8"> &lt;label for=&quot;fileUpload&quot;&gt;Upload&lt;/label&gt;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk8"> &lt;section hidden&gt;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk8"> &lt;span&gt;&lt;/span&gt;&lt;button&gt;Remove&lt;/button&gt;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk8"> &lt;/section&gt;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk8"> &lt;/article&gt;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk8"> &lt;input hidden id=&quot;fileUpload&quot; type=&quot;file&quot; /&gt;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk8">`</span><span class="mtk1">;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk4">class</span><span class="mtk1"> </span><span class="mtk10">FileUpload</span><span class="mtk1"> </span><span class="mtk4">extends</span><span class="mtk1"> </span><span class="mtk10">HTMLElement</span><span class="mtk1"> {</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk4">constructor</span><span class="mtk1">() {</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk3">// Inititialize custom component</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk4">super</span><span class="mtk1">();</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk4">this</span><span class="mtk1">.</span><span class="mtk11">attachShadow</span><span class="mtk1">({ </span><span class="mtk12">mode:</span><span class="mtk1"> </span><span class="mtk8">&#39;open&#39;</span><span class="mtk1"> });</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk4">this</span><span class="mtk1">.</span><span class="mtk12">shadowRoot</span><span class="mtk1">.</span><span class="mtk11">appendChild</span><span class="mtk1">(</span><span class="mtk12">template</span><span class="mtk1">.</span><span class="mtk12">content</span><span class="mtk1">.</span><span class="mtk11">cloneNode</span><span class="mtk1">(</span><span class="mtk4">true</span><span class="mtk1">));</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk3">// Add event listeners</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk4">this</span><span class="mtk1">.</span><span class="mtk11">select</span><span class="mtk1">(</span><span class="mtk8">&#39;input&#39;</span><span class="mtk1">).</span><span class="mtk11">onchange</span><span class="mtk1"> = (</span><span class="mtk12">e</span><span class="mtk1">) </span><span class="mtk4">=&gt;</span><span class="mtk1"> </span><span class="mtk4">this</span><span class="mtk1">.</span><span class="mtk11">handleChange</span><span class="mtk1">(</span><span class="mtk12">e</span><span class="mtk1">);</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk4">this</span><span class="mtk1">.</span><span class="mtk11">select</span><span class="mtk1">(</span><span class="mtk8">&#39;button&#39;</span><span class="mtk1">).</span><span class="mtk11">onclick</span><span class="mtk1"> = () </span><span class="mtk4">=&gt;</span><span class="mtk1"> </span><span class="mtk4">this</span><span class="mtk1">.</span><span class="mtk11">handleRemove</span><span class="mtk1">();</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> }</span></span></span> <span class="grvsc-line"><span class="grvsc-source"></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk11">handleChange</span><span class="mtk1">(</span><span class="mtk12">e</span><span class="mtk1">) {</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk4">const</span><span class="mtk1"> </span><span class="mtk12">file</span><span class="mtk1"> = </span><span class="mtk12">e</span><span class="mtk1">.</span><span class="mtk12">target</span><span class="mtk1">.</span><span class="mtk12">files</span><span class="mtk1">[</span><span class="mtk7">0</span><span class="mtk1">];</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk4">this</span><span class="mtk1">.</span><span class="mtk11">select</span><span class="mtk1">(</span><span class="mtk8">&#39;section&#39;</span><span class="mtk1">).</span><span class="mtk12">style</span><span class="mtk1">.</span><span class="mtk12">display</span><span class="mtk1"> = </span><span class="mtk8">&quot;block&quot;</span><span class="mtk1">;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk4">this</span><span class="mtk1">.</span><span class="mtk11">select</span><span class="mtk1">(</span><span class="mtk8">&#39;span&#39;</span><span class="mtk1">).</span><span class="mtk12">innerText</span><span class="mtk1"> = </span><span class="mtk12">file</span><span class="mtk1">.</span><span class="mtk12">name</span><span class="mtk1">;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk4">this</span><span class="mtk1">.</span><span class="mtk11">dispatch</span><span class="mtk1">(</span><span class="mtk8">&#39;change&#39;</span><span class="mtk1">, </span><span class="mtk12">file</span><span class="mtk1">);</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> }</span></span></span> <span class="grvsc-line"><span class="grvsc-source"></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk11">handleRemove</span><span class="mtk1">() {</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk4">const</span><span class="mtk1"> </span><span class="mtk12">el</span><span class="mtk1"> = </span><span class="mtk4">this</span><span class="mtk1">.</span><span class="mtk11">select</span><span class="mtk1">(</span><span class="mtk8">&#39;input&#39;</span><span class="mtk1">);</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk4">const</span><span class="mtk1"> </span><span class="mtk12">file</span><span class="mtk1"> = </span><span class="mtk12">el</span><span class="mtk1">.</span><span class="mtk12">files</span><span class="mtk1">[</span><span class="mtk7">0</span><span class="mtk1">];</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">el</span><span class="mtk1">.</span><span class="mtk12">value</span><span class="mtk1"> = </span><span class="mtk8">&quot;&quot;</span><span class="mtk1">;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk4">this</span><span class="mtk1">.</span><span class="mtk11">select</span><span class="mtk1">(</span><span class="mtk8">&#39;section&#39;</span><span class="mtk1">).</span><span class="mtk12">style</span><span class="mtk1">.</span><span class="mtk12">display</span><span class="mtk1"> = </span><span class="mtk8">&quot;none&quot;</span><span class="mtk1">;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk4">this</span><span class="mtk1">.</span><span class="mtk11">dispatch</span><span class="mtk1">(</span><span class="mtk8">&#39;change&#39;</span><span class="mtk1">, </span><span class="mtk12">file</span><span class="mtk1">);</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> }</span></span></span> <span class="grvsc-line"><span class="grvsc-source"></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk11">dispatch</span><span class="mtk1">(</span><span class="mtk12">event</span><span class="mtk1">, </span><span class="mtk12">arg</span><span class="mtk1">) {</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk4">this</span><span class="mtk1">.</span><span class="mtk11">dispatchEvent</span><span class="mtk1">(</span><span class="mtk4">new</span><span class="mtk1"> </span><span class="mtk10">CustomEvent</span><span class="mtk1">(</span><span class="mtk12">event</span><span class="mtk1">, {</span><span class="mtk12">detail:</span><span class="mtk1"> </span><span class="mtk12">arg</span><span class="mtk1">}));</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> }</span></span></span> <span class="grvsc-line"><span class="grvsc-source"></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk4">get</span><span class="mtk1"> </span><span class="mtk11">select</span><span class="mtk1">() {</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk15">return</span><span class="mtk1"> </span><span class="mtk4">this</span><span class="mtk1">.</span><span class="mtk12">shadowRoot</span><span class="mtk1">.</span><span class="mtk12">querySelector</span><span class="mtk1">.</span><span class="mtk11">bind</span><span class="mtk1">(</span><span class="mtk4">this</span><span class="mtk1">.</span><span class="mtk12">shadowRoot</span><span class="mtk1">);</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> }</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1">}</span></span></span> <span class="grvsc-line"><span class="grvsc-source"></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk12">window</span><span class="mtk1">.</span><span class="mtk12">customElements</span><span class="mtk1">.</span><span class="mtk11">define</span><span class="mtk1">(</span><span class="mtk8">&#39;file-upload&#39;</span><span class="mtk1">, </span><span class="mtk12">FileUpload</span><span class="mtk1">);</span></span></span></code></pre> <p>If we run <code>main.html</code>, we should get the following results:</p> <p><img src="/dd60e6a94e3889f57f4f04488b8b4c9f/main.html-Google-Chrome-2021-07-10-15-18-15_Trim-1.gif" alt="Upload File Component"></p> <h2 id="add-default-styling" style="position:relative;"><a href="#add-default-styling" aria-label="add default styling permalink" class="anchor before"><svg aria-hidden="true" focusable="false" height="16" version="1.1" viewBox="0 0 16 16" width="16"><path fill-rule="evenodd" d="M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z"></path></svg></a>Add default styling</h2> <p>Although the next step will cover how we can enable developers to apply custom styling, we would still need to offer a basic look and feel:</p> <ul> <li>The <code>label</code> element will look like a default native button</li> <li>The remove <code>button</code> will be replaced with an ‘X’ icon. We can use some of the <a href="https://www.w3schools.com/charsets/ref_utf_dingbats.asp">built-in HTML characters</a></li> <li>And the rest is just layout tweaks and improvements.</li> </ul> <pre class="grvsc-container default-dark" data-language="javascript" data-index="4"><code class="grvsc-code"><span class="grvsc-line"><span class="grvsc-source"><span class="mtk3">// Create template</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk4">const</span><span class="mtk1"> </span><span class="mtk12">template</span><span class="mtk1"> = </span><span class="mtk12">document</span><span class="mtk1">.</span><span class="mtk11">createElement</span><span class="mtk1">(</span><span class="mtk8">&#39;template&#39;</span><span class="mtk1">);</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk12">template</span><span class="mtk1">.</span><span class="mtk12">innerHTML</span><span class="mtk1"> = </span><span class="mtk3">/*html*/</span><span class="mtk8">`</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk8"> &lt;style&gt;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk8"> :host {</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk8"> font-size: 13px;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk8"> font-family: arial;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk8"> }</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk8"> article {</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk8"> display: flex;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk8"> align-items: center;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk8"> }</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk8"> label {</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk8"> background-color: rgb(239, 239, 239);</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk8"> border: 1px solid rgb(118, 118, 118);</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk8"> padding: 2px 6px 2px 6px;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk8"> border-radius: 2px;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk8"> margin-right: 5px;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk8"> }</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk8"> button {</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk8"> border:0;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk8"> background: transparent;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk8"> cursor: pointer;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk8"> }</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk8"> button::before {</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk8"> content: &#39;</span><span class="mtk6">\\</span><span class="mtk8">2716&#39;;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk8"> }</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk8"> &lt;/style&gt;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk8"> &lt;article&gt;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk8"> &lt;label for=&quot;fileUpload&quot;&gt;Upload&lt;/label&gt;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk8"> &lt;section hidden&gt;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk8"> &lt;span&gt;&lt;/span&gt;&lt;button&gt;&lt;/button&gt;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk8"> &lt;/section&gt;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk8"> &lt;/article&gt;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk8"> &lt;input hidden id=&quot;fileUpload&quot; type=&quot;file&quot; /&gt;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk8">`</span><span class="mtk1">;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk4">class</span><span class="mtk1"> </span><span class="mtk10">FileUpload</span><span class="mtk1"> </span><span class="mtk4">extends</span><span class="mtk1"> </span><span class="mtk10">HTMLElement</span><span class="mtk1"> {</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk4">constructor</span><span class="mtk1">() {</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk3">// Inititialize custom component</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk4">super</span><span class="mtk1">();</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk4">this</span><span class="mtk1">.</span><span class="mtk11">attachShadow</span><span class="mtk1">({ </span><span class="mtk12">mode:</span><span class="mtk1"> </span><span class="mtk8">&#39;open&#39;</span><span class="mtk1"> });</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk4">this</span><span class="mtk1">.</span><span class="mtk12">shadowRoot</span><span class="mtk1">.</span><span class="mtk11">appendChild</span><span class="mtk1">(</span><span class="mtk12">template</span><span class="mtk1">.</span><span class="mtk12">content</span><span class="mtk1">.</span><span class="mtk11">cloneNode</span><span class="mtk1">(</span><span class="mtk4">true</span><span class="mtk1">));</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk3">// Add event listeners</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk4">this</span><span class="mtk1">.</span><span class="mtk11">select</span><span class="mtk1">(</span><span class="mtk8">&#39;input&#39;</span><span class="mtk1">).</span><span class="mtk11">onchange</span><span class="mtk1"> = (</span><span class="mtk12">e</span><span class="mtk1">) </span><span class="mtk4">=&gt;</span><span class="mtk1"> </span><span class="mtk4">this</span><span class="mtk1">.</span><span class="mtk11">handleChange</span><span class="mtk1">(</span><span class="mtk12">e</span><span class="mtk1">);</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk4">this</span><span class="mtk1">.</span><span class="mtk11">select</span><span class="mtk1">(</span><span class="mtk8">&#39;button&#39;</span><span class="mtk1">).</span><span class="mtk11">onclick</span><span class="mtk1"> = () </span><span class="mtk4">=&gt;</span><span class="mtk1"> </span><span class="mtk4">this</span><span class="mtk1">.</span><span class="mtk11">handleRemove</span><span class="mtk1">();</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> }</span></span></span> <span class="grvsc-line"><span class="grvsc-source"></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk11">handleChange</span><span class="mtk1">(</span><span class="mtk12">e</span><span class="mtk1">) {</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk4">const</span><span class="mtk1"> </span><span class="mtk12">file</span><span class="mtk1"> = </span><span class="mtk12">e</span><span class="mtk1">.</span><span class="mtk12">target</span><span class="mtk1">.</span><span class="mtk12">files</span><span class="mtk1">[</span><span class="mtk7">0</span><span class="mtk1">];</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk4">this</span><span class="mtk1">.</span><span class="mtk11">select</span><span class="mtk1">(</span><span class="mtk8">&#39;section&#39;</span><span class="mtk1">).</span><span class="mtk12">style</span><span class="mtk1">.</span><span class="mtk12">display</span><span class="mtk1"> = </span><span class="mtk8">&quot;block&quot;</span><span class="mtk1">;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk4">this</span><span class="mtk1">.</span><span class="mtk11">select</span><span class="mtk1">(</span><span class="mtk8">&#39;span&#39;</span><span class="mtk1">).</span><span class="mtk12">innerText</span><span class="mtk1"> = </span><span class="mtk12">file</span><span class="mtk1">.</span><span class="mtk12">name</span><span class="mtk1">;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk4">this</span><span class="mtk1">.</span><span class="mtk11">dispatch</span><span class="mtk1">(</span><span class="mtk8">&#39;change&#39;</span><span class="mtk1">, </span><span class="mtk12">file</span><span class="mtk1">);</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> }</span></span></span> <span class="grvsc-line"><span class="grvsc-source"></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk11">handleRemove</span><span class="mtk1">() {</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk4">const</span><span class="mtk1"> </span><span class="mtk12">el</span><span class="mtk1"> = </span><span class="mtk4">this</span><span class="mtk1">.</span><span class="mtk11">select</span><span class="mtk1">(</span><span class="mtk8">&#39;input&#39;</span><span class="mtk1">);</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk4">const</span><span class="mtk1"> </span><span class="mtk12">file</span><span class="mtk1"> = </span><span class="mtk12">el</span><span class="mtk1">.</span><span class="mtk12">files</span><span class="mtk1">[</span><span class="mtk7">0</span><span class="mtk1">];</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">el</span><span class="mtk1">.</span><span class="mtk12">value</span><span class="mtk1"> = </span><span class="mtk8">&quot;&quot;</span><span class="mtk1">;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk4">this</span><span class="mtk1">.</span><span class="mtk11">select</span><span class="mtk1">(</span><span class="mtk8">&#39;section&#39;</span><span class="mtk1">).</span><span class="mtk12">style</span><span class="mtk1">.</span><span class="mtk12">display</span><span class="mtk1"> = </span><span class="mtk8">&quot;none&quot;</span><span class="mtk1">;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk4">this</span><span class="mtk1">.</span><span class="mtk11">dispatch</span><span class="mtk1">(</span><span class="mtk8">&#39;change&#39;</span><span class="mtk1">, </span><span class="mtk12">file</span><span class="mtk1">);</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> }</span></span></span> <span class="grvsc-line"><span class="grvsc-source"></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk11">dispatch</span><span class="mtk1">(</span><span class="mtk12">event</span><span class="mtk1">, </span><span class="mtk12">arg</span><span class="mtk1">) {</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk4">this</span><span class="mtk1">.</span><span class="mtk11">dispatchEvent</span><span class="mtk1">(</span><span class="mtk4">new</span><span class="mtk1"> </span><span class="mtk10">CustomEvent</span><span class="mtk1">(</span><span class="mtk12">event</span><span class="mtk1">, {</span><span class="mtk12">detail:</span><span class="mtk1"> </span><span class="mtk12">arg</span><span class="mtk1">}));</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> }</span></span></span> <span class="grvsc-line"><span class="grvsc-source"></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk4">get</span><span class="mtk1"> </span><span class="mtk11">select</span><span class="mtk1">() {</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk15">return</span><span class="mtk1"> </span><span class="mtk4">this</span><span class="mtk1">.</span><span class="mtk12">shadowRoot</span><span class="mtk1">.</span><span class="mtk12">querySelector</span><span class="mtk1">.</span><span class="mtk11">bind</span><span class="mtk1">(</span><span class="mtk4">this</span><span class="mtk1">.</span><span class="mtk12">shadowRoot</span><span class="mtk1">);</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> }</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1">}</span></span></span> <span class="grvsc-line"><span class="grvsc-source"></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk12">window</span><span class="mtk1">.</span><span class="mtk12">customElements</span><span class="mtk1">.</span><span class="mtk11">define</span><span class="mtk1">(</span><span class="mtk8">&#39;file-upload&#39;</span><span class="mtk1">, </span><span class="mtk12">FileUpload</span><span class="mtk1">);</span></span></span></code></pre> <p><span class="gatsby-resp-image-wrapper" style="position: relative; display: block; margin-left: auto; margin-right: auto; max-width: 720px; " > <a class="gatsby-resp-image-link" href="/static/27d401c590501b18050c3f84dc7f636a/2bef9/image-7-1024x550.png" style="display: block" target="_blank" rel="noopener" > <span class="gatsby-resp-image-background-image" style="padding-bottom: 53.888888888888886%; position: relative; bottom: 0; left: 0; background-image: url('data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABQAAAALCAYAAAB/Ca1DAAAACXBIWXMAAAsTAAALEwEAmpwYAAAA30lEQVR42u2SzwqCQBDG9y0K6glCSthjgseCDu4KSR261qU/PqY3xXMgaZ3aTL2Zu06rdKhDQdKxD34D3wzzXWaQ3uu1x5qiY20wxH2sYdyIoaqquqIoLbSczrb2ag7TBb1RQgUhRBiG8QKRfUo/crMsC0zTXKN9ENjscoXwEPIwjOB4PAFjFzifWQ1jDNI0hSzL3iLnHKSi6LRDcsGuTJ7nvCgK4LyefaWyLOslGbxFstjPzSb6B/44MI7jXWXkdbkQAprAH6+RJMkGOY7T9X1/4nneSDJuyKjKcF23cwfAb9lypd+b1wAAAABJRU5ErkJggg=='); background-size: cover; display: block;" ></span> <img class="gatsby-resp-image-image" alt="image 7 1024x550" title="" src="/static/27d401c590501b18050c3f84dc7f636a/37523/image-7-1024x550.png" srcset="/static/27d401c590501b18050c3f84dc7f636a/e9ff0/image-7-1024x550.png 180w, /static/27d401c590501b18050c3f84dc7f636a/f21e7/image-7-1024x550.png 360w, /static/27d401c590501b18050c3f84dc7f636a/37523/image-7-1024x550.png 720w, /static/27d401c590501b18050c3f84dc7f636a/2bef9/image-7-1024x550.png 1024w" sizes="(max-width: 720px) 100vw, 720px" style="width:100%;height:100%;margin:0;vertical-align:middle;position:absolute;top:0;left:0;" loading="lazy" decoding="async" /> </a> </span></p> <h2 id="enable-custom-styling" style="position:relative;"><a href="#enable-custom-styling" aria-label="enable custom styling permalink" class="anchor before"><svg aria-hidden="true" focusable="false" height="16" version="1.1" viewBox="0 0 16 16" width="16"><path fill-rule="evenodd" d="M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z"></path></svg></a>Enable custom styling</h2> <p>Since we are using the shadow DOM, the classes we defined are encapsulated and can’t be modified directly. The only way to enable custom styling is through CSS “part”, which allows developers to style CSS properties on an element inside of a shadow tree.</p> <p>Below, we will add <code>part="upload-button"</code> to the <code>label</code> element to enable CSS customization:</p> <pre class="grvsc-container default-dark" data-language="javascript" data-index="5"><code class="grvsc-code"><span class="grvsc-line"><span class="grvsc-source"><span class="mtk3">// Create template</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk4">const</span><span class="mtk1"> </span><span class="mtk12">template</span><span class="mtk1"> = </span><span class="mtk12">document</span><span class="mtk1">.</span><span class="mtk11">createElement</span><span class="mtk1">(</span><span class="mtk8">&#39;template&#39;</span><span class="mtk1">);</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk12">template</span><span class="mtk1">.</span><span class="mtk12">innerHTML</span><span class="mtk1"> = </span><span class="mtk3">/*html*/</span><span class="mtk8">`</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk8"> &lt;style&gt;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk8"> :host {</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk8"> font-size: 13px;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk8"> font-family: arial;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk8"> }</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk8"> article {</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk8"> display: flex;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk8"> align-items: center;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk8"> }</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk8"> label {</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk8"> background-color: rgb(239, 239, 239);</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk8"> border: 1px solid rgb(118, 118, 118);</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk8"> padding: 2px 6px 2px 6px;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk8"> border-radius: 2px;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk8"> margin-right: 5px;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk8"> }</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk8"> button {</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk8"> border:0;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk8"> background: transparent;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk8"> cursor: pointer;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk8"> }</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk8"> button::before {</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk8"> content: &#39;</span><span class="mtk6">\\</span><span class="mtk8">2716&#39;;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk8"> }</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk8"> &lt;/style&gt;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk8"> &lt;article&gt;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk8"> &lt;label part=&quot;upload-button&quot; for=&quot;fileUpload&quot;&gt;Upload&lt;/label&gt;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk8"> &lt;section hidden&gt;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk8"> &lt;span&gt;&lt;/span&gt;&lt;button&gt;&lt;/button&gt;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk8"> &lt;/section&gt;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk8"> &lt;/article&gt;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk8"> &lt;input hidden id=&quot;fileUpload&quot; type=&quot;file&quot; /&gt;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk8">`</span><span class="mtk1">;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk4">class</span><span class="mtk1"> </span><span class="mtk10">FileUpload</span><span class="mtk1"> </span><span class="mtk4">extends</span><span class="mtk1"> </span><span class="mtk10">HTMLElement</span><span class="mtk1"> {</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk4">constructor</span><span class="mtk1">() {</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk3">// Inititialize custom component</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk4">super</span><span class="mtk1">();</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk4">this</span><span class="mtk1">.</span><span class="mtk11">attachShadow</span><span class="mtk1">({ </span><span class="mtk12">mode:</span><span class="mtk1"> </span><span class="mtk8">&#39;open&#39;</span><span class="mtk1"> });</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk4">this</span><span class="mtk1">.</span><span class="mtk12">shadowRoot</span><span class="mtk1">.</span><span class="mtk11">appendChild</span><span class="mtk1">(</span><span class="mtk12">template</span><span class="mtk1">.</span><span class="mtk12">content</span><span class="mtk1">.</span><span class="mtk11">cloneNode</span><span class="mtk1">(</span><span class="mtk4">true</span><span class="mtk1">));</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk3">// Add event listeners</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk4">this</span><span class="mtk1">.</span><span class="mtk11">select</span><span class="mtk1">(</span><span class="mtk8">&#39;input&#39;</span><span class="mtk1">).</span><span class="mtk11">onchange</span><span class="mtk1"> = (</span><span class="mtk12">e</span><span class="mtk1">) </span><span class="mtk4">=&gt;</span><span class="mtk1"> </span><span class="mtk4">this</span><span class="mtk1">.</span><span class="mtk11">handleChange</span><span class="mtk1">(</span><span class="mtk12">e</span><span class="mtk1">);</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk4">this</span><span class="mtk1">.</span><span class="mtk11">select</span><span class="mtk1">(</span><span class="mtk8">&#39;button&#39;</span><span class="mtk1">).</span><span class="mtk11">onclick</span><span class="mtk1"> = () </span><span class="mtk4">=&gt;</span><span class="mtk1"> </span><span class="mtk4">this</span><span class="mtk1">.</span><span class="mtk11">handleRemove</span><span class="mtk1">();</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> }</span></span></span> <span class="grvsc-line"><span class="grvsc-source"></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk11">handleChange</span><span class="mtk1">(</span><span class="mtk12">e</span><span class="mtk1">) {</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk4">const</span><span class="mtk1"> </span><span class="mtk12">file</span><span class="mtk1"> = </span><span class="mtk12">e</span><span class="mtk1">.</span><span class="mtk12">target</span><span class="mtk1">.</span><span class="mtk12">files</span><span class="mtk1">[</span><span class="mtk7">0</span><span class="mtk1">];</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk4">this</span><span class="mtk1">.</span><span class="mtk11">select</span><span class="mtk1">(</span><span class="mtk8">&#39;section&#39;</span><span class="mtk1">).</span><span class="mtk12">style</span><span class="mtk1">.</span><span class="mtk12">display</span><span class="mtk1"> = </span><span class="mtk8">&quot;block&quot;</span><span class="mtk1">;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk4">this</span><span class="mtk1">.</span><span class="mtk11">select</span><span class="mtk1">(</span><span class="mtk8">&#39;span&#39;</span><span class="mtk1">).</span><span class="mtk12">innerText</span><span class="mtk1"> = </span><span class="mtk12">file</span><span class="mtk1">.</span><span class="mtk12">name</span><span class="mtk1">;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk4">this</span><span class="mtk1">.</span><span class="mtk11">dispatch</span><span class="mtk1">(</span><span class="mtk8">&#39;change&#39;</span><span class="mtk1">, </span><span class="mtk12">file</span><span class="mtk1">);</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> }</span></span></span> <span class="grvsc-line"><span class="grvsc-source"></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk11">handleRemove</span><span class="mtk1">() {</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk4">const</span><span class="mtk1"> </span><span class="mtk12">el</span><span class="mtk1"> = </span><span class="mtk4">this</span><span class="mtk1">.</span><span class="mtk11">select</span><span class="mtk1">(</span><span class="mtk8">&#39;input&#39;</span><span class="mtk1">);</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk4">const</span><span class="mtk1"> </span><span class="mtk12">file</span><span class="mtk1"> = </span><span class="mtk12">el</span><span class="mtk1">.</span><span class="mtk12">files</span><span class="mtk1">[</span><span class="mtk7">0</span><span class="mtk1">];</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">el</span><span class="mtk1">.</span><span class="mtk12">value</span><span class="mtk1"> = </span><span class="mtk8">&quot;&quot;</span><span class="mtk1">;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk4">this</span><span class="mtk1">.</span><span class="mtk11">select</span><span class="mtk1">(</span><span class="mtk8">&#39;section&#39;</span><span class="mtk1">).</span><span class="mtk12">style</span><span class="mtk1">.</span><span class="mtk12">display</span><span class="mtk1"> = </span><span class="mtk8">&quot;none&quot;</span><span class="mtk1">;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk4">this</span><span class="mtk1">.</span><span class="mtk11">dispatch</span><span class="mtk1">(</span><span class="mtk8">&#39;change&#39;</span><span class="mtk1">, </span><span class="mtk12">file</span><span class="mtk1">);</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> }</span></span></span> <span class="grvsc-line"><span class="grvsc-source"></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk4">static</span><span class="mtk1"> </span><span class="mtk4">get</span><span class="mtk1"> </span><span class="mtk11">observedAttributes</span><span class="mtk1">() {</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk15">return</span><span class="mtk1"> [</span><span class="mtk8">&#39;upload-label&#39;</span><span class="mtk1">];</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> }</span></span></span> <span class="grvsc-line"><span class="grvsc-source"></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk11">attributeChangedCallback</span><span class="mtk1">(</span><span class="mtk12">name</span><span class="mtk1">, </span><span class="mtk12">oldValue</span><span class="mtk1">, </span><span class="mtk12">newValue</span><span class="mtk1">) {</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk15">if</span><span class="mtk1"> (</span><span class="mtk12">name</span><span class="mtk1"> === </span><span class="mtk8">&#39;upload-label&#39;</span><span class="mtk1">) {</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk15">if</span><span class="mtk1"> (</span><span class="mtk12">newValue</span><span class="mtk1"> &amp;&amp; </span><span class="mtk12">newValue</span><span class="mtk1"> !== </span><span class="mtk8">&#39;&#39;</span><span class="mtk1">) {</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk4">this</span><span class="mtk1">.</span><span class="mtk11">select</span><span class="mtk1">(</span><span class="mtk8">&#39;label&#39;</span><span class="mtk1">).</span><span class="mtk12">innerText</span><span class="mtk1"> = </span><span class="mtk12">newValue</span><span class="mtk1">;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> }</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> }</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> }</span></span></span> <span class="grvsc-line"><span class="grvsc-source"></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk11">dispatch</span><span class="mtk1">(</span><span class="mtk12">event</span><span class="mtk1">, </span><span class="mtk12">arg</span><span class="mtk1">) {</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk4">this</span><span class="mtk1">.</span><span class="mtk11">dispatchEvent</span><span class="mtk1">(</span><span class="mtk4">new</span><span class="mtk1"> </span><span class="mtk10">CustomEvent</span><span class="mtk1">(</span><span class="mtk12">event</span><span class="mtk1">, {</span><span class="mtk12">detail:</span><span class="mtk1"> </span><span class="mtk12">arg</span><span class="mtk1">}));</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> }</span></span></span> <span class="grvsc-line"><span class="grvsc-source"></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk4">get</span><span class="mtk1"> </span><span class="mtk11">select</span><span class="mtk1">() {</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk15">return</span><span class="mtk1"> </span><span class="mtk4">this</span><span class="mtk1">.</span><span class="mtk12">shadowRoot</span><span class="mtk1">.</span><span class="mtk12">querySelector</span><span class="mtk1">.</span><span class="mtk11">bind</span><span class="mtk1">(</span><span class="mtk4">this</span><span class="mtk1">.</span><span class="mtk12">shadowRoot</span><span class="mtk1">);</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> }</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1">}</span></span></span> <span class="grvsc-line"><span class="grvsc-source"></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk12">window</span><span class="mtk1">.</span><span class="mtk12">customElements</span><span class="mtk1">.</span><span class="mtk11">define</span><span class="mtk1">(</span><span class="mtk8">&#39;file-upload&#39;</span><span class="mtk1">, </span><span class="mtk12">FileUpload</span><span class="mtk1">);</span></span></span></code></pre> <p>In the <code>main.html</code> file, we can test it and add custom styles to two different instances of the <code>upload-file</code> component:</p> <pre class="grvsc-container default-dark" data-language="html" data-index="6"><code class="grvsc-code"><span class="grvsc-line"><span class="grvsc-source"><span class="mtk17">&lt;!</span><span class="mtk4">DOCTYPE</span><span class="mtk1"> </span><span class="mtk12">html</span><span class="mtk17">&gt;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk17">&lt;</span><span class="mtk4">html</span><span class="mtk17">&gt;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk17">&lt;</span><span class="mtk4">script</span><span class="mtk1"> </span><span class="mtk12">src</span><span class="mtk1">=</span><span class="mtk8">&quot;./file-upload.js&quot;</span><span class="mtk17">&gt;&lt;/</span><span class="mtk4">script</span><span class="mtk17">&gt;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk17">&lt;</span><span class="mtk4">style</span><span class="mtk17">&gt;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk4">file-upload</span><span class="mtk1">::part(</span><span class="mtk4">upload-button</span><span class="mtk1">) {</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">border</span><span class="mtk1">: </span><span class="mtk8">none</span><span class="mtk1">;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">color</span><span class="mtk1">: </span><span class="mtk8">white</span><span class="mtk1">;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">padding</span><span class="mtk1">: </span><span class="mtk7">9px</span><span class="mtk1"> </span><span class="mtk7">22px</span><span class="mtk1">;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">font-size</span><span class="mtk1">: </span><span class="mtk7">14px</span><span class="mtk1">;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">margin-bottom</span><span class="mtk1">: </span><span class="mtk7">10px</span><span class="mtk1">;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> }</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk6">.upload1</span><span class="mtk1">::part(</span><span class="mtk4">upload-button</span><span class="mtk1">) {</span><span class="mtk12">background-color</span><span class="mtk1">: </span><span class="mtk8">#4CAF50</span><span class="mtk1">;} </span><span class="mtk3">/* Green */</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk6">.upload2</span><span class="mtk1">::part(</span><span class="mtk4">upload-button</span><span class="mtk1">) {</span><span class="mtk12">background-color</span><span class="mtk1">: </span><span class="mtk8">#555555</span><span class="mtk1">;} </span><span class="mtk3">/* Black */</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk17">&lt;/</span><span class="mtk4">style</span><span class="mtk17">&gt;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk17">&lt;</span><span class="mtk4">body</span><span class="mtk17">&gt;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk17">&lt;</span><span class="mtk4">file-upload</span><span class="mtk1"> </span><span class="mtk12">class</span><span class="mtk1">=</span><span class="mtk8">&quot;upload1&quot;</span><span class="mtk17">&gt;&lt;/</span><span class="mtk4">file-upload</span><span class="mtk17">&gt;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk17">&lt;</span><span class="mtk4">file-upload</span><span class="mtk1"> </span><span class="mtk12">class</span><span class="mtk1">=</span><span class="mtk8">&quot;upload2&quot;</span><span class="mtk17">&gt;&lt;/</span><span class="mtk4">file-upload</span><span class="mtk17">&gt;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk17">&lt;/</span><span class="mtk4">body</span><span class="mtk17">&gt;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk17">&lt;/</span><span class="mtk4">html</span><span class="mtk17">&gt;</span></span></span></code></pre> <p><span class="gatsby-resp-image-wrapper" style="position: relative; display: block; margin-left: auto; margin-right: auto; max-width: 720px; " > <a class="gatsby-resp-image-link" href="/static/f987886596ebdfc33bf31c1f744e66d7/2bef9/image-9-1024x517.png" style="display: block" target="_blank" rel="noopener" > <span class="gatsby-resp-image-background-image" style="padding-bottom: 50.55555555555556%; position: relative; bottom: 0; left: 0; background-image: url('data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABQAAAAKCAYAAAC0VX7mAAAACXBIWXMAAAsTAAALEwEAmpwYAAAA+UlEQVR42mMwVjLmdzZU9tA1V/LU1NT11NXFxJqamgSxlpaWh7GxMT9DVlySXV1u1v/M3JT/sbFx/2JjY0E0FEPY8fHx/xMSEnDhfyA6MTERpN6G4eqji3b7Huz4f/zhgb8/f/788+P7j78/fvz8+x2If/z4AcZ//vz5+/fvfxz43x8o/f/ly5c2DHuP7rVrmFj1f8ri/v9A8O8/6QCu5+nTp7YM9+7ds3tw99H/p4+eUcfAZ8+e2WGTpMjAf//+/Qdhqhj46tUrW1CgA/m/gfgXlCYFg/UAY+Uv0EAbqnoZHMvnz58XuHr1asC1a9cCKcE3btzwB5kFADhOiRWjUs8iAAAAAElFTkSuQmCC'); background-size: cover; display: block;" ></span> <img class="gatsby-resp-image-image" alt="Upload File Component" title="" src="/static/f987886596ebdfc33bf31c1f744e66d7/37523/image-9-1024x517.png" srcset="/static/f987886596ebdfc33bf31c1f744e66d7/e9ff0/image-9-1024x517.png 180w, /static/f987886596ebdfc33bf31c1f744e66d7/f21e7/image-9-1024x517.png 360w, /static/f987886596ebdfc33bf31c1f744e66d7/37523/image-9-1024x517.png 720w, /static/f987886596ebdfc33bf31c1f744e66d7/2bef9/image-9-1024x517.png 1024w" sizes="(max-width: 720px) 100vw, 720px" style="width:100%;height:100%;margin:0;vertical-align:middle;position:absolute;top:0;left:0;" loading="lazy" decoding="async" /> </a> </span></p> <h2 id="enable-custom-attributes" style="position:relative;"><a href="#enable-custom-attributes" aria-label="enable custom attributes permalink" class="anchor before"><svg aria-hidden="true" focusable="false" height="16" version="1.1" viewBox="0 0 16 16" width="16"><path fill-rule="evenodd" d="M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z"></path></svg></a>Enable custom attributes</h2> <p>Just like Angular, Vue, or other libraries, we can pass props to a Web Component from the parent to trigger a certain custom behavior. In this example, we are adding a new <code>upload-label</code> attribute to allow the developer to change the text of the upload button.</p> <ul> <li><code>observedAttributes</code> getter will enable a watcher on specified attributes</li> <li><code>attributeChangedCallback</code> function will update the DOM with the new value</li> </ul> <pre class="grvsc-container default-dark" data-language="javascript" data-index="7"><code class="grvsc-code"><span class="grvsc-line"><span class="grvsc-source"><span class="mtk3">// Create template</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk4">const</span><span class="mtk1"> </span><span class="mtk12">template</span><span class="mtk1"> = </span><span class="mtk12">document</span><span class="mtk1">.</span><span class="mtk11">createElement</span><span class="mtk1">(</span><span class="mtk8">&#39;template&#39;</span><span class="mtk1">);</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk12">template</span><span class="mtk1">.</span><span class="mtk12">innerHTML</span><span class="mtk1"> = </span><span class="mtk3">/*html*/</span><span class="mtk8">`</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk8"> &lt;style&gt;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk8"> :host {</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk8"> font-size: 13px;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk8"> font-family: arial;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk8"> }</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk8"> article {</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk8"> display: flex;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk8"> align-items: center;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk8"> }</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk8"> label {</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk8"> background-color: rgb(239, 239, 239);</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk8"> border: 1px solid rgb(118, 118, 118);</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk8"> padding: 2px 6px 2px 6px;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk8"> border-radius: 2px;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk8"> margin-right: 5px;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk8"> }</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk8"> button {</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk8"> border:0;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk8"> background: transparent;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk8"> cursor: pointer;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk8"> }</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk8"> button::before {</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk8"> content: &#39;</span><span class="mtk6">\\</span><span class="mtk8">2716&#39;;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk8"> }</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk8"> &lt;/style&gt;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk8"> &lt;article&gt;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk8"> &lt;label part=&quot;upload-button&quot; for=&quot;fileUpload&quot;&gt;Upload&lt;/label&gt;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk8"> &lt;section hidden&gt;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk8"> &lt;span&gt;&lt;/span&gt;&lt;button&gt;&lt;/button&gt;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk8"> &lt;/section&gt;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk8"> &lt;/article&gt;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk8"> &lt;input hidden id=&quot;fileUpload&quot; type=&quot;file&quot; /&gt;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk8">`</span><span class="mtk1">;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk4">class</span><span class="mtk1"> </span><span class="mtk10">FileUpload</span><span class="mtk1"> </span><span class="mtk4">extends</span><span class="mtk1"> </span><span class="mtk10">HTMLElement</span><span class="mtk1"> {</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk4">constructor</span><span class="mtk1">() {</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk3">// Inititialize custom component</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk4">super</span><span class="mtk1">();</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk4">this</span><span class="mtk1">.</span><span class="mtk11">attachShadow</span><span class="mtk1">({ </span><span class="mtk12">mode:</span><span class="mtk1"> </span><span class="mtk8">&#39;open&#39;</span><span class="mtk1"> });</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk4">this</span><span class="mtk1">.</span><span class="mtk12">shadowRoot</span><span class="mtk1">.</span><span class="mtk11">appendChild</span><span class="mtk1">(</span><span class="mtk12">template</span><span class="mtk1">.</span><span class="mtk12">content</span><span class="mtk1">.</span><span class="mtk11">cloneNode</span><span class="mtk1">(</span><span class="mtk4">true</span><span class="mtk1">));</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk3">// Add event listeners</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk4">this</span><span class="mtk1">.</span><span class="mtk11">select</span><span class="mtk1">(</span><span class="mtk8">&#39;input&#39;</span><span class="mtk1">).</span><span class="mtk11">onchange</span><span class="mtk1"> = (</span><span class="mtk12">e</span><span class="mtk1">) </span><span class="mtk4">=&gt;</span><span class="mtk1"> </span><span class="mtk4">this</span><span class="mtk1">.</span><span class="mtk11">handleChange</span><span class="mtk1">(</span><span class="mtk12">e</span><span class="mtk1">);</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk4">this</span><span class="mtk1">.</span><span class="mtk11">select</span><span class="mtk1">(</span><span class="mtk8">&#39;button&#39;</span><span class="mtk1">).</span><span class="mtk11">onclick</span><span class="mtk1"> = () </span><span class="mtk4">=&gt;</span><span class="mtk1"> </span><span class="mtk4">this</span><span class="mtk1">.</span><span class="mtk11">handleRemove</span><span class="mtk1">();</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> }</span></span></span> <span class="grvsc-line"><span class="grvsc-source"></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk11">handleChange</span><span class="mtk1">(</span><span class="mtk12">e</span><span class="mtk1">) {</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk4">const</span><span class="mtk1"> </span><span class="mtk12">file</span><span class="mtk1"> = </span><span class="mtk12">e</span><span class="mtk1">.</span><span class="mtk12">target</span><span class="mtk1">.</span><span class="mtk12">files</span><span class="mtk1">[</span><span class="mtk7">0</span><span class="mtk1">];</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk4">this</span><span class="mtk1">.</span><span class="mtk11">select</span><span class="mtk1">(</span><span class="mtk8">&#39;section&#39;</span><span class="mtk1">).</span><span class="mtk12">style</span><span class="mtk1">.</span><span class="mtk12">display</span><span class="mtk1"> = </span><span class="mtk8">&quot;block&quot;</span><span class="mtk1">;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk4">this</span><span class="mtk1">.</span><span class="mtk11">select</span><span class="mtk1">(</span><span class="mtk8">&#39;span&#39;</span><span class="mtk1">).</span><span class="mtk12">innerText</span><span class="mtk1"> = </span><span class="mtk12">file</span><span class="mtk1">.</span><span class="mtk12">name</span><span class="mtk1">;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk4">this</span><span class="mtk1">.</span><span class="mtk11">dispatch</span><span class="mtk1">(</span><span class="mtk8">&#39;change&#39;</span><span class="mtk1">, </span><span class="mtk12">file</span><span class="mtk1">);</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> }</span></span></span> <span class="grvsc-line"><span class="grvsc-source"></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk11">handleRemove</span><span class="mtk1">() {</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk4">const</span><span class="mtk1"> </span><span class="mtk12">el</span><span class="mtk1"> = </span><span class="mtk4">this</span><span class="mtk1">.</span><span class="mtk11">select</span><span class="mtk1">(</span><span class="mtk8">&#39;input&#39;</span><span class="mtk1">);</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk4">const</span><span class="mtk1"> </span><span class="mtk12">file</span><span class="mtk1"> = </span><span class="mtk12">el</span><span class="mtk1">.</span><span class="mtk12">files</span><span class="mtk1">[</span><span class="mtk7">0</span><span class="mtk1">];</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">el</span><span class="mtk1">.</span><span class="mtk12">value</span><span class="mtk1"> = </span><span class="mtk8">&quot;&quot;</span><span class="mtk1">;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk4">this</span><span class="mtk1">.</span><span class="mtk11">select</span><span class="mtk1">(</span><span class="mtk8">&#39;section&#39;</span><span class="mtk1">).</span><span class="mtk12">style</span><span class="mtk1">.</span><span class="mtk12">display</span><span class="mtk1"> = </span><span class="mtk8">&quot;none&quot;</span><span class="mtk1">;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk4">this</span><span class="mtk1">.</span><span class="mtk11">dispatch</span><span class="mtk1">(</span><span class="mtk8">&#39;change&#39;</span><span class="mtk1">, </span><span class="mtk12">file</span><span class="mtk1">);</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> }</span></span></span> <span class="grvsc-line"><span class="grvsc-source"></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk4">static</span><span class="mtk1"> </span><span class="mtk4">get</span><span class="mtk1"> </span><span class="mtk11">observedAttributes</span><span class="mtk1">() {</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk15">return</span><span class="mtk1"> [</span><span class="mtk8">&#39;upload-label&#39;</span><span class="mtk1">];</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> }</span></span></span> <span class="grvsc-line"><span class="grvsc-source"></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk11">attributeChangedCallback</span><span class="mtk1">(</span><span class="mtk12">name</span><span class="mtk1">, </span><span class="mtk12">oldValue</span><span class="mtk1">, </span><span class="mtk12">newValue</span><span class="mtk1">) {</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk15">if</span><span class="mtk1"> (</span><span class="mtk12">name</span><span class="mtk1"> === </span><span class="mtk8">&#39;upload-label&#39;</span><span class="mtk1">) {</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk15">if</span><span class="mtk1"> (</span><span class="mtk12">newValue</span><span class="mtk1"> &amp;&amp; </span><span class="mtk12">newValue</span><span class="mtk1"> !== </span><span class="mtk8">&#39;&#39;</span><span class="mtk1">) {</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk4">this</span><span class="mtk1">.</span><span class="mtk11">select</span><span class="mtk1">(</span><span class="mtk8">&#39;label&#39;</span><span class="mtk1">).</span><span class="mtk12">innerText</span><span class="mtk1"> = </span><span class="mtk12">newValue</span><span class="mtk1">;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> }</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> }</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> }</span></span></span> <span class="grvsc-line"><span class="grvsc-source"></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk11">dispatch</span><span class="mtk1">(</span><span class="mtk12">event</span><span class="mtk1">, </span><span class="mtk12">arg</span><span class="mtk1">) {</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk4">this</span><span class="mtk1">.</span><span class="mtk11">dispatchEvent</span><span class="mtk1">(</span><span class="mtk4">new</span><span class="mtk1"> </span><span class="mtk10">CustomEvent</span><span class="mtk1">(</span><span class="mtk12">event</span><span class="mtk1">, {</span><span class="mtk12">detail:</span><span class="mtk1"> </span><span class="mtk12">arg</span><span class="mtk1">}));</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> }</span></span></span> <span class="grvsc-line"><span class="grvsc-source"></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk4">get</span><span class="mtk1"> </span><span class="mtk11">select</span><span class="mtk1">() {</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk15">return</span><span class="mtk1"> </span><span class="mtk4">this</span><span class="mtk1">.</span><span class="mtk12">shadowRoot</span><span class="mtk1">.</span><span class="mtk12">querySelector</span><span class="mtk1">.</span><span class="mtk11">bind</span><span class="mtk1">(</span><span class="mtk4">this</span><span class="mtk1">.</span><span class="mtk12">shadowRoot</span><span class="mtk1">);</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> }</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1">}</span></span></span> <span class="grvsc-line"><span class="grvsc-source"></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk12">window</span><span class="mtk1">.</span><span class="mtk12">customElements</span><span class="mtk1">.</span><span class="mtk11">define</span><span class="mtk1">(</span><span class="mtk8">&#39;file-upload&#39;</span><span class="mtk1">, </span><span class="mtk12">FileUpload</span><span class="mtk1">);</span></span></span></code></pre> <p>Let’s update <code>main.html</code> file and try it out:</p> <pre class="grvsc-container default-dark" data-language="html" data-index="8"><code class="grvsc-code"><span class="grvsc-line"><span class="grvsc-source"><span class="mtk17">&lt;!</span><span class="mtk4">DOCTYPE</span><span class="mtk1"> </span><span class="mtk12">html</span><span class="mtk17">&gt;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk17">&lt;</span><span class="mtk4">html</span><span class="mtk17">&gt;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk17">&lt;</span><span class="mtk4">script</span><span class="mtk1"> </span><span class="mtk12">src</span><span class="mtk1">=</span><span class="mtk8">&quot;./file-upload.js&quot;</span><span class="mtk17">&gt;&lt;/</span><span class="mtk4">script</span><span class="mtk17">&gt;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk17">&lt;</span><span class="mtk4">style</span><span class="mtk17">&gt;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk4">file-upload</span><span class="mtk1">::part(</span><span class="mtk4">upload-button</span><span class="mtk1">) {</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">border</span><span class="mtk1">: </span><span class="mtk8">none</span><span class="mtk1">;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">color</span><span class="mtk1">: </span><span class="mtk8">white</span><span class="mtk1">;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">padding</span><span class="mtk1">: </span><span class="mtk7">9px</span><span class="mtk1"> </span><span class="mtk7">22px</span><span class="mtk1">;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">font-size</span><span class="mtk1">: </span><span class="mtk7">14px</span><span class="mtk1">;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">margin-bottom</span><span class="mtk1">: </span><span class="mtk7">10px</span><span class="mtk1">;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> }</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk6">.upload1</span><span class="mtk1">::part(</span><span class="mtk4">upload-button</span><span class="mtk1">) {</span><span class="mtk12">background-color</span><span class="mtk1">: </span><span class="mtk8">#4CAF50</span><span class="mtk1">;} </span><span class="mtk3">/* Green */</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk6">.upload2</span><span class="mtk1">::part(</span><span class="mtk4">upload-button</span><span class="mtk1">) {</span><span class="mtk12">background-color</span><span class="mtk1">: </span><span class="mtk8">#555555</span><span class="mtk1">;} </span><span class="mtk3">/* Black */</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk17">&lt;/</span><span class="mtk4">style</span><span class="mtk17">&gt;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk17">&lt;</span><span class="mtk4">body</span><span class="mtk17">&gt;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk17">&lt;</span><span class="mtk4">file-upload</span><span class="mtk1"> </span><span class="mtk12">upload-label</span><span class="mtk1">=</span><span class="mtk8">&quot;Browse...&quot;</span><span class="mtk1"> </span><span class="mtk12">class</span><span class="mtk1">=</span><span class="mtk8">&quot;upload1&quot;</span><span class="mtk17">&gt;&lt;/</span><span class="mtk4">file-upload</span><span class="mtk17">&gt;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk17">&lt;</span><span class="mtk4">file-upload</span><span class="mtk1"> </span><span class="mtk12">upload-label</span><span class="mtk1">=</span><span class="mtk8">&quot;Upload Files&quot;</span><span class="mtk1"> </span><span class="mtk12">class</span><span class="mtk1">=</span><span class="mtk8">&quot;upload2&quot;</span><span class="mtk17">&gt;&lt;/</span><span class="mtk4">file-upload</span><span class="mtk17">&gt;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk17">&lt;/</span><span class="mtk4">body</span><span class="mtk17">&gt;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk17">&lt;/</span><span class="mtk4">html</span><span class="mtk17">&gt;</span></span></span></code></pre> <p><span class="gatsby-resp-image-wrapper" style="position: relative; display: block; margin-left: auto; margin-right: auto; max-width: 720px; " > <a class="gatsby-resp-image-link" href="/static/29c6f90a483ee94d93230c1497f2758f/2bef9/image-11-1024x595.png" style="display: block" target="_blank" rel="noopener" > <span class="gatsby-resp-image-background-image" style="padding-bottom: 58.333333333333336%; position: relative; bottom: 0; left: 0; background-image: url('data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABQAAAAMCAYAAABiDJ37AAAACXBIWXMAAAsTAAALEwEAmpwYAAABAElEQVR42mOw11c1MLZRNdfS1zLT19fHirW0tPBiTU1NcyA2ZGBgYGbICAl9kZgQ8t/L2/uPu5v7Pw8PDxTs6en5z8vLCx/+6+3t/R+o7l1AQIAww8lHh18derjr/4M3d/9+/fLt/4ePH/9//PgJjr98+fL/+/cfOPG3b9///f79B6ju64f9+8+IMHTOb3pVNbXo/5rtK/7+B4J/QEgiAGv4/fv3hzNngAZeuXD11Y1LN/9fv3r9799/f/+TAVANBDJeQSXIMg3DwJ8/f4IN/AsEVDGQ6i6kuoF//vx5CZX4A5UkFf+lrQuBhPnRo0edjh8/7kAuBukHmmOxatUqZgB2nRpYRUw+vAAAAABJRU5ErkJggg=='); background-size: cover; display: block;" ></span> <img class="gatsby-resp-image-image" alt="Upload File Component" title="" src="/static/29c6f90a483ee94d93230c1497f2758f/37523/image-11-1024x595.png" srcset="/static/29c6f90a483ee94d93230c1497f2758f/e9ff0/image-11-1024x595.png 180w, /static/29c6f90a483ee94d93230c1497f2758f/f21e7/image-11-1024x595.png 360w, /static/29c6f90a483ee94d93230c1497f2758f/37523/image-11-1024x595.png 720w, /static/29c6f90a483ee94d93230c1497f2758f/2bef9/image-11-1024x595.png 1024w" sizes="(max-width: 720px) 100vw, 720px" style="width:100%;height:100%;margin:0;vertical-align:middle;position:absolute;top:0;left:0;" loading="lazy" decoding="async" /> </a> </span></p> <h2 id="conclusion" style="position:relative;"><a href="#conclusion" aria-label="conclusion permalink" class="anchor before"><svg aria-hidden="true" focusable="false" height="16" version="1.1" viewBox="0 0 16 16" width="16"><path fill-rule="evenodd" d="M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z"></path></svg></a>Conclusion</h2> <p>In this article, I wanted to demonstrate how you can use vanilla JavaScript to write a custom and framework agnostic file uploader that works everywhere. In most cases, I would typically use libraries such as <a href="https://lit.dev/">Lit</a> or <a href="https://stenciljs.com/">Stencil</a>. They provide a more declarative style of writing Web Components which will scale better and speed up the development process. </p> <p>You can access the <a href="https://github.com/muhimasri/custom-file-upload">complete repository here</a>.</p> <p>Bye for now 👋</p> <style class="grvsc-styles"> .grvsc-container { overflow: auto; position: relative; -webkit-overflow-scrolling: touch; padding-top: 1rem; padding-top: var(--grvsc-padding-top, var(--grvsc-padding-v, 1rem)); padding-bottom: 1rem; padding-bottom: var(--grvsc-padding-bottom, var(--grvsc-padding-v, 1rem)); border-radius: 8px; border-radius: var(--grvsc-border-radius, 8px); font-feature-settings: normal; line-height: 1.4; } .grvsc-code { display: table; } .grvsc-line { display: table-row; box-sizing: border-box; width: 100%; position: relative; } .grvsc-line > * { position: relative; } .grvsc-gutter-pad { display: table-cell; padding-left: 0.75rem; padding-left: calc(var(--grvsc-padding-left, var(--grvsc-padding-h, 1.5rem)) / 2); } .grvsc-gutter { display: table-cell; -webkit-user-select: none; -moz-user-select: none; user-select: none; } .grvsc-gutter::before { content: attr(data-content); } .grvsc-source { display: table-cell; padding-left: 1.5rem; padding-left: var(--grvsc-padding-left, var(--grvsc-padding-h, 1.5rem)); padding-right: 1.5rem; padding-right: var(--grvsc-padding-right, var(--grvsc-padding-h, 1.5rem)); } .grvsc-source:empty::after { content: ' '; -webkit-user-select: none; -moz-user-select: none; user-select: none; } .grvsc-gutter + .grvsc-source { padding-left: 0.75rem; padding-left: calc(var(--grvsc-padding-left, var(--grvsc-padding-h, 1.5rem)) / 2); } /* Line transformer styles */ .grvsc-has-line-highlighting > .grvsc-code > .grvsc-line::before { content: ' '; position: absolute; width: 100%; } .grvsc-line-diff-add::before { background-color: var(--grvsc-line-diff-add-background-color, rgba(0, 255, 60, 0.2)); } .grvsc-line-diff-del::before { background-color: var(--grvsc-line-diff-del-background-color, rgba(255, 0, 20, 0.2)); } .grvsc-line-number { padding: 0 2px; text-align: right; opacity: 0.7; } .default-dark { background-color: #1E1E1E; color: #D4D4D4; } .default-dark .mtk3 { color: #6A9955; } .default-dark .mtk4 { color: #569CD6; } .default-dark .mtk1 { color: #D4D4D4; } .default-dark .mtk12 { color: #9CDCFE; } .default-dark .mtk11 { color: #DCDCAA; } .default-dark .mtk8 { color: #CE9178; } .default-dark .mtk10 { color: #4EC9B0; } .default-dark .mtk17 { color: #808080; } .default-dark .mtk7 { color: #B5CEA8; } .default-dark .mtk15 { color: #C586C0; } .default-dark .mtk6 { color: #D7BA7D; } .default-dark .grvsc-line-highlighted::before { background-color: var(--grvsc-line-highlighted-background-color, rgba(255, 255, 255, 0.1)); box-shadow: inset var(--grvsc-line-highlighted-border-width, 4px) 0 0 0 var(--grvsc-line-highlighted-border-color, rgba(255, 255, 255, 0.5)); } </style><![CDATA[4 Effective Tools for Building a React Design System]]>https://muhimasri.com4-effective-tools-for-building-a-react-design-systemhttps://muhimasri.com4-effective-tools-for-building-a-react-design-system<p>Building a design system is a progressive and abstractive approach to maintaining a consistent and cost-efficient components library that follows a specific styling guide and is sharable across multiple products. A design system has always been associated with designers but now it’s becoming critical for frontend developers to understand it from the technology perspective.</p> <p>In this article, I will share some of the tools I used to successfully build a design system in React. Of course, before building the library, we require the designer’s expertise to develop the brand’s look and feel, user experience, style guide, etc.</p> <h2 id="create-react-library" style="position:relative;"><a href="#create-react-library" aria-label="create react library permalink" class="anchor before"><svg aria-hidden="true" focusable="false" height="16" version="1.1" viewBox="0 0 16 16" width="16"><path fill-rule="evenodd" d="M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z"></path></svg></a>create-react-library</h2> <p>One of the essential parts of providing a design system library is to be able to have an independent React components solution that can be published and used by other projects.</p> <p><a href="https://www.npmjs.com/package/create-react-library">create-react-library</a> is a CLI for creating reusable React libraries using Rollup and <a href="https://reactjs.org/docs/create-a-new-react-app.html">create-react-app</a>. All you need to do is a simple global installation <code>npm install -g create-react-library</code>, then <code>create-react-library</code>, followed by few questions about your package and you have it all! A Boilerplate project for publishing React components.</p> <p><span class="gatsby-resp-image-wrapper" style="position: relative; display: block; margin-left: auto; margin-right: auto; max-width: 720px; " > <a class="gatsby-resp-image-link" href="/static/19bbcecad46163d2162da8db921219ec/2bef9/image-7-1024x928.png" style="display: block" target="_blank" rel="noopener" > <span class="gatsby-resp-image-background-image" style="padding-bottom: 90.55555555555556%; position: relative; bottom: 0; left: 0; background-image: url('data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABQAAAASCAYAAABb0P4QAAAACXBIWXMAAAsTAAALEwEAmpwYAAACI0lEQVR42p1UXW+bQBDkl6RSbMAYjsPGgPmwwYCNU6lSqzxVrfIQ8wtSKY6Uf26dtZm9JH2IIsX2w2q54zQ3szt7RrfK3Z/b5Kmosoc8zf/lOQI5TdNPg/9/XBdF8YD8hDw22rrtf9z+onpTq6auqW5qapqGuq6j1WpFbdtSzfv16z7nzWaj83q9pqqqaLFYHPks8s6ot993+c0tFuUBN6jlcqnwQ+GAms/nivfARGVZpsBCf5dlpTOfjeNYhWF4SJKEZrPZvXF396e/+/ubfN9Xtj0iKQMyTYuurr7R9fVAx2Aw/P/9cY/zcGgeRyOHLMvaGV1301fVioTwwaCgpl3TpttSksyJL+CwLPuLsI6v55ydAbo9JJIMAg0IGcQXcO3yYnEioP3GEIBRFPWoFbmup8Zjl6bTkBxn/C5Fyz8h3hhCMsB67pjnCcVALDWOE15rdmcDMkN0TDN0HBe1lBqI2V4EyAzZQ74vlUCHoyjWnQ4QF0uG13SXPV9SluVoTKllXwTIknkCAnTZFyNK04ymYXgq0OeAZVmSgLHHnktZnhO7nm1wsWSeRyGEksLVDN9NzdY5GxAzqiXrGroMmGpQKSfaOmzcswAxKTsMNQDdw3Q6wrQs9EMAlkpKqXBImab5VRxs24Yq+15LBgBbRQWzCE8WP2ENJZgeZse1PCGO7FvHweiBnYcmPE/C8FFMwj2+91GU7MF8j7qeGo+IZyhyXwCdQgB/EVS65AAAAABJRU5ErkJggg=='); background-size: cover; display: block;" ></span> <img class="gatsby-resp-image-image" alt="image 7 1024x928" title="" src="/static/19bbcecad46163d2162da8db921219ec/37523/image-7-1024x928.png" srcset="/static/19bbcecad46163d2162da8db921219ec/e9ff0/image-7-1024x928.png 180w, /static/19bbcecad46163d2162da8db921219ec/f21e7/image-7-1024x928.png 360w, /static/19bbcecad46163d2162da8db921219ec/37523/image-7-1024x928.png 720w, /static/19bbcecad46163d2162da8db921219ec/2bef9/image-7-1024x928.png 1024w" sizes="(max-width: 720px) 100vw, 720px" style="width:100%;height:100%;margin:0;vertical-align:middle;position:absolute;top:0;left:0;" loading="lazy" decoding="async" /> </a> </span></p> <ul> <li><code>src</code> folder is where you develop and export components.</li> <li><code>example</code> folder is for testing your components.</li> </ul> <h2 id="material-ui-mui" style="position:relative;"><a href="#material-ui-mui" aria-label="material ui mui permalink" class="anchor before"><svg aria-hidden="true" focusable="false" height="16" version="1.1" viewBox="0 0 16 16" width="16"><path fill-rule="evenodd" d="M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z"></path></svg></a>Material UI (MUI)</h2> <p><a href="https://material-ui.com/">MUI</a> can serve as a powerful base layer for your design system and can be easily customized to meet your component’s requirements.</p> <p>Advantages of using MUI over building components from scratch:</p> <ul> <li>Built-in functionalities that will take a while to build from scratch, e.g. Dialogs, Autocomplete, Trees, Tables…</li> <li>Material is not only a library but a design system guide that helps you follow best design practices</li> <li>Responsive components that work on different devices</li> <li>Supported by Google</li> </ul> <p>MUI uses <a href="https://emotion.sh/docs/introduction">Emotion</a> as the base styling solution to style your application, but it also provides several other options such as plain CSS, Tailwind CSS, Styled Components… For more details, you can read the documentation on <a href="https://mui.com/guides/interoperability/">Style Library Interoperability</a>.</p> <p><span class="gatsby-resp-image-wrapper" style="position: relative; display: block; margin-left: auto; margin-right: auto; max-width: 720px; " > <a class="gatsby-resp-image-link" href="/static/a84a00732a0d82ed3dec4b82f342914a/2bef9/image-1-1024x216.png" style="display: block" target="_blank" rel="noopener" > <span class="gatsby-resp-image-background-image" style="padding-bottom: 21.111111111111114%; position: relative; bottom: 0; left: 0; background-image: url('data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABQAAAAECAIAAAABPYjBAAAACXBIWXMAAAsTAAALEwEAmpwYAAAAd0lEQVR42mMQ17AX13Dgl7flU7DlkbPhkrHilrXikbPilbMmiBj4FawU9Fz1DX00Db019D0VNFwkVB0EFGz55G0IaxZUspfRdJVUdZDXcAbqVNB0kVF3klZ3ElK05ZElYD+DsIoDv6Itt4wll6wVBHHLQlxO2NkAi+IiPb/8wlUAAAAASUVORK5CYII='); background-size: cover; display: block;" ></span> <img class="gatsby-resp-image-image" alt="image 1 1024x216" title="" src="/static/a84a00732a0d82ed3dec4b82f342914a/37523/image-1-1024x216.png" srcset="/static/a84a00732a0d82ed3dec4b82f342914a/e9ff0/image-1-1024x216.png 180w, /static/a84a00732a0d82ed3dec4b82f342914a/f21e7/image-1-1024x216.png 360w, /static/a84a00732a0d82ed3dec4b82f342914a/37523/image-1-1024x216.png 720w, /static/a84a00732a0d82ed3dec4b82f342914a/2bef9/image-1-1024x216.png 1024w" sizes="(max-width: 720px) 100vw, 720px" style="width:100%;height:100%;margin:0;vertical-align:middle;position:absolute;top:0;left:0;" loading="lazy" decoding="async" /> </a> </span></p> <h2 id="storybook" style="position:relative;"><a href="#storybook" aria-label="storybook permalink" class="anchor before"><svg aria-hidden="true" focusable="false" height="16" version="1.1" viewBox="0 0 16 16" width="16"><path fill-rule="evenodd" d="M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z"></path></svg></a>Storybook</h2> <p>Storybook is a great tool for documenting, showcasing, and testing components with designers, managers, and developers. It allows you to create a story for each component that showcases different variants, behaviors, and features of your component.</p> <p><span class="gatsby-resp-image-wrapper" style="position: relative; display: block; margin-left: auto; margin-right: auto; max-width: 720px; " > <a class="gatsby-resp-image-link" href="/static/ff519d6518900d4be0ce86bbf3655913/c8252/example-button-args.png" style="display: block" target="_blank" rel="noopener" > <span class="gatsby-resp-image-background-image" style="padding-bottom: 76.11111111111111%; position: relative; bottom: 0; left: 0; background-image: url('data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABQAAAAPCAYAAADkmO9VAAAACXBIWXMAAAsTAAALEwEAmpwYAAACKElEQVR42qWTz4vTQBTHC3sRj4KuRfyj/C8EKQhbFHrppb1ItyfLnmTxKnjRuyBeLbbdza51a7NNU9uy22aaTCbJZGaeb6ZNbRcWtvjgG5JH8pn345vccfn4Xvv71xdW/+SVbdsHlmUVW61WsXtxUXQcx6jf7xs57vK52+3iOydGnc7pQa/Xe91sNp+Xy+X7ubflN48XjuvNiAchi1XMBTCuQEoJSikjIQTwNDU5HSaH91qpECZJyGJ6eHj0JFepVPLeLJx5PoN5wNKYS/HxEsRnBwS+dxdxDUySZFxrNJ7m6ggk82sShyFInuDRKZzNFZyi7himwiiKprUaAp+9rOff/fDIh58M3p+n6pOtW4VdYgWMl8ASVmhNKDmfUPg148pZCJAKdoFuA+v1en56NScsZNitVCkOf8fYBuqlXHk+iVMFDC9RIsw2BZbJhd72ctM6d1Nq2YYBsmyGumWfMoLfroAphJQC5RL+MDwZC07iGHTlmY0y62wCvQWdNhor4CL4B4yxwgCBhBDg3DjCwLQXM/m+DyG6wviTcwOkIbsd6AeBtsG6Gg33PM8AdC47YDWKbduUSthywOb4g0AYcRlGiWKMKSmEknqA2B2lVGFFCiFGOp/dC03WM2Rssl4KupysNmZqurnpjQXcuuU4SZYtFwqFh79t55s9HFn2wG2jOoPhsOOORmsNXddoM7eh9mg8PrscDL5Uq9X9HMYe6gHq0X9KM/b+AhS281GOWLwMAAAAAElFTkSuQmCC'); background-size: cover; display: block;" ></span> <img class="gatsby-resp-image-image" alt="Button story with args" title="" src="/static/ff519d6518900d4be0ce86bbf3655913/37523/example-button-args.png" srcset="/static/ff519d6518900d4be0ce86bbf3655913/e9ff0/example-button-args.png 180w, /static/ff519d6518900d4be0ce86bbf3655913/f21e7/example-button-args.png 360w, /static/ff519d6518900d4be0ce86bbf3655913/37523/example-button-args.png 720w, /static/ff519d6518900d4be0ce86bbf3655913/302a4/example-button-args.png 1080w, /static/ff519d6518900d4be0ce86bbf3655913/07a9c/example-button-args.png 1440w, /static/ff519d6518900d4be0ce86bbf3655913/c8252/example-button-args.png 2178w" sizes="(max-width: 720px) 100vw, 720px" style="width:100%;height:100%;margin:0;vertical-align:middle;position:absolute;top:0;left:0;" loading="lazy" decoding="async" /> </a> </span></p> <p>Designers can provide feedback and updates while developers can test and learn how to work with your components.</p> <p>Besides documentation, it has plenty of other useful features and plugins such as:</p> <ul> <li>Unit test functionality</li> <li>Accessibility testing</li> <li>Visual test appearance</li> </ul> <h2 id="style-dictionary-and-design-tokens" style="position:relative;"><a href="#style-dictionary-and-design-tokens" aria-label="style dictionary and design tokens permalink" class="anchor before"><svg aria-hidden="true" focusable="false" height="16" version="1.1" viewBox="0 0 16 16" width="16"><path fill-rule="evenodd" d="M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z"></path></svg></a>Style Dictionary and Design Tokens:</h2> <p>Design tokens are defined as all the values needed to construct and maintain a design system — spacing, color, typography, border, shadow, etc.</p> <p><a href="https://amzn.github.io/style-dictionary/#/README">Style Dictionary</a> enables you to create and organize all Design Tokens as variables in a JSON format and automatically transform it into any format like JS, SASS, XML (for Android), etc.</p> <p><span class="gatsby-resp-image-wrapper" style="position: relative; display: block; margin-left: auto; margin-right: auto; max-width: 720px; " > <a class="gatsby-resp-image-link" href="/static/1d16df4a58a3f352f0cc34dda263cbf7/2bef9/image-10-1024x308.png" style="display: block" target="_blank" rel="noopener" > <span class="gatsby-resp-image-background-image" style="padding-bottom: 30%; position: relative; bottom: 0; left: 0; background-image: url('data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABQAAAAGCAYAAADDl76dAAAACXBIWXMAAAsTAAALEwEAmpwYAAABeElEQVR42nXOTU/CQBAG4I0iShRp6Qc13bJLt/SbKoIaTRRRUSNePHjWfwPiDXvUn2nihk3GtRo9eXjyZiaTmUGP44uru7uTl8HweHpxejr7dfafsx9/vdH5cCpzPhoOL5EXbz830wxMr7MwWinorQQMtyMzBo3GYLSibyQAnfoFrfBVB3I2BJOGiwZLwQmzGapY7EllAeB+52ODJmJlyxdLJhOKbgvNMAWqYYFUR5RwIEpWJMpWLCo4E6sNT6xZrkAKkfAHUjHIXVNUxe3J1wd4b/+90T3kzXTEVdLjK3bIV5s9vqS6fNmgXN8fcDu95f7BPc8GD9zvXfPk4IhbSZ+revdd0zKoYDZB647/rLAE7M7OQmntQNXahrIZAap7gBQGSKeADAplEsOancEm6QLrd6Hq7MJmHIASRyCPLpYNBuu2P0O6m46VZvim+9G87iV53U3zGo1ytRDkKokKNbudVx1PcmWfFrlB2pKX10g4V0jwKnfdfAIXjJNbAf4AjAAAAABJRU5ErkJggg=='); background-size: cover; display: block;" ></span> <img class="gatsby-resp-image-image" alt="image 10 1024x308" title="" src="/static/1d16df4a58a3f352f0cc34dda263cbf7/37523/image-10-1024x308.png" srcset="/static/1d16df4a58a3f352f0cc34dda263cbf7/e9ff0/image-10-1024x308.png 180w, /static/1d16df4a58a3f352f0cc34dda263cbf7/f21e7/image-10-1024x308.png 360w, /static/1d16df4a58a3f352f0cc34dda263cbf7/37523/image-10-1024x308.png 720w, /static/1d16df4a58a3f352f0cc34dda263cbf7/2bef9/image-10-1024x308.png 1024w" sizes="(max-width: 720px) 100vw, 720px" style="width:100%;height:100%;margin:0;vertical-align:middle;position:absolute;top:0;left:0;" loading="lazy" decoding="async" /> </a> </span></p> <p>It is a powerful tool for both designers and developers. As a designer, you control all the design system values to ensure consistency, and as a developer, you don’t need to create and structure style variables for every project that follows the same style guide. As soon as there is a design update, the designer will change the value and it will reflect on all platforms. Awesome!</p> <h2 id="takeaway" style="position:relative;"><a href="#takeaway" aria-label="takeaway permalink" class="anchor before"><svg aria-hidden="true" focusable="false" height="16" version="1.1" viewBox="0 0 16 16" width="16"><path fill-rule="evenodd" d="M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z"></path></svg></a>Takeaway</h2> <p>A design system is a hot topic and an integral part of many companies. Following the best practices to building a design system will ensure scalable and cost-efficient products.</p> <p>Bye for now 👋</p> <style class="grvsc-styles"> .grvsc-container { overflow: auto; position: relative; -webkit-overflow-scrolling: touch; padding-top: 1rem; padding-top: var(--grvsc-padding-top, var(--grvsc-padding-v, 1rem)); padding-bottom: 1rem; padding-bottom: var(--grvsc-padding-bottom, var(--grvsc-padding-v, 1rem)); border-radius: 8px; border-radius: var(--grvsc-border-radius, 8px); font-feature-settings: normal; line-height: 1.4; } .grvsc-code { display: table; } .grvsc-line { display: table-row; box-sizing: border-box; width: 100%; position: relative; } .grvsc-line > * { position: relative; } .grvsc-gutter-pad { display: table-cell; padding-left: 0.75rem; padding-left: calc(var(--grvsc-padding-left, var(--grvsc-padding-h, 1.5rem)) / 2); } .grvsc-gutter { display: table-cell; -webkit-user-select: none; -moz-user-select: none; user-select: none; } .grvsc-gutter::before { content: attr(data-content); } .grvsc-source { display: table-cell; padding-left: 1.5rem; padding-left: var(--grvsc-padding-left, var(--grvsc-padding-h, 1.5rem)); padding-right: 1.5rem; padding-right: var(--grvsc-padding-right, var(--grvsc-padding-h, 1.5rem)); } .grvsc-source:empty::after { content: ' '; -webkit-user-select: none; -moz-user-select: none; user-select: none; } .grvsc-gutter + .grvsc-source { padding-left: 0.75rem; padding-left: calc(var(--grvsc-padding-left, var(--grvsc-padding-h, 1.5rem)) / 2); } /* Line transformer styles */ .grvsc-has-line-highlighting > .grvsc-code > .grvsc-line::before { content: ' '; position: absolute; width: 100%; } .grvsc-line-diff-add::before { background-color: var(--grvsc-line-diff-add-background-color, rgba(0, 255, 60, 0.2)); } .grvsc-line-diff-del::before { background-color: var(--grvsc-line-diff-del-background-color, rgba(255, 0, 20, 0.2)); } .grvsc-line-number { padding: 0 2px; text-align: right; opacity: 0.7; } </style><![CDATA[[Part 1] Create an Editable Table with Bootstrap Vue]]>https://muhimasri.comcreate-an-editable-dynamic-table-with-bootstrap-vuehttps://muhimasri.comcreate-an-editable-dynamic-table-with-bootstrap-vue<p>This series focuses on implementing new features to the Bootstrap Vue table component that enable users to edit data with dynamic and flexible schema.</p> <p><a href="https://bootstrap-vue.org/">BootstrapVue</a> offers components with extensive features that can be used for almost any application. With the power of Vue, Bootstrap components can be easily extended and customized to meet your product’s requirements.</p> <p>In this part, we’ll go through a step-by-step guide to how to customize a Bootstrap table to enable inline editing, on both row and cell levels. The end results will look and behave as follows:</p> <h5 id="bootstrap-vue-table-with-inline-row-editing" style="position:relative;"><a href="#bootstrap-vue-table-with-inline-row-editing" aria-label="bootstrap vue table with inline row editing permalink" class="anchor before"><svg aria-hidden="true" focusable="false" height="16" version="1.1" viewBox="0 0 16 16" width="16"><path fill-rule="evenodd" d="M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z"></path></svg></a>Bootstrap Vue Table with inline row editing:</h5> <div data-youtube="dsK_Y-ZHMHg"> <button>Play Example</button> </div> <h5 id="bootstrap-vue-table-with-inline-cell-editing" style="position:relative;"><a href="#bootstrap-vue-table-with-inline-cell-editing" aria-label="bootstrap vue table with inline cell editing permalink" class="anchor before"><svg aria-hidden="true" focusable="false" height="16" version="1.1" viewBox="0 0 16 16" width="16"><path fill-rule="evenodd" d="M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z"></path></svg></a>Bootstrap Vue Table with inline cell editing:</h5> <div data-youtube="xSX3APgkdYw"> <button>Play Example</button> </div> <p>The object in red is a demonstration of two-way binding on the items being passed into the component. In real life, you would probably edit either a row or a cell but for the sake of this tutorial, we are doing both!</p> <h2 id="vue-setup" style="position:relative;"><a href="#vue-setup" aria-label="vue setup permalink" class="anchor before"><svg aria-hidden="true" focusable="false" height="16" version="1.1" viewBox="0 0 16 16" width="16"><path fill-rule="evenodd" d="M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z"></path></svg></a>Vue setup</h2> <p>Create a new Vue app using <a href="https://cli.vuejs.org/">Vue CLI</a>.</p> <pre class="grvsc-container default-dark" data-language="" data-index="0"><code class="grvsc-code"><span class="grvsc-line"><span class="grvsc-source">npm install -g @vue/cli @vue/cli-service-global</span></span> <span class="grvsc-line"><span class="grvsc-source">vue create vue-editable-table</span></span></code></pre> <h2 id="bootstrap-setup" style="position:relative;"><a href="#bootstrap-setup" aria-label="bootstrap setup permalink" class="anchor before"><svg aria-hidden="true" focusable="false" height="16" version="1.1" viewBox="0 0 16 16" width="16"><path fill-rule="evenodd" d="M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z"></path></svg></a>Bootstrap setup</h2> <p>Install both Bootstrap and Bootstrap Vue.</p> <pre class="grvsc-container default-dark" data-language="" data-index="1"><code class="grvsc-code"><span class="grvsc-line"><span class="grvsc-source">npm install bootstrap bootstrap-vue</span></span></code></pre> <p>In the <code>main.js</code> file, we will add the following code to make all Bootstrap components accessible everywhere.</p> <pre class="grvsc-container default-dark" data-language="javascript" data-index="2"><code class="grvsc-code"><span class="grvsc-line"><span class="grvsc-source"><span class="mtk15">import</span><span class="mtk1"> </span><span class="mtk12">Vue</span><span class="mtk1"> </span><span class="mtk15">from</span><span class="mtk1"> </span><span class="mtk8">&#39;vue&#39;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk15">import</span><span class="mtk1"> </span><span class="mtk12">App</span><span class="mtk1"> </span><span class="mtk15">from</span><span class="mtk1"> </span><span class="mtk8">&#39;./App.vue&#39;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk15">import</span><span class="mtk1"> { </span><span class="mtk12">BootstrapVue</span><span class="mtk1">, </span><span class="mtk12">IconsPlugin</span><span class="mtk1"> } </span><span class="mtk15">from</span><span class="mtk1"> </span><span class="mtk8">&#39;bootstrap-vue&#39;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk3">// Import Bootstrap an BootstrapVue CSS files (order is important)</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk15">import</span><span class="mtk1"> </span><span class="mtk8">&#39;bootstrap/dist/css/bootstrap.css&#39;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk15">import</span><span class="mtk1"> </span><span class="mtk8">&#39;bootstrap-vue/dist/bootstrap-vue.css&#39;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk3">// Make BootstrapVue available throughout your project</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk12">Vue</span><span class="mtk1">.</span><span class="mtk11">use</span><span class="mtk1">(</span><span class="mtk12">BootstrapVue</span><span class="mtk1">)</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk3">// Optionally install the BootstrapVue icon components plugin</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk12">Vue</span><span class="mtk1">.</span><span class="mtk11">use</span><span class="mtk1">(</span><span class="mtk12">IconsPlugin</span><span class="mtk1">)</span></span></span> <span class="grvsc-line"><span class="grvsc-source"></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk12">Vue</span><span class="mtk1">.</span><span class="mtk12">config</span><span class="mtk1">.</span><span class="mtk12">productionTip</span><span class="mtk1"> = </span><span class="mtk4">false</span></span></span> <span class="grvsc-line"><span class="grvsc-source"></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk4">new</span><span class="mtk1"> </span><span class="mtk10">Vue</span><span class="mtk1">({</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk11">render</span><span class="mtk12">:</span><span class="mtk1"> </span><span class="mtk12">h</span><span class="mtk1"> </span><span class="mtk4">=&gt;</span><span class="mtk1"> </span><span class="mtk11">h</span><span class="mtk1">(</span><span class="mtk12">App</span><span class="mtk1">),</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1">}).</span><span class="mtk11">$mount</span><span class="mtk1">(</span><span class="mtk8">&#39;#app&#39;</span><span class="mtk1">)</span></span></span></code></pre> <h2 id="basic-data-table" style="position:relative;"><a href="#basic-data-table" aria-label="basic data table permalink" class="anchor before"><svg aria-hidden="true" focusable="false" height="16" version="1.1" viewBox="0 0 16 16" width="16"><path fill-rule="evenodd" d="M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z"></path></svg></a>Basic data table</h2> <p>VTable is the main component for creating data tables in Bootstrap. In the example below, we are passing it two props:</p> <ul> <li><code>items</code> containing the list of objects for displaying data on the grid.</li> <li><code>fields</code> that defines the column’s schema (for now we only have key and label). <code>label</code> is for specifying the name on the header and <code>key</code> is a unique id used by Bootstrap for custom cell slots, more on that later.</li> </ul> <pre class="grvsc-container default-dark" data-language="html" data-index="3"><code class="grvsc-code"><span class="grvsc-line"><span class="grvsc-source"><span class="mtk17">&lt;</span><span class="mtk4">template</span><span class="mtk17">&gt;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk17">&lt;</span><span class="mtk4">div</span><span class="mtk1"> </span><span class="mtk12">id</span><span class="mtk1">=</span><span class="mtk8">&quot;app&quot;</span><span class="mtk17">&gt;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk17">&lt;</span><span class="mtk4">b-table</span><span class="mtk1"> </span><span class="mtk12">:items</span><span class="mtk1">=</span><span class="mtk8">&quot;items&quot;</span><span class="mtk1"> </span><span class="mtk12">:fields</span><span class="mtk1">=</span><span class="mtk8">&quot;fields&quot;</span><span class="mtk17">&gt;&lt;/</span><span class="mtk4">b-table</span><span class="mtk17">&gt;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk17">&lt;/</span><span class="mtk4">div</span><span class="mtk17">&gt;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk17">&lt;/</span><span class="mtk4">template</span><span class="mtk17">&gt;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk17">&lt;</span><span class="mtk4">script</span><span class="mtk17">&gt;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk15">export</span><span class="mtk1"> </span><span class="mtk15">default</span><span class="mtk1"> {</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">name:</span><span class="mtk1"> </span><span class="mtk8">&quot;App&quot;</span><span class="mtk1">,</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">components:</span><span class="mtk1"> {},</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk11">data</span><span class="mtk1">() {</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk15">return</span><span class="mtk1"> {</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">fields:</span><span class="mtk1"> [</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> { </span><span class="mtk12">key:</span><span class="mtk1"> </span><span class="mtk8">&quot;name&quot;</span><span class="mtk1">, </span><span class="mtk12">label:</span><span class="mtk1"> </span><span class="mtk8">&quot;Name&quot;</span><span class="mtk1">},</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> { </span><span class="mtk12">key:</span><span class="mtk1"> </span><span class="mtk8">&quot;department&quot;</span><span class="mtk1">, </span><span class="mtk12">label:</span><span class="mtk1"> </span><span class="mtk8">&quot;Department&quot;</span><span class="mtk1"> },</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> { </span><span class="mtk12">key:</span><span class="mtk1"> </span><span class="mtk8">&quot;age&quot;</span><span class="mtk1">, </span><span class="mtk12">label:</span><span class="mtk1"> </span><span class="mtk8">&quot;Age&quot;</span><span class="mtk1"> },</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> { </span><span class="mtk12">key:</span><span class="mtk1"> </span><span class="mtk8">&quot;dateOfBirth&quot;</span><span class="mtk1">, </span><span class="mtk12">label:</span><span class="mtk1"> </span><span class="mtk8">&quot;Date Of Birth&quot;</span><span class="mtk1"> },</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> ],</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">items:</span><span class="mtk1"> [</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> { </span><span class="mtk12">age:</span><span class="mtk1"> </span><span class="mtk7">40</span><span class="mtk1">, </span><span class="mtk12">name:</span><span class="mtk1"> </span><span class="mtk8">&#39;Dickerson&#39;</span><span class="mtk1">, </span><span class="mtk12">department:</span><span class="mtk1"> </span><span class="mtk8">&#39;Development&#39;</span><span class="mtk1">, </span><span class="mtk12">dateOfBirth:</span><span class="mtk1"> </span><span class="mtk8">&#39;1984-05-20&#39;</span><span class="mtk1"> },</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> { </span><span class="mtk12">age:</span><span class="mtk1"> </span><span class="mtk7">21</span><span class="mtk1">, </span><span class="mtk12">name:</span><span class="mtk1"> </span><span class="mtk8">&#39;Larsen&#39;</span><span class="mtk1">, </span><span class="mtk12">department:</span><span class="mtk1"> </span><span class="mtk8">&#39;Marketing&#39;</span><span class="mtk1">, </span><span class="mtk12">dateOfBirth:</span><span class="mtk1"> </span><span class="mtk8">&#39;1984-05-20&#39;</span><span class="mtk1"> },</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> { </span><span class="mtk12">age:</span><span class="mtk1"> </span><span class="mtk7">89</span><span class="mtk1">, </span><span class="mtk12">name:</span><span class="mtk1"> </span><span class="mtk8">&#39;Geneva&#39;</span><span class="mtk1">, </span><span class="mtk12">department:</span><span class="mtk1"> </span><span class="mtk8">&#39;HR&#39;</span><span class="mtk1">, </span><span class="mtk12">dateOfBirth:</span><span class="mtk1"> </span><span class="mtk8">&#39;1984-05-20&#39;</span><span class="mtk1"> },</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> { </span><span class="mtk12">age:</span><span class="mtk1"> </span><span class="mtk7">38</span><span class="mtk1">, </span><span class="mtk12">name:</span><span class="mtk1"> </span><span class="mtk8">&#39;Jami&#39;</span><span class="mtk1">, </span><span class="mtk12">department:</span><span class="mtk1"> </span><span class="mtk8">&#39;Accounting&#39;</span><span class="mtk1">, </span><span class="mtk12">dateOfBirth:</span><span class="mtk1"> </span><span class="mtk8">&#39;1984-05-20&#39;</span><span class="mtk1"> }</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> ],</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> };</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> },</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1">};</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk17">&lt;/</span><span class="mtk4">script</span><span class="mtk17">&gt;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk17">&lt;</span><span class="mtk4">style</span><span class="mtk17">&gt;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk6">#app</span><span class="mtk1"> {</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">text-align</span><span class="mtk1">: </span><span class="mtk8">center</span><span class="mtk1">;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">margin-top</span><span class="mtk1">: </span><span class="mtk7">60px</span><span class="mtk1">;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1">}</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk6">thead</span><span class="mtk1">, </span><span class="mtk6">tbody</span><span class="mtk1">, </span><span class="mtk6">tfoot</span><span class="mtk1">, </span><span class="mtk6">tr</span><span class="mtk1">, </span><span class="mtk6">td</span><span class="mtk1">, </span><span class="mtk6">th</span><span class="mtk1"> {</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">text-align</span><span class="mtk1">: </span><span class="mtk8">left</span><span class="mtk1">;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1">}</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk17">&lt;/</span><span class="mtk4">style</span><span class="mtk17">&gt;</span></span></span></code></pre> <p>Now when you run the project <code>npm run serve</code>, you should have a simple data table displayed on the screen:</p> <p><span class="gatsby-resp-image-wrapper" style="position: relative; display: block; margin-left: auto; margin-right: auto; max-width: 720px; " > <a class="gatsby-resp-image-link" href="/static/556af2de0282a7fcdea110091ed9f953/2bef9/image-3-1024x219.png" style="display: block" target="_blank" rel="noopener" > <span class="gatsby-resp-image-background-image" style="padding-bottom: 21.111111111111114%; position: relative; bottom: 0; left: 0; background-image: url('data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABQAAAAECAIAAAABPYjBAAAACXBIWXMAAAsTAAALEwEAmpwYAAAAeklEQVR42lWOWw7FIAhE3f9K1T7uR4sKKN5pTUydkAk5wojbtv0mqrWJKLwU9t6nlNGrVhQaogTSml3XHULEzHh15/kT1d67mcFFJMQIH2TCQYhoP46GmFcu52wf4SMWsVX1FZaZGVdM7mQdRSriMLouN9RzgmopZfI/cIfq9YhwdCIAAAAASUVORK5CYII='); background-size: cover; display: block;" ></span> <img class="gatsby-resp-image-image" alt="image 3 1024x219" title="" src="/static/556af2de0282a7fcdea110091ed9f953/37523/image-3-1024x219.png" srcset="/static/556af2de0282a7fcdea110091ed9f953/e9ff0/image-3-1024x219.png 180w, /static/556af2de0282a7fcdea110091ed9f953/f21e7/image-3-1024x219.png 360w, /static/556af2de0282a7fcdea110091ed9f953/37523/image-3-1024x219.png 720w, /static/556af2de0282a7fcdea110091ed9f953/2bef9/image-3-1024x219.png 1024w" sizes="(max-width: 720px) 100vw, 720px" style="width:100%;height:100%;margin:0;vertical-align:middle;position:absolute;top:0;left:0;" loading="lazy" decoding="async" /> </a> </span></p> <h2 id="custom-cells" style="position:relative;"><a href="#custom-cells" aria-label="custom cells permalink" class="anchor before"><svg aria-hidden="true" focusable="false" height="16" version="1.1" viewBox="0 0 16 16" width="16"><path fill-rule="evenodd" d="M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z"></path></svg></a>Custom cells</h2> <p>VTable provides the option to replace any default field with our own custom component. They provide a slot name that looks and behaves like a function <code>cell(key)</code>, this way we can pass the field <code>key</code> as an argument and VTable will know what cells to change.</p> <p>Below, we are replacing every default cell with an input element (text, number, date, and select):</p> <pre class="grvsc-container default-dark" data-language="html" data-index="4"><code class="grvsc-code"><span class="grvsc-line"><span class="grvsc-source"><span class="mtk17">&lt;</span><span class="mtk4">template</span><span class="mtk17">&gt;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk17">&lt;</span><span class="mtk4">div</span><span class="mtk1"> </span><span class="mtk12">id</span><span class="mtk1">=</span><span class="mtk8">&quot;app&quot;</span><span class="mtk17">&gt;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk17">&lt;</span><span class="mtk4">b-table</span><span class="mtk1"> </span><span class="mtk12">:items</span><span class="mtk1">=</span><span class="mtk8">&quot;items&quot;</span><span class="mtk1"> </span><span class="mtk12">:fields</span><span class="mtk1">=</span><span class="mtk8">&quot;fields&quot;</span><span class="mtk17">&gt;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk17">&lt;</span><span class="mtk4">template</span><span class="mtk1"> </span><span class="mtk12">#cell(name)</span><span class="mtk1">=</span><span class="mtk8">&quot;data&quot;</span><span class="mtk17">&gt;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk17">&lt;</span><span class="mtk4">b-form-input</span><span class="mtk1"> </span><span class="mtk12">type</span><span class="mtk1">=</span><span class="mtk8">&quot;text&quot;</span><span class="mtk1"> </span><span class="mtk12">:value</span><span class="mtk1">=</span><span class="mtk8">&quot;data.value&quot;</span><span class="mtk17">&gt;&lt;/</span><span class="mtk4">b-form-input</span><span class="mtk17">&gt;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk17">&lt;/</span><span class="mtk4">template</span><span class="mtk17">&gt;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk17">&lt;</span><span class="mtk4">template</span><span class="mtk1"> </span><span class="mtk12">#cell(department)</span><span class="mtk1">=</span><span class="mtk8">&quot;data&quot;</span><span class="mtk17">&gt;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk17">&lt;</span><span class="mtk4">b-form-select</span><span class="mtk1"> </span><span class="mtk12">v-model</span><span class="mtk1">=</span><span class="mtk8">&quot;data.value&quot;</span><span class="mtk1"> </span><span class="mtk12">:options</span><span class="mtk1">=</span><span class="mtk8">&quot;[&#39;Development&#39;, &#39;Marketing&#39;, &#39;HR&#39;, &#39;Accounting&#39;]&quot;</span><span class="mtk1"> </span><span class="mtk12">class</span><span class="mtk1">=</span><span class="mtk8">&quot;form-control&quot;</span><span class="mtk17">&gt;&lt;/</span><span class="mtk4">b-form-select</span><span class="mtk17">&gt;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk17">&lt;/</span><span class="mtk4">template</span><span class="mtk17">&gt;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk17">&lt;</span><span class="mtk4">template</span><span class="mtk1"> </span><span class="mtk12">#cell(age)</span><span class="mtk1">=</span><span class="mtk8">&quot;data&quot;</span><span class="mtk17">&gt;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk17">&lt;</span><span class="mtk4">b-form-input</span><span class="mtk1"> </span><span class="mtk12">type</span><span class="mtk1">=</span><span class="mtk8">&quot;number&quot;</span><span class="mtk1"> </span><span class="mtk12">:value</span><span class="mtk1">=</span><span class="mtk8">&quot;data.value&quot;</span><span class="mtk17">&gt;&lt;/</span><span class="mtk4">b-form-input</span><span class="mtk17">&gt;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk17">&lt;/</span><span class="mtk4">template</span><span class="mtk17">&gt;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk17">&lt;</span><span class="mtk4">template</span><span class="mtk1"> </span><span class="mtk12">#cell(dateOfBirth)</span><span class="mtk1">=</span><span class="mtk8">&quot;data&quot;</span><span class="mtk17">&gt;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk17">&lt;</span><span class="mtk4">b-form-datepicker</span><span class="mtk1"> </span><span class="mtk12">v-model</span><span class="mtk1">=</span><span class="mtk8">&quot;data.value&quot;</span><span class="mtk17">&gt;&lt;/</span><span class="mtk4">b-form-datepicker</span><span class="mtk17">&gt;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk17">&lt;/</span><span class="mtk4">template</span><span class="mtk17">&gt;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk17">&lt;/</span><span class="mtk4">b-table</span><span class="mtk17">&gt;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk17">&lt;/</span><span class="mtk4">div</span><span class="mtk17">&gt;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk17">&lt;/</span><span class="mtk4">template</span><span class="mtk17">&gt;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk17">&lt;</span><span class="mtk4">script</span><span class="mtk17">&gt;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk15">export</span><span class="mtk1"> </span><span class="mtk15">default</span><span class="mtk1"> {</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">name:</span><span class="mtk1"> </span><span class="mtk8">&quot;App&quot;</span><span class="mtk1">,</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">components:</span><span class="mtk1"> {},</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk11">data</span><span class="mtk1">() {</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk15">return</span><span class="mtk1"> {</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">fields:</span><span class="mtk1"> [</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> { </span><span class="mtk12">key:</span><span class="mtk1"> </span><span class="mtk8">&quot;name&quot;</span><span class="mtk1">, </span><span class="mtk12">label:</span><span class="mtk1"> </span><span class="mtk8">&quot;Name&quot;</span><span class="mtk1">},</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> { </span><span class="mtk12">key:</span><span class="mtk1"> </span><span class="mtk8">&quot;department&quot;</span><span class="mtk1">, </span><span class="mtk12">label:</span><span class="mtk1"> </span><span class="mtk8">&quot;Department&quot;</span><span class="mtk1"> },</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> { </span><span class="mtk12">key:</span><span class="mtk1"> </span><span class="mtk8">&quot;age&quot;</span><span class="mtk1">, </span><span class="mtk12">label:</span><span class="mtk1"> </span><span class="mtk8">&quot;Age&quot;</span><span class="mtk1"> },</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> { </span><span class="mtk12">key:</span><span class="mtk1"> </span><span class="mtk8">&quot;dateOfBirth&quot;</span><span class="mtk1">, </span><span class="mtk12">label:</span><span class="mtk1"> </span><span class="mtk8">&quot;Date Of Birth&quot;</span><span class="mtk1"> },</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> ],</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">items:</span><span class="mtk1"> [</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> { </span><span class="mtk12">age:</span><span class="mtk1"> </span><span class="mtk7">40</span><span class="mtk1">, </span><span class="mtk12">name:</span><span class="mtk1"> </span><span class="mtk8">&#39;Dickerson&#39;</span><span class="mtk1">, </span><span class="mtk12">department:</span><span class="mtk1"> </span><span class="mtk8">&#39;Development&#39;</span><span class="mtk1">, </span><span class="mtk12">dateOfBirth:</span><span class="mtk1"> </span><span class="mtk8">&#39;1984-05-20&#39;</span><span class="mtk1"> },</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> { </span><span class="mtk12">age:</span><span class="mtk1"> </span><span class="mtk7">21</span><span class="mtk1">, </span><span class="mtk12">name:</span><span class="mtk1"> </span><span class="mtk8">&#39;Larsen&#39;</span><span class="mtk1">, </span><span class="mtk12">department:</span><span class="mtk1"> </span><span class="mtk8">&#39;Marketing&#39;</span><span class="mtk1">, </span><span class="mtk12">dateOfBirth:</span><span class="mtk1"> </span><span class="mtk8">&#39;1984-05-20&#39;</span><span class="mtk1"> },</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> { </span><span class="mtk12">age:</span><span class="mtk1"> </span><span class="mtk7">89</span><span class="mtk1">, </span><span class="mtk12">name:</span><span class="mtk1"> </span><span class="mtk8">&#39;Geneva&#39;</span><span class="mtk1">, </span><span class="mtk12">department:</span><span class="mtk1"> </span><span class="mtk8">&#39;HR&#39;</span><span class="mtk1">, </span><span class="mtk12">dateOfBirth:</span><span class="mtk1"> </span><span class="mtk8">&#39;1984-05-20&#39;</span><span class="mtk1"> },</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> { </span><span class="mtk12">age:</span><span class="mtk1"> </span><span class="mtk7">38</span><span class="mtk1">, </span><span class="mtk12">name:</span><span class="mtk1"> </span><span class="mtk8">&#39;Jami&#39;</span><span class="mtk1">, </span><span class="mtk12">department:</span><span class="mtk1"> </span><span class="mtk8">&#39;Accounting&#39;</span><span class="mtk1">, </span><span class="mtk12">dateOfBirth:</span><span class="mtk1"> </span><span class="mtk8">&#39;1984-05-20&#39;</span><span class="mtk1"> }</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> ],</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> };</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> },</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1">};</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk17">&lt;/</span><span class="mtk4">script</span><span class="mtk17">&gt;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk17">&lt;</span><span class="mtk4">style</span><span class="mtk17">&gt;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk6">#app</span><span class="mtk1"> {</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">text-align</span><span class="mtk1">: </span><span class="mtk8">center</span><span class="mtk1">;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">margin-top</span><span class="mtk1">: </span><span class="mtk7">60px</span><span class="mtk1">;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1">}</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk6">thead</span><span class="mtk1">, </span><span class="mtk6">tbody</span><span class="mtk1">, </span><span class="mtk6">tfoot</span><span class="mtk1">, </span><span class="mtk6">tr</span><span class="mtk1">, </span><span class="mtk6">td</span><span class="mtk1">, </span><span class="mtk6">th</span><span class="mtk1"> {</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">text-align</span><span class="mtk1">: </span><span class="mtk8">left</span><span class="mtk1">;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1">}</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk17">&lt;/</span><span class="mtk4">style</span><span class="mtk17">&gt;</span></span></span></code></pre> <p>The slot returns <code>data</code> that contains the current row information (index, field, value…). For now, we are using <code>data.value</code> to bind data to the input fields.</p> <p>When refreshing the page, we should see all default cells replaced with input fields:</p> <p><span class="gatsby-resp-image-wrapper" style="position: relative; display: block; margin-left: auto; margin-right: auto; max-width: 720px; " > <a class="gatsby-resp-image-link" href="/static/fada4e9aead3e4c95d93df0f68702ff2/2bef9/image-4-1024x222.png" style="display: block" target="_blank" rel="noopener" > <span class="gatsby-resp-image-background-image" style="padding-bottom: 21.666666666666668%; position: relative; bottom: 0; left: 0; background-image: url('data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABQAAAAECAIAAAABPYjBAAAACXBIWXMAAAsTAAALEwEAmpwYAAAAe0lEQVR42k2PWw4FIQhD3f9e5+ITHAVyqyZmTviotEAMMaUxxtyoas75eX4Q0ntjhrgWUSSiGwahlIqXbdydmSlGaHjI2QckMZ9SnmO6m6oFFllrzU6NzR5WiNtH1ca5YMM6pmf4fd9z8wBDpEPoPu4fRKTW1tr6y+n8AUv76jFdEogeAAAAAElFTkSuQmCC'); background-size: cover; display: block;" ></span> <img class="gatsby-resp-image-image" alt="image 4 1024x222" title="" src="/static/fada4e9aead3e4c95d93df0f68702ff2/37523/image-4-1024x222.png" srcset="/static/fada4e9aead3e4c95d93df0f68702ff2/e9ff0/image-4-1024x222.png 180w, /static/fada4e9aead3e4c95d93df0f68702ff2/f21e7/image-4-1024x222.png 360w, /static/fada4e9aead3e4c95d93df0f68702ff2/37523/image-4-1024x222.png 720w, /static/fada4e9aead3e4c95d93df0f68702ff2/2bef9/image-4-1024x222.png 1024w" sizes="(max-width: 720px) 100vw, 720px" style="width:100%;height:100%;margin:0;vertical-align:middle;position:absolute;top:0;left:0;" loading="lazy" decoding="async" /> </a> </span></p> <h2 id="inline-row-editing" style="position:relative;"><a href="#inline-row-editing" aria-label="inline row editing permalink" class="anchor before"><svg aria-hidden="true" focusable="false" height="16" version="1.1" viewBox="0 0 16 16" width="16"><path fill-rule="evenodd" d="M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z"></path></svg></a>Inline row editing</h2> <p>So far, we were able to display data with customized cells and input fields, awesome job! In this step, we will make the row editable on demand. Upon clicking the edit button, the row will toggle between read-only and edit mode.</p> <p>Let’s go through the required steps:</p> <ul> <li>Add a new “edit” object to the <code>fields</code> array, it will have an empty <code>label</code> as we don’t require a header name for the edit column.</li> <li>Re-generate the <code>items</code> model to include a new <code>isEdit</code> property for every row. This will determine whether or not a row is in edit mode.</li> <li>Every slot will have an <code>if else</code> block that toggles between read-only and edit mode.</li> <li>Add a new edit button slot with a click event that will modify the <code>isEdit</code>. Also, it will toggle between “Edit” and “Done” label.</li> <li>Finally, <code>:value</code> has to be replaced with a <code>v-model</code> for two-way binding. It will modify the <code>items</code> object directly (e.g. <code>v-model=items[data.index].name</code>).</li> </ul> <p>Below is the full code with a working example:</p> <pre class="grvsc-container default-dark" data-language="html" data-index="5"><code class="grvsc-code"><span class="grvsc-line"><span class="grvsc-source"><span class="mtk17">&lt;</span><span class="mtk4">template</span><span class="mtk17">&gt;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk17">&lt;</span><span class="mtk4">div</span><span class="mtk1"> </span><span class="mtk12">id</span><span class="mtk1">=</span><span class="mtk8">&quot;app&quot;</span><span class="mtk17">&gt;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk17">&lt;</span><span class="mtk4">b-table</span><span class="mtk1"> </span><span class="mtk12">:items</span><span class="mtk1">=</span><span class="mtk8">&quot;items&quot;</span><span class="mtk1"> </span><span class="mtk12">:fields</span><span class="mtk1">=</span><span class="mtk8">&quot;fields&quot;</span><span class="mtk17">&gt;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk17">&lt;</span><span class="mtk4">template</span><span class="mtk1"> </span><span class="mtk12">#cell(name)</span><span class="mtk1">=</span><span class="mtk8">&quot;data&quot;</span><span class="mtk17">&gt;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk17">&lt;</span><span class="mtk4">b-form-input</span><span class="mtk1"> </span><span class="mtk12">v-if</span><span class="mtk1">=</span><span class="mtk8">&quot;items[data.index].isEdit&quot;</span><span class="mtk1"> </span><span class="mtk12">type</span><span class="mtk1">=</span><span class="mtk8">&quot;text&quot;</span><span class="mtk1"> </span><span class="mtk12">v-model</span><span class="mtk1">=</span><span class="mtk8">&quot;items[data.index].name&quot;</span><span class="mtk17">&gt;&lt;/</span><span class="mtk4">b-form-input</span><span class="mtk17">&gt;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk17">&lt;</span><span class="mtk4">span</span><span class="mtk1"> </span><span class="mtk12">v-else</span><span class="mtk17">&gt;</span><span class="mtk1">{{data.value}}</span><span class="mtk17">&lt;/</span><span class="mtk4">span</span><span class="mtk17">&gt;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk17">&lt;/</span><span class="mtk4">template</span><span class="mtk17">&gt;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk17">&lt;</span><span class="mtk4">template</span><span class="mtk1"> </span><span class="mtk12">#cell(department)</span><span class="mtk1">=</span><span class="mtk8">&quot;data&quot;</span><span class="mtk17">&gt;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk17">&lt;</span><span class="mtk4">b-form-select</span><span class="mtk1"> </span><span class="mtk12">v-if</span><span class="mtk1">=</span><span class="mtk8">&quot;items[data.index].isEdit&quot;</span><span class="mtk1"> </span><span class="mtk12">v-model</span><span class="mtk1">=</span><span class="mtk8">&quot;items[data.index].department&quot;</span><span class="mtk1"> </span><span class="mtk12">:options</span><span class="mtk1">=</span><span class="mtk8">&quot;[&#39;Development&#39;, &#39;Marketing&#39;, &#39;HR&#39;, &#39;Accounting&#39;]&quot;</span><span class="mtk17">&gt;&lt;/</span><span class="mtk4">b-form-select</span><span class="mtk17">&gt;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk17">&lt;</span><span class="mtk4">span</span><span class="mtk1"> </span><span class="mtk12">v-else</span><span class="mtk17">&gt;</span><span class="mtk1">{{data.value}}</span><span class="mtk17">&lt;/</span><span class="mtk4">span</span><span class="mtk17">&gt;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk17">&lt;/</span><span class="mtk4">template</span><span class="mtk17">&gt;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk17">&lt;</span><span class="mtk4">template</span><span class="mtk1"> </span><span class="mtk12">#cell(age)</span><span class="mtk1">=</span><span class="mtk8">&quot;data&quot;</span><span class="mtk17">&gt;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk17">&lt;</span><span class="mtk4">b-form-input</span><span class="mtk1"> </span><span class="mtk12">v-if</span><span class="mtk1">=</span><span class="mtk8">&quot;items[data.index].isEdit&quot;</span><span class="mtk1"> </span><span class="mtk12">type</span><span class="mtk1">=</span><span class="mtk8">&quot;number&quot;</span><span class="mtk1"> </span><span class="mtk12">v-model</span><span class="mtk1">=</span><span class="mtk8">&quot;items[data.index].age&quot;</span><span class="mtk17">&gt;&lt;/</span><span class="mtk4">b-form-input</span><span class="mtk17">&gt;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk17">&lt;</span><span class="mtk4">span</span><span class="mtk1"> </span><span class="mtk12">v-else</span><span class="mtk17">&gt;</span><span class="mtk1">{{data.value}}</span><span class="mtk17">&lt;/</span><span class="mtk4">span</span><span class="mtk17">&gt;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk17">&lt;/</span><span class="mtk4">template</span><span class="mtk17">&gt;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk17">&lt;</span><span class="mtk4">template</span><span class="mtk1"> </span><span class="mtk12">#cell(dateOfBirth)</span><span class="mtk1">=</span><span class="mtk8">&quot;data&quot;</span><span class="mtk17">&gt;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk17">&lt;</span><span class="mtk4">b-form-datepicker</span><span class="mtk1"> </span><span class="mtk12">v-if</span><span class="mtk1">=</span><span class="mtk8">&quot;items[data.index].isEdit&quot;</span><span class="mtk1"> </span><span class="mtk12">v-model</span><span class="mtk1">=</span><span class="mtk8">&quot;items[data.index].dateOfBirth&quot;</span><span class="mtk17">&gt;&lt;/</span><span class="mtk4">b-form-datepicker</span><span class="mtk17">&gt;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk17">&lt;</span><span class="mtk4">span</span><span class="mtk1"> </span><span class="mtk12">v-else</span><span class="mtk17">&gt;</span><span class="mtk1">{{data.value}}</span><span class="mtk17">&lt;/</span><span class="mtk4">span</span><span class="mtk17">&gt;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk17">&lt;/</span><span class="mtk4">template</span><span class="mtk17">&gt;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk17">&lt;</span><span class="mtk4">template</span><span class="mtk1"> </span><span class="mtk12">#cell(edit)</span><span class="mtk1">=</span><span class="mtk8">&quot;data&quot;</span><span class="mtk17">&gt;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk17">&lt;</span><span class="mtk4">b-button</span><span class="mtk1"> </span><span class="mtk12">@click</span><span class="mtk1">=</span><span class="mtk8">&quot;editRowHandler(data)&quot;</span><span class="mtk17">&gt;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk17">&lt;</span><span class="mtk4">span</span><span class="mtk1"> </span><span class="mtk12">v-if</span><span class="mtk1">=</span><span class="mtk8">&quot;!items[data.index].isEdit&quot;</span><span class="mtk17">&gt;</span><span class="mtk1">Edit</span><span class="mtk17">&lt;/</span><span class="mtk4">span</span><span class="mtk17">&gt;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk17">&lt;</span><span class="mtk4">span</span><span class="mtk1"> </span><span class="mtk12">v-else</span><span class="mtk17">&gt;</span><span class="mtk1">Done</span><span class="mtk17">&lt;/</span><span class="mtk4">span</span><span class="mtk17">&gt;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk17">&lt;/</span><span class="mtk4">b-button</span><span class="mtk17">&gt;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk17">&lt;/</span><span class="mtk4">template</span><span class="mtk17">&gt;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk17">&lt;/</span><span class="mtk4">b-table</span><span class="mtk17">&gt;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk17">&lt;</span><span class="mtk4">pre</span><span class="mtk17">&gt;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> {{items}}</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk17">&lt;/</span><span class="mtk4">pre</span><span class="mtk17">&gt;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk17">&lt;/</span><span class="mtk4">div</span><span class="mtk17">&gt;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk17">&lt;/</span><span class="mtk4">template</span><span class="mtk17">&gt;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk17">&lt;</span><span class="mtk4">script</span><span class="mtk17">&gt;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk15">export</span><span class="mtk1"> </span><span class="mtk15">default</span><span class="mtk1"> {</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">name:</span><span class="mtk1"> </span><span class="mtk8">&quot;App&quot;</span><span class="mtk1">,</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">components:</span><span class="mtk1"> {},</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk11">data</span><span class="mtk1">() {</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk15">return</span><span class="mtk1"> {</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">fields:</span><span class="mtk1"> [</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> { </span><span class="mtk12">key:</span><span class="mtk1"> </span><span class="mtk8">&quot;name&quot;</span><span class="mtk1">, </span><span class="mtk12">label:</span><span class="mtk1"> </span><span class="mtk8">&quot;Name&quot;</span><span class="mtk1">},</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> { </span><span class="mtk12">key:</span><span class="mtk1"> </span><span class="mtk8">&quot;department&quot;</span><span class="mtk1">, </span><span class="mtk12">label:</span><span class="mtk1"> </span><span class="mtk8">&quot;Department&quot;</span><span class="mtk1"> },</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> { </span><span class="mtk12">key:</span><span class="mtk1"> </span><span class="mtk8">&quot;age&quot;</span><span class="mtk1">, </span><span class="mtk12">label:</span><span class="mtk1"> </span><span class="mtk8">&quot;Age&quot;</span><span class="mtk1"> },</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> { </span><span class="mtk12">key:</span><span class="mtk1"> </span><span class="mtk8">&quot;dateOfBirth&quot;</span><span class="mtk1">, </span><span class="mtk12">label:</span><span class="mtk1"> </span><span class="mtk8">&quot;Date Of Birth&quot;</span><span class="mtk1"> },</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> { </span><span class="mtk12">key:</span><span class="mtk1"> </span><span class="mtk8">&#39;edit&#39;</span><span class="mtk1">, </span><span class="mtk12">label:</span><span class="mtk1"> </span><span class="mtk8">&#39;&#39;</span><span class="mtk1">}</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> ],</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">items:</span><span class="mtk1"> [</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> { </span><span class="mtk12">age:</span><span class="mtk1"> </span><span class="mtk7">40</span><span class="mtk1">, </span><span class="mtk12">name:</span><span class="mtk1"> </span><span class="mtk8">&#39;Dickerson&#39;</span><span class="mtk1">, </span><span class="mtk12">department:</span><span class="mtk1"> </span><span class="mtk8">&#39;Development&#39;</span><span class="mtk1">, </span><span class="mtk12">dateOfBirth:</span><span class="mtk1"> </span><span class="mtk8">&#39;1984-05-20&#39;</span><span class="mtk1"> },</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> { </span><span class="mtk12">age:</span><span class="mtk1"> </span><span class="mtk7">21</span><span class="mtk1">, </span><span class="mtk12">name:</span><span class="mtk1"> </span><span class="mtk8">&#39;Larsen&#39;</span><span class="mtk1">, </span><span class="mtk12">department:</span><span class="mtk1"> </span><span class="mtk8">&#39;Marketing&#39;</span><span class="mtk1">, </span><span class="mtk12">dateOfBirth:</span><span class="mtk1"> </span><span class="mtk8">&#39;1984-05-20&#39;</span><span class="mtk1"> },</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> { </span><span class="mtk12">age:</span><span class="mtk1"> </span><span class="mtk7">89</span><span class="mtk1">, </span><span class="mtk12">name:</span><span class="mtk1"> </span><span class="mtk8">&#39;Geneva&#39;</span><span class="mtk1">, </span><span class="mtk12">department:</span><span class="mtk1"> </span><span class="mtk8">&#39;HR&#39;</span><span class="mtk1">, </span><span class="mtk12">dateOfBirth:</span><span class="mtk1"> </span><span class="mtk8">&#39;1984-05-20&#39;</span><span class="mtk1"> },</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> { </span><span class="mtk12">age:</span><span class="mtk1"> </span><span class="mtk7">38</span><span class="mtk1">, </span><span class="mtk12">name:</span><span class="mtk1"> </span><span class="mtk8">&#39;Jami&#39;</span><span class="mtk1">, </span><span class="mtk12">department:</span><span class="mtk1"> </span><span class="mtk8">&#39;Accounting&#39;</span><span class="mtk1">, </span><span class="mtk12">dateOfBirth:</span><span class="mtk1"> </span><span class="mtk8">&#39;1984-05-20&#39;</span><span class="mtk1"> }</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> ],</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> };</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> },</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk11">mounted</span><span class="mtk1">() {</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk4">this</span><span class="mtk1">.</span><span class="mtk12">items</span><span class="mtk1"> = </span><span class="mtk4">this</span><span class="mtk1">.</span><span class="mtk12">items</span><span class="mtk1">.</span><span class="mtk11">map</span><span class="mtk1">(</span><span class="mtk12">item</span><span class="mtk1"> </span><span class="mtk4">=&gt;</span><span class="mtk1"> ({...</span><span class="mtk12">item</span><span class="mtk1">, </span><span class="mtk12">isEdit:</span><span class="mtk1"> </span><span class="mtk4">false</span><span class="mtk1">}));</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> },</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">methods:</span><span class="mtk1"> {</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk11">editRowHandler</span><span class="mtk1">(</span><span class="mtk12">data</span><span class="mtk1">) {</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk4">this</span><span class="mtk1">.</span><span class="mtk12">items</span><span class="mtk1">[</span><span class="mtk12">data</span><span class="mtk1">.</span><span class="mtk12">index</span><span class="mtk1">].</span><span class="mtk12">isEdit</span><span class="mtk1"> = !</span><span class="mtk4">this</span><span class="mtk1">.</span><span class="mtk12">items</span><span class="mtk1">[</span><span class="mtk12">data</span><span class="mtk1">.</span><span class="mtk12">index</span><span class="mtk1">].</span><span class="mtk12">isEdit</span><span class="mtk1">;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> }</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> }</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> }</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk17">&lt;/</span><span class="mtk4">script</span><span class="mtk17">&gt;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk17">&lt;</span><span class="mtk4">style</span><span class="mtk17">&gt;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk6">#app</span><span class="mtk1"> {</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">text-align</span><span class="mtk1">: </span><span class="mtk8">center</span><span class="mtk1">;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">margin</span><span class="mtk1">: </span><span class="mtk7">60px</span><span class="mtk1">;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1">}</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk6">thead</span><span class="mtk1">, </span><span class="mtk6">tbody</span><span class="mtk1">, </span><span class="mtk6">tfoot</span><span class="mtk1">, </span><span class="mtk6">tr</span><span class="mtk1">, </span><span class="mtk6">td</span><span class="mtk1">, </span><span class="mtk6">th</span><span class="mtk1"> {</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">text-align</span><span class="mtk1">: </span><span class="mtk8">left</span><span class="mtk1">;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">width</span><span class="mtk1">: </span><span class="mtk7">100px</span><span class="mtk1">;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">vertical-align</span><span class="mtk1">: </span><span class="mtk8">middle</span><span class="mtk1">;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1">}</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk6">pre</span><span class="mtk1"> {</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">text-align</span><span class="mtk1">: </span><span class="mtk8">left</span><span class="mtk1">;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">color</span><span class="mtk1">: </span><span class="mtk8">#d63384</span><span class="mtk1">;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1">}</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk17">&lt;/</span><span class="mtk4">style</span><span class="mtk17">&gt;</span></span></span></code></pre> <div data-youtube="pdoWaGTUMeo"> <button>Play Example</button> </div> <h2 id="inline-cell-editing" style="position:relative;"><a href="#inline-cell-editing" aria-label="inline cell editing permalink" class="anchor before"><svg aria-hidden="true" focusable="false" height="16" version="1.1" viewBox="0 0 16 16" width="16"><path fill-rule="evenodd" d="M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z"></path></svg></a>Inline cell editing</h2> <p>An alternative approach to editing a row is to edit an individual cell. Here are the steps for supporting inline cell editing:</p> <ul> <li>Add a new string data called <code>selectedCell</code> to determine which cell is currently selected.</li> <li>Update the slot condition to check for both <code>isEdit</code> and the <code>selectedCell</code>. E.g. <code>v-if="items[data.index].isEdit &#x26;&#x26; selectedCell === 'name'"</code>.</li> <li>The click event should be added on the cell element instead of the edit button and the handler function will update both the <code>selectedCell</code> and <code>isEdit</code>. Also, we can now remove the edit button slot as it’s not required anymore.</li> </ul> <p>Below is the full code with a working example:</p> <pre class="grvsc-container default-dark" data-language="html" data-index="6"><code class="grvsc-code"><span class="grvsc-line"><span class="grvsc-source"><span class="mtk17">&lt;</span><span class="mtk4">template</span><span class="mtk17">&gt;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk17">&lt;</span><span class="mtk4">div</span><span class="mtk1"> </span><span class="mtk12">id</span><span class="mtk1">=</span><span class="mtk8">&quot;app&quot;</span><span class="mtk17">&gt;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk17">&lt;</span><span class="mtk4">b-table</span><span class="mtk1"> </span><span class="mtk12">:items</span><span class="mtk1">=</span><span class="mtk8">&quot;items&quot;</span><span class="mtk1"> </span><span class="mtk12">:fields</span><span class="mtk1">=</span><span class="mtk8">&quot;fields&quot;</span><span class="mtk17">&gt;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk17">&lt;</span><span class="mtk4">template</span><span class="mtk1"> </span><span class="mtk12">#cell(name)</span><span class="mtk1">=</span><span class="mtk8">&quot;data&quot;</span><span class="mtk17">&gt;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk17">&lt;</span><span class="mtk4">b-form-input</span><span class="mtk1"> </span><span class="mtk12">v-if</span><span class="mtk1">=</span><span class="mtk8">&quot;items[data.index].isEdit &amp;&amp; selectedCell === &#39;name&#39;&quot;</span><span class="mtk1"> </span><span class="mtk12">type</span><span class="mtk1">=</span><span class="mtk8">&quot;text&quot;</span><span class="mtk1"> </span><span class="mtk12">v-model</span><span class="mtk1">=</span><span class="mtk8">&quot;items[data.index].name&quot;</span><span class="mtk17">&gt;&lt;/</span><span class="mtk4">b-form-input</span><span class="mtk17">&gt;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk17">&lt;</span><span class="mtk4">span</span><span class="mtk1"> </span><span class="mtk12">v-else</span><span class="mtk1"> </span><span class="mtk12">@click</span><span class="mtk1">=</span><span class="mtk8">&quot;editCellHandler(data, &#39;name&#39;)&quot;</span><span class="mtk17">&gt;</span><span class="mtk1">{{data.value}}</span><span class="mtk17">&lt;/</span><span class="mtk4">span</span><span class="mtk17">&gt;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk17">&lt;/</span><span class="mtk4">template</span><span class="mtk17">&gt;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk17">&lt;</span><span class="mtk4">template</span><span class="mtk1"> </span><span class="mtk12">#cell(department)</span><span class="mtk1">=</span><span class="mtk8">&quot;data&quot;</span><span class="mtk17">&gt;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk17">&lt;</span><span class="mtk4">b-form-select</span><span class="mtk1"> </span><span class="mtk12">v-if</span><span class="mtk1">=</span><span class="mtk8">&quot;items[data.index].isEdit &amp;&amp; selectedCell === &#39;department&#39;&quot;</span><span class="mtk1"> </span><span class="mtk12">v-model</span><span class="mtk1">=</span><span class="mtk8">&quot;items[data.index].department&quot;</span><span class="mtk1"> </span><span class="mtk12">:options</span><span class="mtk1">=</span><span class="mtk8">&quot;[&#39;Development&#39;, &#39;Marketing&#39;, &#39;HR&#39;, &#39;Accounting&#39;]&quot;</span><span class="mtk1"> </span><span class="mtk12">class</span><span class="mtk1">=</span><span class="mtk8">&quot;form-control&quot;</span><span class="mtk17">&gt;&lt;/</span><span class="mtk4">b-form-select</span><span class="mtk17">&gt;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk17">&lt;</span><span class="mtk4">span</span><span class="mtk1"> </span><span class="mtk12">v-else</span><span class="mtk1"> </span><span class="mtk12">@click</span><span class="mtk1">=</span><span class="mtk8">&quot;editCellHandler(data, &#39;department&#39;)&quot;</span><span class="mtk17">&gt;</span><span class="mtk1">{{data.value}}</span><span class="mtk17">&lt;/</span><span class="mtk4">span</span><span class="mtk17">&gt;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk17">&lt;/</span><span class="mtk4">template</span><span class="mtk17">&gt;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk17">&lt;</span><span class="mtk4">template</span><span class="mtk1"> </span><span class="mtk12">#cell(age)</span><span class="mtk1">=</span><span class="mtk8">&quot;data&quot;</span><span class="mtk17">&gt;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk17">&lt;</span><span class="mtk4">b-form-input</span><span class="mtk1"> </span><span class="mtk12">v-if</span><span class="mtk1">=</span><span class="mtk8">&quot;items[data.index].isEdit &amp;&amp; selectedCell === &#39;age&#39;&quot;</span><span class="mtk1"> </span><span class="mtk12">type</span><span class="mtk1">=</span><span class="mtk8">&quot;number&quot;</span><span class="mtk1"> </span><span class="mtk12">v-model</span><span class="mtk1">=</span><span class="mtk8">&quot;items[data.index].age&quot;</span><span class="mtk17">&gt;&lt;/</span><span class="mtk4">b-form-input</span><span class="mtk17">&gt;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk17">&lt;</span><span class="mtk4">span</span><span class="mtk1"> </span><span class="mtk12">v-else</span><span class="mtk1"> </span><span class="mtk12">@click</span><span class="mtk1">=</span><span class="mtk8">&quot;editCellHandler(data, &#39;age&#39;)&quot;</span><span class="mtk17">&gt;</span><span class="mtk1">{{data.value}}</span><span class="mtk17">&lt;/</span><span class="mtk4">span</span><span class="mtk17">&gt;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk17">&lt;/</span><span class="mtk4">template</span><span class="mtk17">&gt;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk17">&lt;</span><span class="mtk4">template</span><span class="mtk1"> </span><span class="mtk12">#cell(dateOfBirth)</span><span class="mtk1">=</span><span class="mtk8">&quot;data&quot;</span><span class="mtk17">&gt;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk17">&lt;</span><span class="mtk4">b-form-datepicker</span><span class="mtk1"> </span><span class="mtk12">v-if</span><span class="mtk1">=</span><span class="mtk8">&quot;items[data.index].isEdit &amp;&amp; selectedCell === &#39;dateOfBirth&#39;&quot;</span><span class="mtk1"> </span><span class="mtk12">v-model</span><span class="mtk1">=</span><span class="mtk8">&quot;items[data.index].dateOfBirth&quot;</span><span class="mtk17">&gt;&lt;/</span><span class="mtk4">b-form-datepicker</span><span class="mtk17">&gt;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk17">&lt;</span><span class="mtk4">span</span><span class="mtk1"> </span><span class="mtk12">v-else</span><span class="mtk1"> </span><span class="mtk12">@click</span><span class="mtk1">=</span><span class="mtk8">&quot;editCellHandler(data, &#39;dateOfBirth&#39;)&quot;</span><span class="mtk17">&gt;</span><span class="mtk1">{{data.value}}</span><span class="mtk17">&lt;/</span><span class="mtk4">span</span><span class="mtk17">&gt;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk17">&lt;/</span><span class="mtk4">template</span><span class="mtk17">&gt;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk17">&lt;/</span><span class="mtk4">b-table</span><span class="mtk17">&gt;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk17">&lt;</span><span class="mtk4">pre</span><span class="mtk17">&gt;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> {{items}}</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk17">&lt;/</span><span class="mtk4">pre</span><span class="mtk17">&gt;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk17">&lt;/</span><span class="mtk4">div</span><span class="mtk17">&gt;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk17">&lt;/</span><span class="mtk4">template</span><span class="mtk17">&gt;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk17">&lt;</span><span class="mtk4">script</span><span class="mtk17">&gt;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk15">export</span><span class="mtk1"> </span><span class="mtk15">default</span><span class="mtk1"> {</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">name:</span><span class="mtk1"> </span><span class="mtk8">&quot;App&quot;</span><span class="mtk1">,</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">components:</span><span class="mtk1"> {},</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk11">data</span><span class="mtk1">() {</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk15">return</span><span class="mtk1"> {</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">fields:</span><span class="mtk1"> [</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> { </span><span class="mtk12">key:</span><span class="mtk1"> </span><span class="mtk8">&quot;name&quot;</span><span class="mtk1">, </span><span class="mtk12">label:</span><span class="mtk1"> </span><span class="mtk8">&quot;Name&quot;</span><span class="mtk1">},</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> { </span><span class="mtk12">key:</span><span class="mtk1"> </span><span class="mtk8">&quot;department&quot;</span><span class="mtk1">, </span><span class="mtk12">label:</span><span class="mtk1"> </span><span class="mtk8">&quot;Department&quot;</span><span class="mtk1"> },</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> { </span><span class="mtk12">key:</span><span class="mtk1"> </span><span class="mtk8">&quot;age&quot;</span><span class="mtk1">, </span><span class="mtk12">label:</span><span class="mtk1"> </span><span class="mtk8">&quot;Age&quot;</span><span class="mtk1"> },</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> { </span><span class="mtk12">key:</span><span class="mtk1"> </span><span class="mtk8">&quot;dateOfBirth&quot;</span><span class="mtk1">, </span><span class="mtk12">label:</span><span class="mtk1"> </span><span class="mtk8">&quot;Date Of Birth&quot;</span><span class="mtk1"> },</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> { </span><span class="mtk12">key:</span><span class="mtk1"> </span><span class="mtk8">&#39;edit&#39;</span><span class="mtk1">, </span><span class="mtk12">label:</span><span class="mtk1"> </span><span class="mtk8">&#39;&#39;</span><span class="mtk1">}</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> ],</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">items:</span><span class="mtk1"> [</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> { </span><span class="mtk12">age:</span><span class="mtk1"> </span><span class="mtk7">40</span><span class="mtk1">, </span><span class="mtk12">name:</span><span class="mtk1"> </span><span class="mtk8">&#39;Dickerson&#39;</span><span class="mtk1">, </span><span class="mtk12">department:</span><span class="mtk1"> </span><span class="mtk8">&#39;Development&#39;</span><span class="mtk1">, </span><span class="mtk12">dateOfBirth:</span><span class="mtk1"> </span><span class="mtk8">&#39;1984-05-20&#39;</span><span class="mtk1"> },</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> { </span><span class="mtk12">age:</span><span class="mtk1"> </span><span class="mtk7">21</span><span class="mtk1">, </span><span class="mtk12">name:</span><span class="mtk1"> </span><span class="mtk8">&#39;Larsen&#39;</span><span class="mtk1">, </span><span class="mtk12">department:</span><span class="mtk1"> </span><span class="mtk8">&#39;Marketing&#39;</span><span class="mtk1">, </span><span class="mtk12">dateOfBirth:</span><span class="mtk1"> </span><span class="mtk8">&#39;1984-05-20&#39;</span><span class="mtk1"> },</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> { </span><span class="mtk12">age:</span><span class="mtk1"> </span><span class="mtk7">89</span><span class="mtk1">, </span><span class="mtk12">name:</span><span class="mtk1"> </span><span class="mtk8">&#39;Geneva&#39;</span><span class="mtk1">, </span><span class="mtk12">department:</span><span class="mtk1"> </span><span class="mtk8">&#39;HR&#39;</span><span class="mtk1">, </span><span class="mtk12">dateOfBirth:</span><span class="mtk1"> </span><span class="mtk8">&#39;1984-05-20&#39;</span><span class="mtk1"> },</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> { </span><span class="mtk12">age:</span><span class="mtk1"> </span><span class="mtk7">38</span><span class="mtk1">, </span><span class="mtk12">name:</span><span class="mtk1"> </span><span class="mtk8">&#39;Jami&#39;</span><span class="mtk1">, </span><span class="mtk12">department:</span><span class="mtk1"> </span><span class="mtk8">&#39;Accounting&#39;</span><span class="mtk1">, </span><span class="mtk12">dateOfBirth:</span><span class="mtk1"> </span><span class="mtk8">&#39;1984-05-20&#39;</span><span class="mtk1"> }</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> ],</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">selectedCell:</span><span class="mtk1"> </span><span class="mtk4">null</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> };</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> },</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk11">mounted</span><span class="mtk1">() {</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk4">this</span><span class="mtk1">.</span><span class="mtk12">items</span><span class="mtk1"> = </span><span class="mtk4">this</span><span class="mtk1">.</span><span class="mtk12">items</span><span class="mtk1">.</span><span class="mtk11">map</span><span class="mtk1">(</span><span class="mtk12">item</span><span class="mtk1"> </span><span class="mtk4">=&gt;</span><span class="mtk1"> ({...</span><span class="mtk12">item</span><span class="mtk1">, </span><span class="mtk12">isEdit:</span><span class="mtk1"> </span><span class="mtk4">false</span><span class="mtk1">}));</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> },</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">methods:</span><span class="mtk1"> {</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk11">editCellHandler</span><span class="mtk1">(</span><span class="mtk12">data</span><span class="mtk1">, </span><span class="mtk12">name</span><span class="mtk1">) {</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk4">this</span><span class="mtk1">.</span><span class="mtk12">items</span><span class="mtk1"> = </span><span class="mtk4">this</span><span class="mtk1">.</span><span class="mtk12">items</span><span class="mtk1">.</span><span class="mtk11">map</span><span class="mtk1">(</span><span class="mtk12">item</span><span class="mtk1"> </span><span class="mtk4">=&gt;</span><span class="mtk1"> ({...</span><span class="mtk12">item</span><span class="mtk1">, </span><span class="mtk12">isEdit:</span><span class="mtk1"> </span><span class="mtk4">false</span><span class="mtk1">}));</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk4">this</span><span class="mtk1">.</span><span class="mtk12">items</span><span class="mtk1">[</span><span class="mtk12">data</span><span class="mtk1">.</span><span class="mtk12">index</span><span class="mtk1">].</span><span class="mtk12">isEdit</span><span class="mtk1"> = </span><span class="mtk4">true</span><span class="mtk1">;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk4">this</span><span class="mtk1">.</span><span class="mtk12">selectedCell</span><span class="mtk1"> = </span><span class="mtk12">name</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> }</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> }</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> }</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk17">&lt;/</span><span class="mtk4">script</span><span class="mtk17">&gt;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk17">&lt;</span><span class="mtk4">style</span><span class="mtk17">&gt;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk6">#app</span><span class="mtk1"> {</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">text-align</span><span class="mtk1">: </span><span class="mtk8">center</span><span class="mtk1">;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">margin</span><span class="mtk1">: </span><span class="mtk7">60px</span><span class="mtk1">;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1">}</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk6">thead</span><span class="mtk1">, </span><span class="mtk6">tbody</span><span class="mtk1">, </span><span class="mtk6">tfoot</span><span class="mtk1">, </span><span class="mtk6">tr</span><span class="mtk1">, </span><span class="mtk6">td</span><span class="mtk1">, </span><span class="mtk6">th</span><span class="mtk1"> {</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">text-align</span><span class="mtk1">: </span><span class="mtk8">left</span><span class="mtk1">;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">width</span><span class="mtk1">: </span><span class="mtk7">100px</span><span class="mtk1">;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">vertical-align</span><span class="mtk1">: </span><span class="mtk8">middle</span><span class="mtk1">;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1">}</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk6">pre</span><span class="mtk1"> {</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">text-align</span><span class="mtk1">: </span><span class="mtk8">left</span><span class="mtk1">;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">color</span><span class="mtk1">: </span><span class="mtk8">#d63384</span><span class="mtk1">;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1">}</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk17">&lt;/</span><span class="mtk4">style</span><span class="mtk17">&gt;</span></span></span></code></pre> <p>Notice, at the beginning of the function, we’re resetting <code>isEdit</code> to false for all rows to restrict editing one cell at a time.</p> <pre class="grvsc-container default-dark" data-language="javascript" data-index="7"><code class="grvsc-code"><span class="grvsc-line"><span class="grvsc-source"><span class="mtk4">this</span><span class="mtk1">.</span><span class="mtk12">items</span><span class="mtk1"> = </span><span class="mtk4">this</span><span class="mtk1">.</span><span class="mtk12">items</span><span class="mtk1">.</span><span class="mtk11">map</span><span class="mtk1">(</span><span class="mtk12">item</span><span class="mtk1"> </span><span class="mtk4">=&gt;</span><span class="mtk1"> ({...</span><span class="mtk12">item</span><span class="mtk1">, </span><span class="mtk12">isEdit:</span><span class="mtk1"> </span><span class="mtk4">false</span><span class="mtk1">}));</span></span></span></code></pre> <div data-youtube="5rzhFrzmEFo"> <button>Play Example</button> </div> <h2 id="summary" style="position:relative;"><a href="#summary" aria-label="summary permalink" class="anchor before"><svg aria-hidden="true" focusable="false" height="16" version="1.1" viewBox="0 0 16 16" width="16"><path fill-rule="evenodd" d="M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z"></path></svg></a>Summary</h2> <p>If you made it to this section, pat yourself on the back! You just learned how to:</p> <ul> <li>Setup a Vue and Bootstrap project</li> <li>Create a basic data table</li> <li>Enable inline row and cell editing</li> </ul> <p>You can access the <a href="https://github.com/muhimasri/vue-editable-table-example">complete repository here</a>.</p> <p>Bye for now 👋</p> <style class="grvsc-styles"> .grvsc-container { overflow: auto; position: relative; -webkit-overflow-scrolling: touch; padding-top: 1rem; padding-top: var(--grvsc-padding-top, var(--grvsc-padding-v, 1rem)); padding-bottom: 1rem; padding-bottom: var(--grvsc-padding-bottom, var(--grvsc-padding-v, 1rem)); border-radius: 8px; border-radius: var(--grvsc-border-radius, 8px); font-feature-settings: normal; line-height: 1.4; } .grvsc-code { display: table; } .grvsc-line { display: table-row; box-sizing: border-box; width: 100%; position: relative; } .grvsc-line > * { position: relative; } .grvsc-gutter-pad { display: table-cell; padding-left: 0.75rem; padding-left: calc(var(--grvsc-padding-left, var(--grvsc-padding-h, 1.5rem)) / 2); } .grvsc-gutter { display: table-cell; -webkit-user-select: none; -moz-user-select: none; user-select: none; } .grvsc-gutter::before { content: attr(data-content); } .grvsc-source { display: table-cell; padding-left: 1.5rem; padding-left: var(--grvsc-padding-left, var(--grvsc-padding-h, 1.5rem)); padding-right: 1.5rem; padding-right: var(--grvsc-padding-right, var(--grvsc-padding-h, 1.5rem)); } .grvsc-source:empty::after { content: ' '; -webkit-user-select: none; -moz-user-select: none; user-select: none; } .grvsc-gutter + .grvsc-source { padding-left: 0.75rem; padding-left: calc(var(--grvsc-padding-left, var(--grvsc-padding-h, 1.5rem)) / 2); } /* Line transformer styles */ .grvsc-has-line-highlighting > .grvsc-code > .grvsc-line::before { content: ' '; position: absolute; width: 100%; } .grvsc-line-diff-add::before { background-color: var(--grvsc-line-diff-add-background-color, rgba(0, 255, 60, 0.2)); } .grvsc-line-diff-del::before { background-color: var(--grvsc-line-diff-del-background-color, rgba(255, 0, 20, 0.2)); } .grvsc-line-number { padding: 0 2px; text-align: right; opacity: 0.7; } .default-dark { background-color: #1E1E1E; color: #D4D4D4; } .default-dark .mtk15 { color: #C586C0; } .default-dark .mtk1 { color: #D4D4D4; } .default-dark .mtk12 { color: #9CDCFE; } .default-dark .mtk8 { color: #CE9178; } .default-dark .mtk3 { color: #6A9955; } .default-dark .mtk11 { color: #DCDCAA; } .default-dark .mtk4 { color: #569CD6; } .default-dark .mtk10 { color: #4EC9B0; } .default-dark .mtk17 { color: #808080; } .default-dark .mtk7 { color: #B5CEA8; } .default-dark .mtk6 { color: #D7BA7D; } .default-dark .grvsc-line-highlighted::before { background-color: var(--grvsc-line-highlighted-background-color, rgba(255, 255, 255, 0.1)); box-shadow: inset var(--grvsc-line-highlighted-border-width, 4px) 0 0 0 var(--grvsc-line-highlighted-border-color, rgba(255, 255, 255, 0.5)); } </style><![CDATA[How to Create a Single File Component in Angular]]>https://muhimasri.comhow-to-create-a-single-file-component-in-angularhttps://muhimasri.comhow-to-create-a-single-file-component-in-angular<p>If you come from a Vue or React (styled component/JSS) background, a single file component is your “normal” definition of a component. I fully appreciate the separation of concern that Angular conveys to the world along with all the amazing features that it provides out of the box. But in some cases, especially when building a design system, components tend to be small and it might make more sense to encapsulate JS, HTML, and CSS in one single file representing a customized and composable UI element.</p> <p>In this article, I will walk you through few easy steps you need to make a single file component with Angular including intellisense and auto-generation configuration.</p> <h2 id="setup-angular-project" style="position:relative;"><a href="#setup-angular-project" aria-label="setup angular project permalink" class="anchor before"><svg aria-hidden="true" focusable="false" height="16" version="1.1" viewBox="0 0 16 16" width="16"><path fill-rule="evenodd" d="M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z"></path></svg></a>Setup Angular Project</h2> <p>Install <a href="https://angular.io/cli">Angular CLI</a> and create a new project</p> <pre class="grvsc-container default-dark" data-language="" data-index="0"><code class="grvsc-code"><span class="grvsc-line"><span class="grvsc-source">npm install -g @angular/cli</span></span> <span class="grvsc-line"><span class="grvsc-source">ng new angular-single-file-component</span></span></code></pre> <h2 id="add-angular-configuration" style="position:relative;"><a href="#add-angular-configuration" aria-label="add angular configuration permalink" class="anchor before"><svg aria-hidden="true" focusable="false" height="16" version="1.1" viewBox="0 0 16 16" width="16"><path fill-rule="evenodd" d="M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z"></path></svg></a>Add Angular Configuration</h2> <p>When running <code>ng g component</code>, Angular by default creates a folder with four files (ts, html, css, and spec). We need to add a new configuration to make it generate only ts and spec files.</p> <p>In <code>angular.json</code> file, add the following under <code>"sematics"</code> property:</p> <pre class="grvsc-container default-dark" data-language="json" data-index="1"><code class="grvsc-code"><span class="grvsc-line"><span class="grvsc-source"><span class="mtk8">&quot;schematics&quot;</span><span class="mtk1">: {</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">&quot;@schematics/angular:component&quot;</span><span class="mtk1">: {</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">&quot;inlineStyle&quot;</span><span class="mtk1">: </span><span class="mtk4">true</span><span class="mtk1">,</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">&quot;inlineTemplate&quot;</span><span class="mtk1">: </span><span class="mtk4">true</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> }</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1">}</span></span></span></code></pre> <h2 id="generate-a-test-component" style="position:relative;"><a href="#generate-a-test-component" aria-label="generate a test component permalink" class="anchor before"><svg aria-hidden="true" focusable="false" height="16" version="1.1" viewBox="0 0 16 16" width="16"><path fill-rule="evenodd" d="M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z"></path></svg></a>Generate a test component</h2> <p>Let’s use CLI in the command-line to generate a single file component:</p> <p>ng g component single-file</p> <p>The following folder with two files will be created:</p> <p><span class="gatsby-resp-image-wrapper" style="position: relative; display: block; margin-left: auto; margin-right: auto; max-width: 377px; " > <a class="gatsby-resp-image-link" href="/static/02adad9c59ae0e249fec08ed2b95eca6/6146e/image.png" style="display: block" target="_blank" rel="noopener" > <span class="gatsby-resp-image-background-image" style="padding-bottom: 29.444444444444446%; position: relative; bottom: 0; left: 0; background-image: url('data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABQAAAAGCAIAAABM9SnKAAAACXBIWXMAAAsTAAALEwEAmpwYAAAAx0lEQVR42o3LSXKDMBRFUVYCxEJ9Z3XoC6cQOAE7+99QiCfpBsmrW292GkjeGXkaMCEUY/Jnw4CNlpyxtm0bKeQ+Ryv4qUcY4f9gKQSj9IG5cjm4OeoSpNfoCQ0If+035kpS9sCC05iFmZMuXsGZWSm85mfFnRLBHD/8GEKEM0zJB/YhTfUC9wX2CrcVbrW8Hb/Afc1bjVMx1hvzmdbOxdH62HVdE8dLfN7KvsDLAtfja9lWuNbyusSxOJtCyN/yY4IppNx3/TvAiT8Wn3V94gAAAABJRU5ErkJggg=='); background-size: cover; display: block;" ></span> <img class="gatsby-resp-image-image" alt="image" title="" src="/static/02adad9c59ae0e249fec08ed2b95eca6/6146e/image.png" srcset="/static/02adad9c59ae0e249fec08ed2b95eca6/e9ff0/image.png 180w, /static/02adad9c59ae0e249fec08ed2b95eca6/f21e7/image.png 360w, /static/02adad9c59ae0e249fec08ed2b95eca6/6146e/image.png 377w" sizes="(max-width: 377px) 100vw, 377px" style="width:100%;height:100%;margin:0;vertical-align:middle;position:absolute;top:0;left:0;" loading="lazy" decoding="async" /> </a> </span></p> <p>And the <code>single-file.ts</code> file will look like this:</p> <p><span class="gatsby-resp-image-wrapper" style="position: relative; display: block; margin-left: auto; margin-right: auto; max-width: 529px; " > <a class="gatsby-resp-image-link" href="/static/7714c7752a3a6d817a174e37fecd96e6/67d6a/image-1.png" style="display: block" target="_blank" rel="noopener" > <span class="gatsby-resp-image-background-image" style="padding-bottom: 78.88888888888889%; position: relative; bottom: 0; left: 0; background-image: url('data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABQAAAAQCAIAAACZeshMAAAACXBIWXMAAAsTAAALEwEAmpwYAAABqUlEQVR42pVSW47bMAzMPWKLIimKkuVH/Ii32WJ/2r/e/0Cl7SbbLrZIOyAIWuZwaI1Pqtp1/diP6/yyTHNzuQ4vr9f1ZV5vy5ebnYz99HaRr/Z6Xdd5WuapLaWua+fcCQC8900oitEj5XGN3YgSKbWUGgRMnHMIg0pmzAEZ/bmq3I6NHDjkaeB1ivOoSclV7IG9I3DooXYmU1dbcpU9uHecTJYQJZXp24/h7XvMZdDQp3hJsVNJwjYdnAP3CXYyEXi8jHNTOkQyJZtv3aZ2X/Bz3MkAQn4p2idpVToNY47kwblnZGa2LiUfCY/TJ6QHOYRAhMRSlpuUzurNBdjplo/CHQV8GHyQjRtYorc9jXqutm+1OIrtrs97bIeWD5N/kZnD3E5tyD5k1IJ9obEjy1NvBTaJmzm0V0oddg0PrWr8jWzKJCIZQzLTSIU0AqH9AFsgAomnAJ6AyO/d72STBnNIWggFtU0SI/O+ZL3b9jH+WBuJYgzr0k5jk1WgUSoJ0T+a/nrbMYpZZSOMt+1AbL4js1kIz3BKKeWcJcpD5/AE/gEnvsP9P34CSLeA5lcBjKkAAAAASUVORK5CYII='); background-size: cover; display: block;" ></span> <img class="gatsby-resp-image-image" alt="image 1" title="" src="/static/7714c7752a3a6d817a174e37fecd96e6/67d6a/image-1.png" srcset="/static/7714c7752a3a6d817a174e37fecd96e6/e9ff0/image-1.png 180w, /static/7714c7752a3a6d817a174e37fecd96e6/f21e7/image-1.png 360w, /static/7714c7752a3a6d817a174e37fecd96e6/67d6a/image-1.png 529w" sizes="(max-width: 529px) 100vw, 529px" style="width:100%;height:100%;margin:0;vertical-align:middle;position:absolute;top:0;left:0;" loading="lazy" decoding="async" /> </a> </span></p> <h2 id="add-syntax-highlighting-and-intellisense-support" style="position:relative;"><a href="#add-syntax-highlighting-and-intellisense-support" aria-label="add syntax highlighting and intellisense support permalink" class="anchor before"><svg aria-hidden="true" focusable="false" height="16" version="1.1" viewBox="0 0 16 16" width="16"><path fill-rule="evenodd" d="M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z"></path></svg></a>Add Syntax Highlighting and Intellisense Support</h2> <p>If you are using VS Code, installing <a href="https://marketplace.visualstudio.com/items?itemName=Angular.ng-template">Angular Language Service</a> extension will enable syntax highlighting and intellisense:</p> <p><span class="gatsby-resp-image-wrapper" style="position: relative; display: block; margin-left: auto; margin-right: auto; max-width: 596px; " > <a class="gatsby-resp-image-link" href="/static/a4311e006353766d615fec7f7f18b74e/699b7/image-2.png" style="display: block" target="_blank" rel="noopener" > <span class="gatsby-resp-image-background-image" style="padding-bottom: 88.33333333333333%; position: relative; bottom: 0; left: 0; background-image: url('data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABQAAAASCAIAAADUsmlHAAAACXBIWXMAAAsTAAALEwEAmpwYAAABuElEQVR42p1S2W7cMAz0d8SWSfHQba2P3RR573P//3PKdYAi26RZoAPZsAUSMxzOEEKota3Leqx7WXrebtt+bMfrehzbuq+1vvV4ux772rd1LbnMHzAAApP0fBHRuKx5e6WQKFVKWbxkTj1qU85Cgck599CMAEE13na+7u3YkpB4SOSV0CM4N032uHfMf2FgbzVQth/Xn79Cu0T2iamcPELe6uE8X2JARG8gU7rUWkKMqiHlzCLGBd9isD5mRphTNuOa+ZdiarXKpwm/YCZij6gpa1kA0a6mE3fa+QkGFRvNswbN9e7Q+DJNo7Nz+jR9Sz6IiI0Ms1Plsu7pcoTaQ+um/74e4efNZhuLcoiSCmkgjUS2MzRRz2Qb2BhM5TiNL248ZdvY547t+uE8GkYppd46zAieLW4YBIVRBYSBGDkgCTDbr+XmkVlVWHrqQQulhUrmtfkcyd69+Jg4bxQXTMnXTEwfyd9nRucFtKJmW7MSzZObx8mWNt9NH2d3fk+fZBuzZawt+XrtSyucE7VsFt6r4H3T8K+MDhYvKzXtti8zHQBtdoCnAfkzs4iRPA3jl/EkRJz/C78BQQ2NpeNLX4MAAAAASUVORK5CYII='); background-size: cover; display: block;" ></span> <img class="gatsby-resp-image-image" alt="image 2" title="" src="/static/a4311e006353766d615fec7f7f18b74e/699b7/image-2.png" srcset="/static/a4311e006353766d615fec7f7f18b74e/e9ff0/image-2.png 180w, /static/a4311e006353766d615fec7f7f18b74e/f21e7/image-2.png 360w, /static/a4311e006353766d615fec7f7f18b74e/699b7/image-2.png 596w" sizes="(max-width: 596px) 100vw, 596px" style="width:100%;height:100%;margin:0;vertical-align:middle;position:absolute;top:0;left:0;" loading="lazy" decoding="async" /> </a> </span></p> <p>And finally, we can try binding attributes and properties with intellisense:</p> <p><img src="/a1f3311b9e54a8bb4f187cfeccfbfc4c/ezgif.com-gif-maker-7.gif" alt=""></p> <p>You can access the <a href="https://github.com/muhimasri/angular-single-file-component">complete repository here</a>.</p> <p>Bye for now 👋</p> <style class="grvsc-styles"> .grvsc-container { overflow: auto; position: relative; -webkit-overflow-scrolling: touch; padding-top: 1rem; padding-top: var(--grvsc-padding-top, var(--grvsc-padding-v, 1rem)); padding-bottom: 1rem; padding-bottom: var(--grvsc-padding-bottom, var(--grvsc-padding-v, 1rem)); border-radius: 8px; border-radius: var(--grvsc-border-radius, 8px); font-feature-settings: normal; line-height: 1.4; } .grvsc-code { display: table; } .grvsc-line { display: table-row; box-sizing: border-box; width: 100%; position: relative; } .grvsc-line > * { position: relative; } .grvsc-gutter-pad { display: table-cell; padding-left: 0.75rem; padding-left: calc(var(--grvsc-padding-left, var(--grvsc-padding-h, 1.5rem)) / 2); } .grvsc-gutter { display: table-cell; -webkit-user-select: none; -moz-user-select: none; user-select: none; } .grvsc-gutter::before { content: attr(data-content); } .grvsc-source { display: table-cell; padding-left: 1.5rem; padding-left: var(--grvsc-padding-left, var(--grvsc-padding-h, 1.5rem)); padding-right: 1.5rem; padding-right: var(--grvsc-padding-right, var(--grvsc-padding-h, 1.5rem)); } .grvsc-source:empty::after { content: ' '; -webkit-user-select: none; -moz-user-select: none; user-select: none; } .grvsc-gutter + .grvsc-source { padding-left: 0.75rem; padding-left: calc(var(--grvsc-padding-left, var(--grvsc-padding-h, 1.5rem)) / 2); } /* Line transformer styles */ .grvsc-has-line-highlighting > .grvsc-code > .grvsc-line::before { content: ' '; position: absolute; width: 100%; } .grvsc-line-diff-add::before { background-color: var(--grvsc-line-diff-add-background-color, rgba(0, 255, 60, 0.2)); } .grvsc-line-diff-del::before { background-color: var(--grvsc-line-diff-del-background-color, rgba(255, 0, 20, 0.2)); } .grvsc-line-number { padding: 0 2px; text-align: right; opacity: 0.7; } .default-dark { background-color: #1E1E1E; color: #D4D4D4; } .default-dark .mtk8 { color: #CE9178; } .default-dark .mtk1 { color: #D4D4D4; } .default-dark .mtk12 { color: #9CDCFE; } .default-dark .mtk4 { color: #569CD6; } .default-dark .grvsc-line-highlighted::before { background-color: var(--grvsc-line-highlighted-background-color, rgba(255, 255, 255, 0.1)); box-shadow: inset var(--grvsc-line-highlighted-border-width, 4px) 0 0 0 var(--grvsc-line-highlighted-border-color, rgba(255, 255, 255, 0.5)); } </style><![CDATA[Why Choose Preact for your Next Project]]>https://muhimasri.comwhy-i-chose-preact-for-my-latest-projecthttps://muhimasri.comwhy-i-chose-preact-for-my-latest-project<p>As part of my ongoing consultation, architecture, and development work with JavaScript applications, I’ve recently started a new project that required me to re-evaluate the typical options that I usually go for (Angular, React, or Vue).</p> <p>Here are some of the project’s requirements:</p> <ul> <li>Web Components support</li> <li>Progressive Web App</li> <li>Server-Side rendering</li> <li>JSX-like syntax and functional components</li> <li>Size and performance</li> </ul> <p>While, to some extent, this is all achievable by most of the popular JavaScript frameworks, Preact fully met the criteria without any hurdles and workarounds.</p> <p>Let’s dig a bit deeper into some of Preact’s features that I put together from research and hands-on experience:</p> <h2 id="web-components-support" style="position:relative;"><a href="#web-components-support" aria-label="web components support permalink" class="anchor before"><svg aria-hidden="true" focusable="false" height="16" version="1.1" viewBox="0 0 16 16" width="16"><path fill-rule="evenodd" d="M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z"></path></svg></a>Web Components Support:</h2> <p>Unlike React, Preact uses the browser’s native addEventListener for handling events internally so it can listen to native DOM events dispatched from Custom Elements. Also, it has a special approach to know when to pass data to Custom Elements as either properties or attributes.</p> <p>Here is an example from <a href="https://preactjs.com/guide/v10/web-components">Preact official site</a>:</p> <pre class="grvsc-container default-dark" data-language="jsx" data-index="0"><code class="grvsc-code"><span class="grvsc-line"><span class="grvsc-source"><span class="mtk12">customElements</span><span class="mtk1">.</span><span class="mtk11">define</span><span class="mtk1">(</span><span class="mtk8">&#39;context-menu&#39;</span><span class="mtk1">, </span><span class="mtk4">class</span><span class="mtk1"> </span><span class="mtk4">extends</span><span class="mtk1"> </span><span class="mtk10">HTMLElement</span><span class="mtk1"> {</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk4">set</span><span class="mtk1"> </span><span class="mtk11">position</span><span class="mtk1">({ </span><span class="mtk12">x</span><span class="mtk1">, </span><span class="mtk12">y</span><span class="mtk1"> }) {</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk4">this</span><span class="mtk1">.</span><span class="mtk12">style</span><span class="mtk1">.</span><span class="mtk12">cssText</span><span class="mtk1"> = </span><span class="mtk8">`left:</span><span class="mtk4">${</span><span class="mtk12">x</span><span class="mtk4">}</span><span class="mtk8">px; top:</span><span class="mtk4">${</span><span class="mtk12">y</span><span class="mtk4">}</span><span class="mtk8">px;`</span><span class="mtk1">;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> }</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1">});</span></span></span> <span class="grvsc-line"><span class="grvsc-source"></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk4">function</span><span class="mtk1"> </span><span class="mtk11">Foo</span><span class="mtk1">() {</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk15">return</span><span class="mtk1"> </span><span class="mtk17">&lt;</span><span class="mtk10">context-menu</span><span class="mtk1"> </span><span class="mtk12">position</span><span class="mtk1">=</span><span class="mtk4">{</span><span class="mtk1">{ </span><span class="mtk12">x:</span><span class="mtk1"> </span><span class="mtk7">10</span><span class="mtk1">, </span><span class="mtk12">y:</span><span class="mtk1"> </span><span class="mtk7">20</span><span class="mtk1"> }</span><span class="mtk4">}</span><span class="mtk17">&gt;</span><span class="mtk1"> ... </span><span class="mtk17">&lt;/</span><span class="mtk10">context-menu</span><span class="mtk17">&gt;</span><span class="mtk1">;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1">}</span></span></span></code></pre> <p>If you prefer using the same library for both your Web Components and Preact components, then you can use <a href="https://github.com/preactjs/preact-custom-element">preact-custom-element</a> to turn any Preact component into a Web Component!</p> <h2 id="jsx-and-htm" style="position:relative;"><a href="#jsx-and-htm" aria-label="jsx and htm permalink" class="anchor before"><svg aria-hidden="true" focusable="false" height="16" version="1.1" viewBox="0 0 16 16" width="16"><path fill-rule="evenodd" d="M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z"></path></svg></a>JSX and HTM</h2> <p>JSX allows us to write HTML elements in JavaScript. This is very useful if you want to leverage JavaScript syntax within your templates.</p> <p>Preact supports JSX out of the box but also encourages to use HTM as an alternative. HTM is a JSX-like syntax but does not require an extra build step because it uses JavaScript’s Tagged Templates Literals to bind data and properties to the template. Awesome!</p> <pre class="grvsc-container default-dark" data-language="jsx" data-index="1"><code class="grvsc-code"><span class="grvsc-line"><span class="grvsc-source"><span class="mtk4">const</span><span class="mtk1"> </span><span class="mtk11">Panel</span><span class="mtk1"> = ({</span><span class="mtk12">title</span><span class="mtk1">, </span><span class="mtk12">content</span><span class="mtk1">}) </span><span class="mtk4">=&gt;</span><span class="mtk1"> {</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk15">return</span><span class="mtk1"> </span><span class="mtk11">html</span><span class="mtk8">`</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk8"> &lt;article&gt;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk8"> &lt;section&gt;</span><span class="mtk4">${</span><span class="mtk12">title</span><span class="mtk4">}</span><span class="mtk8">&lt;/section&gt;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk8"> &lt;section&gt;</span><span class="mtk4">${</span><span class="mtk12">content</span><span class="mtk4">}</span><span class="mtk8">&lt;/section&gt;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk8"> &lt;/article&gt;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk8"> `</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1">}</span></span></span></code></pre> <h2 id="react-compatibility" style="position:relative;"><a href="#react-compatibility" aria-label="react compatibility permalink" class="anchor before"><svg aria-hidden="true" focusable="false" height="16" version="1.1" viewBox="0 0 16 16" width="16"><path fill-rule="evenodd" d="M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z"></path></svg></a>React compatibility</h2> <p>One of the biggest advantages of using React is its vast community, support, and libraries. Preact’s syntax is nearly identical to React and by adding a simple <code>preact/compact</code> layer, it allows you to use any React library and fully leverage its ecosystem. Also, it supports Hooks API using <code>preact/hooks</code>.</p> <h2 id="progressive-web-apps-pwa" style="position:relative;"><a href="#progressive-web-apps-pwa" aria-label="progressive web apps pwa permalink" class="anchor before"><svg aria-hidden="true" focusable="false" height="16" version="1.1" viewBox="0 0 16 16" width="16"><path fill-rule="evenodd" d="M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z"></path></svg></a>Progressive Web Apps (PWA)</h2> <p>PWS is a design pattern that is typically used to provide a native like-app user experience.</p> <p>Preact CLI bundles your code into a highly optimized Progressive Web App with a 100 <a href="https://developers.google.com/web/tools/lighthouse/">Lighthouse</a> score. Here are some of the features that Preact CLI provides out of the box:</p> <ul> <li>Code-splitting for your URL routes</li> <li>Automatically generates and installs a ServiceWorker</li> <li>Generates HTTP2/Push headers based on the URL</li> </ul> <h2 id="server-side-rendering" style="position:relative;"><a href="#server-side-rendering" aria-label="server side rendering permalink" class="anchor before"><svg aria-hidden="true" focusable="false" height="16" version="1.1" viewBox="0 0 16 16" width="16"><path fill-rule="evenodd" d="M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z"></path></svg></a>Server-Side Rendering</h2> <p>Server-Side Rendering (SSR) allows you to render your application on the server as HTML string which then can be sent to the client-side. This design pattern usually improves performance and SEO.</p> <p>SSR is automatically enabled with <code>preact-cli</code>. Here is an example from <a href="https://preactjs.com/guide/v10/server-side-rendering/">Preact official site</a>:</p> <pre class="grvsc-container default-dark" data-language="jsx" data-index="2"><code class="grvsc-code"><span class="grvsc-line"><span class="grvsc-source"><span class="mtk15">import</span><span class="mtk1"> </span><span class="mtk12">render</span><span class="mtk1"> </span><span class="mtk15">from</span><span class="mtk1"> </span><span class="mtk8">&#39;preact-render-to-string&#39;</span><span class="mtk1">;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk15">import</span><span class="mtk1"> { </span><span class="mtk12">h</span><span class="mtk1"> } </span><span class="mtk15">from</span><span class="mtk1"> </span><span class="mtk8">&#39;preact&#39;</span><span class="mtk1">;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk4">const</span><span class="mtk1"> </span><span class="mtk12">App</span><span class="mtk1"> = </span><span class="mtk17">&lt;</span><span class="mtk4">div</span><span class="mtk1"> </span><span class="mtk12">class</span><span class="mtk1">=</span><span class="mtk8">&quot;foo&quot;</span><span class="mtk17">&gt;</span><span class="mtk1">content</span><span class="mtk17">&lt;/</span><span class="mtk4">div</span><span class="mtk17">&gt;</span><span class="mtk1">;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk10">console</span><span class="mtk1">.</span><span class="mtk11">log</span><span class="mtk1">(</span><span class="mtk11">render</span><span class="mtk1">(</span><span class="mtk12">App</span><span class="mtk1">));</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk3">// &lt;div class=&quot;foo&quot;&gt;content&lt;/div&gt;</span></span></span></code></pre> <h2 id="size-and-performance" style="position:relative;"><a href="#size-and-performance" aria-label="size and performance permalink" class="anchor before"><svg aria-hidden="true" focusable="false" height="16" version="1.1" viewBox="0 0 16 16" width="16"><path fill-rule="evenodd" d="M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z"></path></svg></a>Size and performance</h2> <p>Although most modern JavaScript libraries and frameworks focus on performance, size, efficiency, etc. It’s worth mentioning that Preact had the smallest bundle size and fastest loading time compared to React, Vue, and Angular.</p> <p><em>This comparison was not conducted on a large-scale enterprise application. If performance and size is the main requirement for your next JavaScript project, please make sure to do enough research and testing and don’t just rely on this article.</em></p> <h2 id="other-cool-features" style="position:relative;"><a href="#other-cool-features" aria-label="other cool features permalink" class="anchor before"><svg aria-hidden="true" focusable="false" height="16" version="1.1" viewBox="0 0 16 16" width="16"><path fill-rule="evenodd" d="M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z"></path></svg></a>Other cool features</h2> <ul> <li>Native support for ES Modules</li> <li>Helpful warnings and errors by importing <code>preact/debug</code></li> <li>Powerful and easy to use <a href="https://github.com/preactjs/preact-cli">CLI</a></li> </ul> <h2 id="final-thoughts" style="position:relative;"><a href="#final-thoughts" aria-label="final thoughts permalink" class="anchor before"><svg aria-hidden="true" focusable="false" height="16" version="1.1" viewBox="0 0 16 16" width="16"><path fill-rule="evenodd" d="M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z"></path></svg></a>Final Thoughts</h2> <p>Working with Preact surpassed the expectations and was very satisfying but as usual, each project has its requirements and Preact might not be the optimum solution for you and your team.</p> <p>Bye for now 👋</p> <style class="grvsc-styles"> .grvsc-container { overflow: auto; position: relative; -webkit-overflow-scrolling: touch; padding-top: 1rem; padding-top: var(--grvsc-padding-top, var(--grvsc-padding-v, 1rem)); padding-bottom: 1rem; padding-bottom: var(--grvsc-padding-bottom, var(--grvsc-padding-v, 1rem)); border-radius: 8px; border-radius: var(--grvsc-border-radius, 8px); font-feature-settings: normal; line-height: 1.4; } .grvsc-code { display: table; } .grvsc-line { display: table-row; box-sizing: border-box; width: 100%; position: relative; } .grvsc-line > * { position: relative; } .grvsc-gutter-pad { display: table-cell; padding-left: 0.75rem; padding-left: calc(var(--grvsc-padding-left, var(--grvsc-padding-h, 1.5rem)) / 2); } .grvsc-gutter { display: table-cell; -webkit-user-select: none; -moz-user-select: none; user-select: none; } .grvsc-gutter::before { content: attr(data-content); } .grvsc-source { display: table-cell; padding-left: 1.5rem; padding-left: var(--grvsc-padding-left, var(--grvsc-padding-h, 1.5rem)); padding-right: 1.5rem; padding-right: var(--grvsc-padding-right, var(--grvsc-padding-h, 1.5rem)); } .grvsc-source:empty::after { content: ' '; -webkit-user-select: none; -moz-user-select: none; user-select: none; } .grvsc-gutter + .grvsc-source { padding-left: 0.75rem; padding-left: calc(var(--grvsc-padding-left, var(--grvsc-padding-h, 1.5rem)) / 2); } /* Line transformer styles */ .grvsc-has-line-highlighting > .grvsc-code > .grvsc-line::before { content: ' '; position: absolute; width: 100%; } .grvsc-line-diff-add::before { background-color: var(--grvsc-line-diff-add-background-color, rgba(0, 255, 60, 0.2)); } .grvsc-line-diff-del::before { background-color: var(--grvsc-line-diff-del-background-color, rgba(255, 0, 20, 0.2)); } .grvsc-line-number { padding: 0 2px; text-align: right; opacity: 0.7; } .default-dark { background-color: #1E1E1E; color: #D4D4D4; } .default-dark .mtk12 { color: #9CDCFE; } .default-dark .mtk1 { color: #D4D4D4; } .default-dark .mtk11 { color: #DCDCAA; } .default-dark .mtk8 { color: #CE9178; } .default-dark .mtk4 { color: #569CD6; } .default-dark .mtk10 { color: #4EC9B0; } .default-dark .mtk15 { color: #C586C0; } .default-dark .mtk17 { color: #808080; } .default-dark .mtk7 { color: #B5CEA8; } .default-dark .mtk3 { color: #6A9955; } .default-dark .grvsc-line-highlighted::before { background-color: var(--grvsc-line-highlighted-background-color, rgba(255, 255, 255, 0.1)); box-shadow: inset var(--grvsc-line-highlighted-border-width, 4px) 0 0 0 var(--grvsc-line-highlighted-border-color, rgba(255, 255, 255, 0.5)); } </style><![CDATA[How to Create a Built-In Loading Bar for your React Dialog]]>https://muhimasri.comhow-to-create-a-built-in-loading-bar-for-your-react-dialoghttps://muhimasri.comhow-to-create-a-built-in-loading-bar-for-your-react-dialog<p>Form dialogs are very common and useful especially when you don’t want to redirect the user to a separate page. A common example would be a newsletter subscription dialog, whether or not users choose to subscribe, they shouldn’t have to navigate back to the initial page.</p> <p>A good practice is to trigger a loading bar as soon as the user submits a request to the server. Here is an example I created using Material Linear Progress:</p> <p><img src="/6e09e3a69e5b5f7a7a38755c44d6454b/ezgif.com-gif-maker-6-1.gif" alt=""></p> <p>But what if we have other form dialogs in a project that requires to behave the same way? In this article, I will go through a step-by-step guide to creating a reusable custom dialog that inherits from React Material and extends functionality to include a built-in loading bar. This way, we have a consistent experience in every dialog without any redundancies.</p> <h2 id="setup-react-project" style="position:relative;"><a href="#setup-react-project" aria-label="setup react project permalink" class="anchor before"><svg aria-hidden="true" focusable="false" height="16" version="1.1" viewBox="0 0 16 16" width="16"><path fill-rule="evenodd" d="M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z"></path></svg></a>Setup React Project</h2> <p><a href="https://create-react-app.dev/docs/getting-started/">Create React App</a> and install <a href="https://material-ui.com/getting-started/installation/">React Material</a></p> <pre class="grvsc-container default-dark" data-language="" data-index="0"><code class="grvsc-code"><span class="grvsc-line"><span class="grvsc-source">npx create-react-app react-material-dialog</span></span> <span class="grvsc-line"><span class="grvsc-source">npm install @material-ui/core</span></span></code></pre> <h2 id="create-a-custom-dialog" style="position:relative;"><a href="#create-a-custom-dialog" aria-label="create a custom dialog permalink" class="anchor before"><svg aria-hidden="true" focusable="false" height="16" version="1.1" viewBox="0 0 16 16" width="16"><path fill-rule="evenodd" d="M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z"></path></svg></a>Create a Custom Dialog</h2> <p>Let’s create a new <code>Dialog.js</code> component that inherits from Material Dialog and uses a <code>LinearProgress</code> component.</p> <pre class="grvsc-container default-dark" data-language="jsx" data-index="1"><code class="grvsc-code"><span class="grvsc-line"><span class="grvsc-source"><span class="mtk15">import</span><span class="mtk1"> { </span><span class="mtk12">LinearProgress</span><span class="mtk1"> } </span><span class="mtk15">from</span><span class="mtk1"> </span><span class="mtk8">&#39;@material-ui/core&#39;</span><span class="mtk1">;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk15">import</span><span class="mtk1"> </span><span class="mtk12">MatDialog</span><span class="mtk1"> </span><span class="mtk15">from</span><span class="mtk1"> </span><span class="mtk8">&#39;@material-ui/core/Dialog&#39;</span><span class="mtk1">;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk15">export</span><span class="mtk1"> </span><span class="mtk4">const</span><span class="mtk1"> </span><span class="mtk11">Dialog</span><span class="mtk1"> = ({</span><span class="mtk12">children</span><span class="mtk1">, ...</span><span class="mtk12">props</span><span class="mtk1">}) </span><span class="mtk4">=&gt;</span><span class="mtk1"> {</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk15">return</span><span class="mtk1"> (</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk17">&lt;</span><span class="mtk10">MatDialog</span><span class="mtk1"> </span><span class="mtk4">{</span><span class="mtk1">...</span><span class="mtk12">props</span><span class="mtk4">}</span><span class="mtk17">&gt;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk17">&lt;</span><span class="mtk10">LinearProgress</span><span class="mtk17">&gt;&lt;/</span><span class="mtk10">LinearProgress</span><span class="mtk17">&gt;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk4">{</span><span class="mtk12">children</span><span class="mtk4">}</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk17">&lt;/</span><span class="mtk10">MatDialog</span><span class="mtk17">&gt;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> )</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1">}</span></span></span></code></pre> <p>We placed the LinearProgress as the first element within MatDialog followed by the children that will eventually be passed by the consumer. Also, <code>…props</code> should go into MatDialog in order to access all the component’s features (such as open, onClose, aria…).</p> <p><em>The reason why I’m importing Material Dialog as <code>MatDialog</code> to not to cause naming conflict with the custom <code>dialog.js</code> we just created</em></p> <h2 id="test-loading-bar" style="position:relative;"><a href="#test-loading-bar" aria-label="test loading bar permalink" class="anchor before"><svg aria-hidden="true" focusable="false" height="16" version="1.1" viewBox="0 0 16 16" width="16"><path fill-rule="evenodd" d="M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z"></path></svg></a>Test Loading Bar</h2> <p>In the main <code>App.js</code> component, let’s try out the custom dialog we just created and check if the loading bar is showing. We will use one of the form dialog examples from <a href="https://material-ui.com/components/dialogs/">React Material</a> but instead of importing the dialog from <code>@material-ui/core</code> will import the custom one <code>./Dialog</code></p> <pre class="grvsc-container default-dark" data-language="jsx" data-index="2"><code class="grvsc-code"><span class="grvsc-line"><span class="grvsc-source"><span class="mtk15">import</span><span class="mtk1"> { </span><span class="mtk12">useState</span><span class="mtk1"> } </span><span class="mtk15">from</span><span class="mtk1"> </span><span class="mtk8">&#39;react&#39;</span><span class="mtk1">;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk15">import</span><span class="mtk1"> </span><span class="mtk8">&#39;./App.css&#39;</span><span class="mtk1">;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk15">import</span><span class="mtk1"> { </span><span class="mtk12">Button</span><span class="mtk1">, </span><span class="mtk12">DialogTitle</span><span class="mtk1">, </span><span class="mtk12">DialogContent</span><span class="mtk1">, </span><span class="mtk12">DialogContentText</span><span class="mtk1">, </span><span class="mtk12">TextField</span><span class="mtk1">, </span><span class="mtk12">DialogActions</span><span class="mtk1"> } </span><span class="mtk15">from</span><span class="mtk1"> </span><span class="mtk8">&#39;@material-ui/core&#39;</span><span class="mtk1">;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk15">import</span><span class="mtk1"> { </span><span class="mtk12">Dialog</span><span class="mtk1"> } </span><span class="mtk15">from</span><span class="mtk1"> </span><span class="mtk8">&#39;./Dialog&#39;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk4">function</span><span class="mtk1"> </span><span class="mtk11">App</span><span class="mtk1">() {</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk4">const</span><span class="mtk1"> [</span><span class="mtk12">open</span><span class="mtk1">, </span><span class="mtk12">setOpen</span><span class="mtk1">] = </span><span class="mtk11">useState</span><span class="mtk1">(</span><span class="mtk4">false</span><span class="mtk1">);</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk4">const</span><span class="mtk1"> </span><span class="mtk11">handleClose</span><span class="mtk1"> = () </span><span class="mtk4">=&gt;</span><span class="mtk1"> {</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk11">setOpen</span><span class="mtk1">(</span><span class="mtk4">false</span><span class="mtk1">);</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> };</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk15">return</span><span class="mtk1"> (</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk17">&lt;</span><span class="mtk4">div</span><span class="mtk1"> </span><span class="mtk12">className</span><span class="mtk1">=</span><span class="mtk8">&quot;App&quot;</span><span class="mtk17">&gt;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk17">&lt;</span><span class="mtk10">Button</span><span class="mtk1"> </span><span class="mtk12">onClick</span><span class="mtk1">=</span><span class="mtk4">{</span><span class="mtk1">() </span><span class="mtk4">=&gt;</span><span class="mtk1"> </span><span class="mtk11">setOpen</span><span class="mtk1">(</span><span class="mtk4">true</span><span class="mtk1">)</span><span class="mtk4">}</span><span class="mtk17">&gt;</span><span class="mtk1">Open</span><span class="mtk17">&lt;/</span><span class="mtk10">Button</span><span class="mtk17">&gt;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk17">&lt;</span><span class="mtk10">Dialog</span><span class="mtk1"> </span><span class="mtk12">open</span><span class="mtk1">=</span><span class="mtk4">{</span><span class="mtk12">open</span><span class="mtk4">}</span><span class="mtk1"> </span><span class="mtk12">onClose</span><span class="mtk1">=</span><span class="mtk4">{</span><span class="mtk12">handleClose</span><span class="mtk4">}</span><span class="mtk1"> </span><span class="mtk12">aria-labelledby</span><span class="mtk1">=</span><span class="mtk8">&quot;form-dialog-title&quot;</span><span class="mtk17">&gt;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk17">&lt;</span><span class="mtk10">DialogTitle</span><span class="mtk1"> </span><span class="mtk12">id</span><span class="mtk1">=</span><span class="mtk8">&quot;form-dialog-title&quot;</span><span class="mtk17">&gt;</span><span class="mtk1">Subscribe</span><span class="mtk17">&lt;/</span><span class="mtk10">DialogTitle</span><span class="mtk17">&gt;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk17">&lt;</span><span class="mtk10">DialogContent</span><span class="mtk17">&gt;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk17">&lt;</span><span class="mtk10">DialogContentText</span><span class="mtk17">&gt;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> To subscribe to this website, please enter your email address here. We will send updates</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> occasionally.</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk17">&lt;/</span><span class="mtk10">DialogContentText</span><span class="mtk17">&gt;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk17">&lt;</span><span class="mtk10">TextField</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">autoFocus</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">margin</span><span class="mtk1">=</span><span class="mtk8">&quot;dense&quot;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">id</span><span class="mtk1">=</span><span class="mtk8">&quot;name&quot;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">label</span><span class="mtk1">=</span><span class="mtk8">&quot;Email Address&quot;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">type</span><span class="mtk1">=</span><span class="mtk8">&quot;email&quot;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">fullWidth</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk17">/&gt;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk17">&lt;/</span><span class="mtk10">DialogContent</span><span class="mtk17">&gt;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk17">&lt;</span><span class="mtk10">DialogActions</span><span class="mtk17">&gt;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk17">&lt;</span><span class="mtk10">Button</span><span class="mtk1"> </span><span class="mtk12">onClick</span><span class="mtk1">=</span><span class="mtk4">{</span><span class="mtk12">handleClose</span><span class="mtk4">}</span><span class="mtk1"> </span><span class="mtk12">color</span><span class="mtk1">=</span><span class="mtk8">&quot;primary&quot;</span><span class="mtk17">&gt;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> Cancel</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk17">&lt;/</span><span class="mtk10">Button</span><span class="mtk17">&gt;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk17">&lt;</span><span class="mtk10">Button</span><span class="mtk1"> </span><span class="mtk12">onClick</span><span class="mtk1">=</span><span class="mtk4">{</span><span class="mtk12">handleClose</span><span class="mtk4">}</span><span class="mtk1"> </span><span class="mtk12">color</span><span class="mtk1">=</span><span class="mtk8">&quot;primary&quot;</span><span class="mtk17">&gt;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> Subscribe</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk17">&lt;/</span><span class="mtk10">Button</span><span class="mtk17">&gt;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk17">&lt;/</span><span class="mtk10">DialogActions</span><span class="mtk17">&gt;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk17">&lt;/</span><span class="mtk10">Dialog</span><span class="mtk17">&gt;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk17">&lt;/</span><span class="mtk4">div</span><span class="mtk17">&gt;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> );</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1">}</span></span></span> <span class="grvsc-line"><span class="grvsc-source"></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk15">export</span><span class="mtk1"> </span><span class="mtk15">default</span><span class="mtk1"> </span><span class="mtk12">App</span><span class="mtk1">;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1">@</span><span class="mtk12">muhimasri</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span></span></span></code></pre> <p><img src="/1602a15cccb19f6125f7fc2745831883/ezgif.com-gif-maker-4-2.gif" alt="React dialog"></p> <h2 id="create-conditional-loading" style="position:relative;"><a href="#create-conditional-loading" aria-label="create conditional loading permalink" class="anchor before"><svg aria-hidden="true" focusable="false" height="16" version="1.1" viewBox="0 0 16 16" width="16"><path fill-rule="evenodd" d="M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z"></path></svg></a>Create Conditional Loading</h2> <p>As we can see above, the current component is not complete as the loading bar shows all the time.</p> <p>We can easily adjust this by adding a new <code>loading</code> prop that can be passed by the consumer. It will indicate when to trigger the loading:</p> <pre class="grvsc-container default-dark" data-language="jsx" data-index="3"><code class="grvsc-code"><span class="grvsc-line"><span class="grvsc-source"><span class="mtk15">import</span><span class="mtk1"> { </span><span class="mtk12">LinearProgress</span><span class="mtk1"> } </span><span class="mtk15">from</span><span class="mtk1"> </span><span class="mtk8">&#39;@material-ui/core&#39;</span><span class="mtk1">;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk15">import</span><span class="mtk1"> </span><span class="mtk12">MatDialog</span><span class="mtk1"> </span><span class="mtk15">from</span><span class="mtk1"> </span><span class="mtk8">&#39;@material-ui/core/Dialog&#39;</span><span class="mtk1">;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk15">export</span><span class="mtk1"> </span><span class="mtk4">const</span><span class="mtk1"> </span><span class="mtk11">Dialog</span><span class="mtk1"> = ({</span><span class="mtk12">loading</span><span class="mtk1">, </span><span class="mtk12">children</span><span class="mtk1">, ...</span><span class="mtk12">props</span><span class="mtk1">}) </span><span class="mtk4">=&gt;</span><span class="mtk1"> {</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk15">return</span><span class="mtk1"> (</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk17">&lt;</span><span class="mtk10">MatDialog</span><span class="mtk1"> </span><span class="mtk4">{</span><span class="mtk1">...</span><span class="mtk12">props</span><span class="mtk4">}</span><span class="mtk17">&gt;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk4">{</span><span class="mtk12">loading</span><span class="mtk1"> ? </span><span class="mtk17">&lt;</span><span class="mtk10">LinearProgress</span><span class="mtk17">&gt;&lt;/</span><span class="mtk10">LinearProgress</span><span class="mtk17">&gt;</span><span class="mtk1"> : </span><span class="mtk4">null}</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk4">{</span><span class="mtk12">children</span><span class="mtk4">}</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk17">&lt;/</span><span class="mtk10">MatDialog</span><span class="mtk17">&gt;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> )</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1">}</span></span></span></code></pre> <p>Now that we have the full component ready and it accepts a <code>loading</code> prop, let’s trigger the loading bar upon submitting the form. We will including a timeout function to mimic an API call and then close the dialog:</p> <pre class="grvsc-container default-dark" data-language="jsx" data-index="4"><code class="grvsc-code"><span class="grvsc-line"><span class="grvsc-source"><span class="mtk15">import</span><span class="mtk1"> { </span><span class="mtk12">useState</span><span class="mtk1"> } </span><span class="mtk15">from</span><span class="mtk1"> </span><span class="mtk8">&#39;react&#39;</span><span class="mtk1">;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk15">import</span><span class="mtk1"> </span><span class="mtk8">&#39;./App.css&#39;</span><span class="mtk1">;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk15">import</span><span class="mtk1"> { </span><span class="mtk12">Button</span><span class="mtk1">, </span><span class="mtk12">DialogTitle</span><span class="mtk1">, </span><span class="mtk12">DialogContent</span><span class="mtk1">, </span><span class="mtk12">DialogContentText</span><span class="mtk1">, </span><span class="mtk12">TextField</span><span class="mtk1">, </span><span class="mtk12">DialogActions</span><span class="mtk1"> } </span><span class="mtk15">from</span><span class="mtk1"> </span><span class="mtk8">&#39;@material-ui/core&#39;</span><span class="mtk1">;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk15">import</span><span class="mtk1"> { </span><span class="mtk12">Dialog</span><span class="mtk1"> } </span><span class="mtk15">from</span><span class="mtk1"> </span><span class="mtk8">&#39;./Dialog&#39;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk4">function</span><span class="mtk1"> </span><span class="mtk11">App</span><span class="mtk1">() {</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk4">const</span><span class="mtk1"> [</span><span class="mtk12">open</span><span class="mtk1">, </span><span class="mtk12">setOpen</span><span class="mtk1">] = </span><span class="mtk11">useState</span><span class="mtk1">(</span><span class="mtk4">false</span><span class="mtk1">);</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk4">const</span><span class="mtk1"> [</span><span class="mtk12">loading</span><span class="mtk1">, </span><span class="mtk12">setLoading</span><span class="mtk1">] = </span><span class="mtk11">useState</span><span class="mtk1">(</span><span class="mtk4">false</span><span class="mtk1">);</span></span></span> <span class="grvsc-line"><span class="grvsc-source"></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk4">const</span><span class="mtk1"> </span><span class="mtk11">handleClose</span><span class="mtk1"> = () </span><span class="mtk4">=&gt;</span><span class="mtk1"> {</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk11">setOpen</span><span class="mtk1">(</span><span class="mtk4">false</span><span class="mtk1">);</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> };</span></span></span> <span class="grvsc-line"><span class="grvsc-source"></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk4">const</span><span class="mtk1"> </span><span class="mtk11">handleSubscribe</span><span class="mtk1"> = () </span><span class="mtk4">=&gt;</span><span class="mtk1"> {</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk11">setLoading</span><span class="mtk1">(</span><span class="mtk4">true</span><span class="mtk1">);</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk11">setTimeout</span><span class="mtk1">(() </span><span class="mtk4">=&gt;</span><span class="mtk1"> {</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk11">setLoading</span><span class="mtk1">(</span><span class="mtk4">false</span><span class="mtk1">);</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk11">setOpen</span><span class="mtk1">(</span><span class="mtk4">false</span><span class="mtk1">);</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> }, </span><span class="mtk7">2000</span><span class="mtk1">)</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> }</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk15">return</span><span class="mtk1"> (</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk17">&lt;</span><span class="mtk4">div</span><span class="mtk1"> </span><span class="mtk12">className</span><span class="mtk1">=</span><span class="mtk8">&quot;App&quot;</span><span class="mtk17">&gt;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk17">&lt;</span><span class="mtk10">Button</span><span class="mtk1"> </span><span class="mtk12">variant</span><span class="mtk1">=</span><span class="mtk8">&quot;outlined&quot;</span><span class="mtk1"> </span><span class="mtk12">onClick</span><span class="mtk1">=</span><span class="mtk4">{</span><span class="mtk1">() </span><span class="mtk4">=&gt;</span><span class="mtk1"> </span><span class="mtk11">setOpen</span><span class="mtk1">(</span><span class="mtk4">true</span><span class="mtk1">)</span><span class="mtk4">}</span><span class="mtk17">&gt;</span><span class="mtk1">Open Dialog</span><span class="mtk17">&lt;/</span><span class="mtk10">Button</span><span class="mtk17">&gt;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk17">&lt;</span><span class="mtk10">Dialog</span><span class="mtk1"> </span><span class="mtk12">loading</span><span class="mtk1">=</span><span class="mtk4">{</span><span class="mtk12">loading</span><span class="mtk4">}</span><span class="mtk1"> </span><span class="mtk12">open</span><span class="mtk1">=</span><span class="mtk4">{</span><span class="mtk12">open</span><span class="mtk4">}</span><span class="mtk1"> </span><span class="mtk12">onClose</span><span class="mtk1">=</span><span class="mtk4">{</span><span class="mtk12">handleClose</span><span class="mtk4">}</span><span class="mtk1"> </span><span class="mtk12">aria-labelledby</span><span class="mtk1">=</span><span class="mtk8">&quot;form-dialog-title&quot;</span><span class="mtk17">&gt;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk17">&lt;</span><span class="mtk10">DialogTitle</span><span class="mtk1"> </span><span class="mtk12">id</span><span class="mtk1">=</span><span class="mtk8">&quot;form-dialog-title&quot;</span><span class="mtk17">&gt;</span><span class="mtk1">Subscribe</span><span class="mtk17">&lt;/</span><span class="mtk10">DialogTitle</span><span class="mtk17">&gt;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk17">&lt;</span><span class="mtk10">DialogContent</span><span class="mtk17">&gt;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk17">&lt;</span><span class="mtk10">DialogContentText</span><span class="mtk17">&gt;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> To subscribe to this website, please enter your email address here. We will send updates</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> occasionally.</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk17">&lt;/</span><span class="mtk10">DialogContentText</span><span class="mtk17">&gt;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk17">&lt;</span><span class="mtk10">TextField</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">autoFocus</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">margin</span><span class="mtk1">=</span><span class="mtk8">&quot;dense&quot;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">id</span><span class="mtk1">=</span><span class="mtk8">&quot;name&quot;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">label</span><span class="mtk1">=</span><span class="mtk8">&quot;Email Address&quot;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">type</span><span class="mtk1">=</span><span class="mtk8">&quot;email&quot;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">fullWidth</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk17">/&gt;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk17">&lt;/</span><span class="mtk10">DialogContent</span><span class="mtk17">&gt;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk17">&lt;</span><span class="mtk10">DialogActions</span><span class="mtk17">&gt;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk17">&lt;</span><span class="mtk10">Button</span><span class="mtk1"> </span><span class="mtk12">onClick</span><span class="mtk1">=</span><span class="mtk4">{</span><span class="mtk12">handleClose</span><span class="mtk4">}</span><span class="mtk1"> </span><span class="mtk12">color</span><span class="mtk1">=</span><span class="mtk8">&quot;primary&quot;</span><span class="mtk17">&gt;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> Cancel</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk17">&lt;/</span><span class="mtk10">Button</span><span class="mtk17">&gt;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk17">&lt;</span><span class="mtk10">Button</span><span class="mtk1"> </span><span class="mtk12">onClick</span><span class="mtk1">=</span><span class="mtk4">{</span><span class="mtk12">handleSubscribe</span><span class="mtk4">}</span><span class="mtk1"> </span><span class="mtk12">color</span><span class="mtk1">=</span><span class="mtk8">&quot;primary&quot;</span><span class="mtk17">&gt;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> Subscribe</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk17">&lt;/</span><span class="mtk10">Button</span><span class="mtk17">&gt;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk17">&lt;/</span><span class="mtk10">DialogActions</span><span class="mtk17">&gt;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk17">&lt;/</span><span class="mtk10">Dialog</span><span class="mtk17">&gt;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk17">&lt;/</span><span class="mtk4">div</span><span class="mtk17">&gt;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> );</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1">}</span></span></span> <span class="grvsc-line"><span class="grvsc-source"></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk15">export</span><span class="mtk1"> </span><span class="mtk15">default</span><span class="mtk1"> </span><span class="mtk12">App</span><span class="mtk1">;</span></span></span></code></pre> <p><img src="/6e09e3a69e5b5f7a7a38755c44d6454b/ezgif.com-gif-maker-6.gif" alt="React dialog"></p> <p>And you’re all done! Now, anytime you have a form dialog, all you need to do is to use the new custom dialog and pass it the <code>loading</code> prop.</p> <p>You can access the <a href="https://github.com/muhimasri/react-material-loading-dialog">complete repository here</a>.</p> <p>Bye for now 👋</p> <style class="grvsc-styles"> .grvsc-container { overflow: auto; position: relative; -webkit-overflow-scrolling: touch; padding-top: 1rem; padding-top: var(--grvsc-padding-top, var(--grvsc-padding-v, 1rem)); padding-bottom: 1rem; padding-bottom: var(--grvsc-padding-bottom, var(--grvsc-padding-v, 1rem)); border-radius: 8px; border-radius: var(--grvsc-border-radius, 8px); font-feature-settings: normal; line-height: 1.4; } .grvsc-code { display: table; } .grvsc-line { display: table-row; box-sizing: border-box; width: 100%; position: relative; } .grvsc-line > * { position: relative; } .grvsc-gutter-pad { display: table-cell; padding-left: 0.75rem; padding-left: calc(var(--grvsc-padding-left, var(--grvsc-padding-h, 1.5rem)) / 2); } .grvsc-gutter { display: table-cell; -webkit-user-select: none; -moz-user-select: none; user-select: none; } .grvsc-gutter::before { content: attr(data-content); } .grvsc-source { display: table-cell; padding-left: 1.5rem; padding-left: var(--grvsc-padding-left, var(--grvsc-padding-h, 1.5rem)); padding-right: 1.5rem; padding-right: var(--grvsc-padding-right, var(--grvsc-padding-h, 1.5rem)); } .grvsc-source:empty::after { content: ' '; -webkit-user-select: none; -moz-user-select: none; user-select: none; } .grvsc-gutter + .grvsc-source { padding-left: 0.75rem; padding-left: calc(var(--grvsc-padding-left, var(--grvsc-padding-h, 1.5rem)) / 2); } /* Line transformer styles */ .grvsc-has-line-highlighting > .grvsc-code > .grvsc-line::before { content: ' '; position: absolute; width: 100%; } .grvsc-line-diff-add::before { background-color: var(--grvsc-line-diff-add-background-color, rgba(0, 255, 60, 0.2)); } .grvsc-line-diff-del::before { background-color: var(--grvsc-line-diff-del-background-color, rgba(255, 0, 20, 0.2)); } .grvsc-line-number { padding: 0 2px; text-align: right; opacity: 0.7; } .default-dark { background-color: #1E1E1E; color: #D4D4D4; } .default-dark .mtk15 { color: #C586C0; } .default-dark .mtk1 { color: #D4D4D4; } .default-dark .mtk12 { color: #9CDCFE; } .default-dark .mtk8 { color: #CE9178; } .default-dark .mtk4 { color: #569CD6; } .default-dark .mtk11 { color: #DCDCAA; } .default-dark .mtk17 { color: #808080; } .default-dark .mtk10 { color: #4EC9B0; } .default-dark .mtk7 { color: #B5CEA8; } .default-dark .grvsc-line-highlighted::before { background-color: var(--grvsc-line-highlighted-background-color, rgba(255, 255, 255, 0.1)); box-shadow: inset var(--grvsc-line-highlighted-border-width, 4px) 0 0 0 var(--grvsc-line-highlighted-border-color, rgba(255, 255, 255, 0.5)); } </style><![CDATA[How to Create Custom v-model for Web Components]]>https://muhimasri.comhow-to-create-custom-v-model-for-web-componentshttps://muhimasri.comhow-to-create-custom-v-model-for-web-components<p>I wrote in a previous article the importance of Web Components and how to make them <a href="https://muhimasri.com/blogs/web-components-with-react-hooks/">work with React</a>. Today, I’m focusing on a Vue example with a Web Component input element.</p> <p>Fortunately, Vue fully supports Web Components according to <a href="https://custom-elements-everywhere.com/">custom-elements-everywhere.com</a> but I faced a small inconvenience while using v-model directive with an input element.</p> <p>V-model is a built-in directive in Vue that makes data binding easier with less code.</p> <p>The code below:</p> <pre class="grvsc-container default-dark" data-language="html" data-index="0"><code class="grvsc-code"><span class="grvsc-line"><span class="grvsc-source"><span class="mtk17">&lt;</span><span class="mtk4">input</span><span class="mtk1"> </span><span class="mtk12">v-model</span><span class="mtk1">=</span><span class="mtk8">&quot;searchText&quot;</span><span class="mtk17">&gt;</span></span></span></code></pre> <p>Is the same as:</p> <pre class="grvsc-container default-dark" data-language="html" data-index="1"><code class="grvsc-code"><span class="grvsc-line"><span class="grvsc-source"><span class="mtk17">&lt;</span><span class="mtk4">input</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">:value</span><span class="mtk1">=</span><span class="mtk8">&quot;searchText&quot;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">@input</span><span class="mtk1">=</span><span class="mtk8">&quot;searchText = $event.target.value&quot;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk17">&gt;</span></span></span></code></pre> <p>Currently, we can’t use v-model in a Web Component but we can create our own custom directive to make it behave the same way across all custom elements!</p> <p>For simplicity purposes, I’m using <a href="https://wiredjs.com/">Wired Elements</a> for the Web Components example. Wired Elements are a set of common UI elements with a hand-drawn, sketchy look. The library uses <a href="https://lit-element.polymer-project.org/">LitElement</a> for creating Web Components.</p> <h2 id="create-vue-app" style="position:relative;"><a href="#create-vue-app" aria-label="create vue app permalink" class="anchor before"><svg aria-hidden="true" focusable="false" height="16" version="1.1" viewBox="0 0 16 16" width="16"><path fill-rule="evenodd" d="M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z"></path></svg></a>Create Vue App</h2> <p>Install <a href="https://cli.vuejs.org/">Vue CLI</a> and create a new project.</p> <pre class="grvsc-container default-dark" data-language="" data-index="2"><code class="grvsc-code"><span class="grvsc-line"><span class="grvsc-source">npm install -g @vue/cli @vue/cli-service-global</span></span> <span class="grvsc-line"><span class="grvsc-source">vue create vue-custom-v-model-example</span></span></code></pre> <h2 id="install-wired-elements" style="position:relative;"><a href="#install-wired-elements" aria-label="install wired elements permalink" class="anchor before"><svg aria-hidden="true" focusable="false" height="16" version="1.1" viewBox="0 0 16 16" width="16"><path fill-rule="evenodd" d="M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z"></path></svg></a>Install Wired Elements</h2> <p>Full documentation on Wired Elements is available on their main <a href="https://github.com/rough-stuff/wired-elements">repository</a></p> <pre class="grvsc-container default-dark" data-language="" data-index="3"><code class="grvsc-code"><span class="grvsc-line"><span class="grvsc-source">npm i wired-elements</span></span></code></pre> <h2 id="import-input-element" style="position:relative;"><a href="#import-input-element" aria-label="import input element permalink" class="anchor before"><svg aria-hidden="true" focusable="false" height="16" version="1.1" viewBox="0 0 16 16" width="16"><path fill-rule="evenodd" d="M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z"></path></svg></a>Import Input Element:</h2> <p>In this section, we will add a Wired Input Element and show how the v-model won’t work the way it usually does with the native input element.</p> <pre class="grvsc-container default-dark" data-language="html" data-index="4"><code class="grvsc-code"><span class="grvsc-line"><span class="grvsc-source"><span class="mtk17">&lt;</span><span class="mtk4">template</span><span class="mtk17">&gt;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk17">&lt;</span><span class="mtk4">article</span><span class="mtk17">&gt;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk17">&lt;</span><span class="mtk4">wired-input</span><span class="mtk1"> </span><span class="mtk12">v-model</span><span class="mtk1">=</span><span class="mtk8">&quot;txtValue&quot;</span><span class="mtk17">&gt;&lt;/</span><span class="mtk4">wired-input</span><span class="mtk17">&gt;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> {{txtValue}}</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk17">&lt;/</span><span class="mtk4">article</span><span class="mtk17">&gt;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk17">&lt;/</span><span class="mtk4">template</span><span class="mtk17">&gt;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk17">&lt;</span><span class="mtk4">script</span><span class="mtk17">&gt;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk15">import</span><span class="mtk1"> </span><span class="mtk8">&#39;wired-input&#39;</span><span class="mtk1">;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk15">export</span><span class="mtk1"> </span><span class="mtk15">default</span><span class="mtk1"> {</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">name:</span><span class="mtk1"> </span><span class="mtk8">&#39;App&#39;</span><span class="mtk1">,</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">components:</span><span class="mtk1"> {</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> },</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk11">data</span><span class="mtk1">() {</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk15">return</span><span class="mtk1"> {</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">txtValue:</span><span class="mtk1"> </span><span class="mtk8">&#39;&#39;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> }</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> }</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1">}</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk17">&lt;/</span><span class="mtk4">script</span><span class="mtk17">&gt;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk17">&lt;</span><span class="mtk4">style</span><span class="mtk17">&gt;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk6">#app</span><span class="mtk1"> {</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">text-align</span><span class="mtk1">: </span><span class="mtk8">center</span><span class="mtk1">;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">color</span><span class="mtk1">: </span><span class="mtk8">#2c3e50</span><span class="mtk1">;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">margin-top</span><span class="mtk1">: </span><span class="mtk7">60px</span><span class="mtk1">;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1">}</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk17">&lt;/</span><span class="mtk4">style</span><span class="mtk17">&gt;</span></span></span></code></pre> <p>Quick summary of the code above:</p> <ul> <li>Imported <code>wired-input</code></li> <li>Created a new <code>txtValue</code> data to use in v-model</li> <li>Print out the <code>txtValue</code> on the screen as we are typing</li> </ul> <p>Now as expected, when typing, nothing is printed:</p> <p><img src="/06087100fabf6af78a3b6e1ed525f7f1/ezgif.com-gif-maker-1.gif" alt=""></p> <h2 id="create-a-custom-directive" style="position:relative;"><a href="#create-a-custom-directive" aria-label="create a custom directive permalink" class="anchor before"><svg aria-hidden="true" focusable="false" height="16" version="1.1" viewBox="0 0 16 16" width="16"><path fill-rule="evenodd" d="M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z"></path></svg></a>Create a custom directive</h2> <p>Let’s create a new directive and call it <code>custom-model.js</code>. The directive will listen to the input event and update the binding value.</p> <pre class="grvsc-container default-dark" data-language="javascript" data-index="5"><code class="grvsc-code"><span class="grvsc-line"><span class="grvsc-source"><span class="mtk15">import</span><span class="mtk1"> </span><span class="mtk12">Vue</span><span class="mtk1"> </span><span class="mtk15">from</span><span class="mtk1"> </span><span class="mtk8">&quot;vue&quot;</span><span class="mtk1">;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk12">Vue</span><span class="mtk1">.</span><span class="mtk11">directive</span><span class="mtk1">(</span><span class="mtk8">&quot;custom-model&quot;</span><span class="mtk1">, {</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk11">bind</span><span class="mtk1">(</span><span class="mtk12">el</span><span class="mtk1">, </span><span class="mtk12">binding</span><span class="mtk1">, </span><span class="mtk12">vnode</span><span class="mtk1">) {</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk4">const</span><span class="mtk1"> </span><span class="mtk11">inputHandler</span><span class="mtk1"> = (</span><span class="mtk12">event</span><span class="mtk1">) </span><span class="mtk4">=&gt;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> (</span><span class="mtk12">vnode</span><span class="mtk1">.</span><span class="mtk12">context</span><span class="mtk1">.</span><span class="mtk12">$data</span><span class="mtk1">[</span><span class="mtk12">binding</span><span class="mtk1">.</span><span class="mtk12">expression</span><span class="mtk1">] = </span><span class="mtk12">event</span><span class="mtk1">.</span><span class="mtk12">target</span><span class="mtk1">.</span><span class="mtk12">value</span><span class="mtk1">);</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">el</span><span class="mtk1">.</span><span class="mtk11">addEventListener</span><span class="mtk1">(</span><span class="mtk8">&quot;input&quot;</span><span class="mtk1">, </span><span class="mtk12">inputHandler</span><span class="mtk1">);</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> },</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1">});</span></span></span></code></pre> <p>Here are some details of what we did in the code above:</p> <ul> <li>In line 4, we are using the <code>bind</code> hook function (when the directive is first bound to the element)</li> <li>In line 6, we are accessing the context data from <code>vnode</code> object to update the binding value in the <code>inputHandler</code> function.</li> <li>Line 7, simply add an event listener to the element</li> </ul> <h2 id="test-input-element-with-the-custom-directive" style="position:relative;"><a href="#test-input-element-with-the-custom-directive" aria-label="test input element with the custom directive permalink" class="anchor before"><svg aria-hidden="true" focusable="false" height="16" version="1.1" viewBox="0 0 16 16" width="16"><path fill-rule="evenodd" d="M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z"></path></svg></a>Test input element with the custom directive</h2> <p>Now that we have the directive ready, let’s apply it to the web component.</p> <p>First, let’s update <code>App.vue</code> to use the new directive:</p> <pre class="grvsc-container default-dark" data-language="html" data-index="6"><code class="grvsc-code"><span class="grvsc-line"><span class="grvsc-source"><span class="mtk17">&lt;</span><span class="mtk4">template</span><span class="mtk17">&gt;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk17">&lt;</span><span class="mtk4">div</span><span class="mtk1"> </span><span class="mtk12">id</span><span class="mtk1">=</span><span class="mtk8">&quot;app&quot;</span><span class="mtk17">&gt;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk17">&lt;</span><span class="mtk4">wired-input</span><span class="mtk1"> </span><span class="mtk12">v-custom-model</span><span class="mtk1">=</span><span class="mtk8">&quot;txtValue&quot;</span><span class="mtk1"> </span><span class="mtk17">/&gt;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> {{txtValue}}</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk17">&lt;/</span><span class="mtk4">div</span><span class="mtk17">&gt;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk17">&lt;/</span><span class="mtk4">template</span><span class="mtk17">&gt;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk17">&lt;</span><span class="mtk4">script</span><span class="mtk17">&gt;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk15">import</span><span class="mtk1"> </span><span class="mtk8">&#39;wired-input&#39;</span><span class="mtk1">;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk15">import</span><span class="mtk1"> </span><span class="mtk12">CustomModelDirective</span><span class="mtk1"> </span><span class="mtk15">from</span><span class="mtk1"> </span><span class="mtk8">&#39;./directives/custom-model&#39;</span><span class="mtk1">;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk15">export</span><span class="mtk1"> </span><span class="mtk15">default</span><span class="mtk1"> {</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">name:</span><span class="mtk1"> </span><span class="mtk8">&#39;App&#39;</span><span class="mtk1">,</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">components:</span><span class="mtk1"> {</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> },</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk11">data</span><span class="mtk1">() {</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk15">return</span><span class="mtk1"> {</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">txtValue:</span><span class="mtk1"> </span><span class="mtk8">&#39;&#39;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> }</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> },</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">directives:</span><span class="mtk1"> {</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">CustomModelDirective</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> }</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1">}</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk17">&lt;/</span><span class="mtk4">script</span><span class="mtk17">&gt;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk17">&lt;</span><span class="mtk4">style</span><span class="mtk17">&gt;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk6">#app</span><span class="mtk1"> {</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">text-align</span><span class="mtk1">: </span><span class="mtk8">center</span><span class="mtk1">;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">color</span><span class="mtk1">: </span><span class="mtk8">#2c3e50</span><span class="mtk1">;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">margin-top</span><span class="mtk1">: </span><span class="mtk7">60px</span><span class="mtk1">;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1">}</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk17">&lt;/</span><span class="mtk4">style</span><span class="mtk17">&gt;</span></span></span></code></pre> <p>Here is a demonstration of the final working code:</p> <p><img src="/fb35ed484ae3256ebd502e7a867d9ef5/ezgif.com-gif-maker-3.gif" alt=""></p> <p>You can access the <a href="https://github.com/muhimasri/vue-custom-v-model-example">complete repository here</a>.</p> <p>Bye for now 👋</p> <style class="grvsc-styles"> .grvsc-container { overflow: auto; position: relative; -webkit-overflow-scrolling: touch; padding-top: 1rem; padding-top: var(--grvsc-padding-top, var(--grvsc-padding-v, 1rem)); padding-bottom: 1rem; padding-bottom: var(--grvsc-padding-bottom, var(--grvsc-padding-v, 1rem)); border-radius: 8px; border-radius: var(--grvsc-border-radius, 8px); font-feature-settings: normal; line-height: 1.4; } .grvsc-code { display: table; } .grvsc-line { display: table-row; box-sizing: border-box; width: 100%; position: relative; } .grvsc-line > * { position: relative; } .grvsc-gutter-pad { display: table-cell; padding-left: 0.75rem; padding-left: calc(var(--grvsc-padding-left, var(--grvsc-padding-h, 1.5rem)) / 2); } .grvsc-gutter { display: table-cell; -webkit-user-select: none; -moz-user-select: none; user-select: none; } .grvsc-gutter::before { content: attr(data-content); } .grvsc-source { display: table-cell; padding-left: 1.5rem; padding-left: var(--grvsc-padding-left, var(--grvsc-padding-h, 1.5rem)); padding-right: 1.5rem; padding-right: var(--grvsc-padding-right, var(--grvsc-padding-h, 1.5rem)); } .grvsc-source:empty::after { content: ' '; -webkit-user-select: none; -moz-user-select: none; user-select: none; } .grvsc-gutter + .grvsc-source { padding-left: 0.75rem; padding-left: calc(var(--grvsc-padding-left, var(--grvsc-padding-h, 1.5rem)) / 2); } /* Line transformer styles */ .grvsc-has-line-highlighting > .grvsc-code > .grvsc-line::before { content: ' '; position: absolute; width: 100%; } .grvsc-line-diff-add::before { background-color: var(--grvsc-line-diff-add-background-color, rgba(0, 255, 60, 0.2)); } .grvsc-line-diff-del::before { background-color: var(--grvsc-line-diff-del-background-color, rgba(255, 0, 20, 0.2)); } .grvsc-line-number { padding: 0 2px; text-align: right; opacity: 0.7; } .default-dark { background-color: #1E1E1E; color: #D4D4D4; } .default-dark .mtk17 { color: #808080; } .default-dark .mtk4 { color: #569CD6; } .default-dark .mtk1 { color: #D4D4D4; } .default-dark .mtk12 { color: #9CDCFE; } .default-dark .mtk8 { color: #CE9178; } .default-dark .mtk15 { color: #C586C0; } .default-dark .mtk11 { color: #DCDCAA; } .default-dark .mtk6 { color: #D7BA7D; } .default-dark .mtk7 { color: #B5CEA8; } .default-dark .grvsc-line-highlighted::before { background-color: var(--grvsc-line-highlighted-background-color, rgba(255, 255, 255, 0.1)); box-shadow: inset var(--grvsc-line-highlighted-border-width, 4px) 0 0 0 var(--grvsc-line-highlighted-border-color, rgba(255, 255, 255, 0.5)); } </style><![CDATA[Web Components with React Hooks]]>https://muhimasri.comweb-components-with-react-hookshttps://muhimasri.comweb-components-with-react-hooks<p>Web Components are of great use when it comes to creating a future proof component-based design system that can be interoperable and shared across multiple products.</p> <p>Unfortunately, React is one of the few modern libraries that does not have full support to Web Components, especially when it comes to handling events. The reason is that React implements its own synthetic event system, it cannot listen for DOM events coming from Web Components.</p> <p>The great news is that you don’t need to rewrite all your design system from scratch using React. There is a simple workaround that requires creating thin wrappers and subscribing to DOM events.</p> <p>In this example, I’m using <a href="https://wiredjs.com/">Wired Elements</a> to make an input Web Component work with React. Wired Elements are a set of common UI elements with a hand-drawn, sketchy look. The library uses <a href="https://lit-element.polymer-project.org/">LitElement</a> for creating Web Components.</p> <p>Also, in this article, I’m solving specifically the problem with capturing DOM events through a React component wrapper. Please refer to <a href="https://custom-elements-everywhere.com/">custom-elements-everywhere.com</a> if you want to look at all open issues regarding React and Web Components support.</p> <h2 id="create-react-app" style="position:relative;"><a href="#create-react-app" aria-label="create react app permalink" class="anchor before"><svg aria-hidden="true" focusable="false" height="16" version="1.1" viewBox="0 0 16 16" width="16"><path fill-rule="evenodd" d="M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z"></path></svg></a>Create React App</h2> <p>Create a new <a href="https://create-react-app.dev/docs/getting-started/">React App</a>.</p> <pre class="grvsc-container default-dark" data-language="" data-index="0"><code class="grvsc-code"><span class="grvsc-line"><span class="grvsc-source">npx create-react-app react-webcomponent</span></span></code></pre> <h2 id="install-wired-elements" style="position:relative;"><a href="#install-wired-elements" aria-label="install wired elements permalink" class="anchor before"><svg aria-hidden="true" focusable="false" height="16" version="1.1" viewBox="0 0 16 16" width="16"><path fill-rule="evenodd" d="M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z"></path></svg></a>Install Wired Elements</h2> <p>Full documentation on Wired Elements is available on their main <a href="https://github.com/rough-stuff/wired-elements">repository</a></p> <pre class="grvsc-container default-dark" data-language="" data-index="1"><code class="grvsc-code"><span class="grvsc-line"><span class="grvsc-source">npm i wired-elements</span></span></code></pre> <h2 id="import-wired-input-element" style="position:relative;"><a href="#import-wired-input-element" aria-label="import wired input element permalink" class="anchor before"><svg aria-hidden="true" focusable="false" height="16" version="1.1" viewBox="0 0 16 16" width="16"><path fill-rule="evenodd" d="M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z"></path></svg></a>Import Wired Input Element</h2> <p>In this section, we will add a Wired Input Element without a wrapper and show how the <code>onChange</code> event will not be triggered as React does not detect DOM events.</p> <pre class="grvsc-container default-dark" data-language="jsx" data-index="2"><code class="grvsc-code"><span class="grvsc-line"><span class="grvsc-source"><span class="mtk15">import</span><span class="mtk1"> </span><span class="mtk8">&#39;./App.css&#39;</span><span class="mtk1">;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk15">import</span><span class="mtk1"> </span><span class="mtk8">&#39;wired-elements&#39;</span><span class="mtk1">;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk4">function</span><span class="mtk1"> </span><span class="mtk11">App</span><span class="mtk1">() {</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk4">function</span><span class="mtk1"> </span><span class="mtk11">handleInput</span><span class="mtk1">(</span><span class="mtk12">e</span><span class="mtk1">) {</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk10">console</span><span class="mtk1">.</span><span class="mtk11">log</span><span class="mtk1">(</span><span class="mtk12">e</span><span class="mtk1">.</span><span class="mtk12">target</span><span class="mtk1">.</span><span class="mtk12">value</span><span class="mtk1">);</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> }</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk15">return</span><span class="mtk1"> (</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk17">&lt;</span><span class="mtk4">div</span><span class="mtk1"> </span><span class="mtk12">className</span><span class="mtk1">=</span><span class="mtk8">&quot;App&quot;</span><span class="mtk17">&gt;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk17">&lt;</span><span class="mtk10">wired-input</span><span class="mtk1"> </span><span class="mtk12">onChange</span><span class="mtk1">=</span><span class="mtk4">{</span><span class="mtk12">handleInput</span><span class="mtk4">}</span><span class="mtk17">&gt;&lt;/</span><span class="mtk10">wired-input</span><span class="mtk17">&gt;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk17">&lt;/</span><span class="mtk4">div</span><span class="mtk17">&gt;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> );</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1">}</span></span></span> <span class="grvsc-line"><span class="grvsc-source"></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk15">export</span><span class="mtk1"> </span><span class="mtk15">default</span><span class="mtk1"> </span><span class="mtk12">App</span><span class="mtk1">;</span></span></span></code></pre> <p>Quick summary of the code above:</p> <ul> <li>Reused <code>App.js</code> file and cleaned up unused code</li> <li>Imported <code>wired-elements</code></li> <li>Added <code>&#x3C;wired-input></code> to the template</li> <li>Created a handle input function to print the value being typed when <code>onChange</code> is triggered</li> </ul> <p>Now as expected, when typing, the console doesn’t print anything:</p> <p><img src="/a0031ffdbeb3da0641a02a3aa4fc0838/no-value.gif" alt=""></p> <h2 id="create-a-component-wrapper" style="position:relative;"><a href="#create-a-component-wrapper" aria-label="create a component wrapper permalink" class="anchor before"><svg aria-hidden="true" focusable="false" height="16" version="1.1" viewBox="0 0 16 16" width="16"><path fill-rule="evenodd" d="M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z"></path></svg></a>Create a component wrapper</h2> <p>Let’s add a new react component and call it <code>WiredInput.js</code>. It will subscribe to the input event and call <code>onChange</code> function from the component props</p> <pre class="grvsc-container default-dark" data-language="jsx" data-index="3"><code class="grvsc-code"><span class="grvsc-line"><span class="grvsc-source"><span class="mtk15">import</span><span class="mtk1"> { </span><span class="mtk12">createRef</span><span class="mtk1">, </span><span class="mtk12">useEffect</span><span class="mtk1"> } </span><span class="mtk15">from</span><span class="mtk1"> </span><span class="mtk8">&quot;react&quot;</span><span class="mtk1">;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk15">import</span><span class="mtk1"> </span><span class="mtk8">&quot;wired-elements&quot;</span><span class="mtk1">;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk4">function</span><span class="mtk1"> </span><span class="mtk11">WiredInput</span><span class="mtk1">({ </span><span class="mtk12">onChange</span><span class="mtk1"> }) {</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk4">const</span><span class="mtk1"> </span><span class="mtk12">inputRef</span><span class="mtk1"> = </span><span class="mtk11">createRef</span><span class="mtk1">();</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk11">useEffect</span><span class="mtk1">(() </span><span class="mtk4">=&gt;</span><span class="mtk1"> {</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">inputRef</span><span class="mtk1">.</span><span class="mtk12">current</span><span class="mtk1">.</span><span class="mtk11">addEventListener</span><span class="mtk1">(</span><span class="mtk8">&quot;input&quot;</span><span class="mtk1">, (</span><span class="mtk12">e</span><span class="mtk1">) </span><span class="mtk4">=&gt;</span><span class="mtk1"> {</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk15">if</span><span class="mtk1"> (</span><span class="mtk12">onChange</span><span class="mtk1">) {</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk11">onChange</span><span class="mtk1">(</span><span class="mtk12">e</span><span class="mtk1">);</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> }</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> });</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> }, [</span><span class="mtk12">inputRef</span><span class="mtk1">, </span><span class="mtk12">onChange</span><span class="mtk1">]);</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk15">return</span><span class="mtk1"> </span><span class="mtk17">&lt;</span><span class="mtk10">wired-input</span><span class="mtk1"> </span><span class="mtk12">ref</span><span class="mtk1">=</span><span class="mtk4">{</span><span class="mtk12">inputRef</span><span class="mtk4">}</span><span class="mtk17">&gt;&lt;/</span><span class="mtk10">wired-input</span><span class="mtk17">&gt;</span><span class="mtk1">;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1">}</span></span></span> <span class="grvsc-line"><span class="grvsc-source"></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk15">export</span><span class="mtk1"> </span><span class="mtk15">default</span><span class="mtk1"> </span><span class="mtk12">WiredInput</span><span class="mtk1">;</span></span></span></code></pre> <p>Here are some details of what we did in the code above:</p> <ul> <li>In line 5, created a reference to the <wired-input> element using <code>createRef</code> and named it <code>inputRef</code></li> <li>In line 6, added a <code>useEffect</code> function to be triggered when the DOM is ready (this way we ensure <code>inputRef</code> is not empty)</li> <li>Line 7, subscribe to the input event</li> <li>Line 8, checking if <code>onChange</code> is not undefined then call the function and pass it the event</li> <li>Line 13, added the wired input element with <code>inputRef</code></li> </ul> <h2 id="test-input-change-event" style="position:relative;"><a href="#test-input-change-event" aria-label="test input change event permalink" class="anchor before"><svg aria-hidden="true" focusable="false" height="16" version="1.1" viewBox="0 0 16 16" width="16"><path fill-rule="evenodd" d="M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z"></path></svg></a>Test input change event</h2> <p>Now that we have the wrapper component ready, let’s put it into action!</p> <p>First, let’s update app.js to use the new component:</p> <pre class="grvsc-container default-dark" data-language="jsx" data-index="4"><code class="grvsc-code"><span class="grvsc-line"><span class="grvsc-source"><span class="mtk15">import</span><span class="mtk1"> </span><span class="mtk8">&#39;./App.css&#39;</span><span class="mtk1">;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk15">import</span><span class="mtk1"> </span><span class="mtk12">WiredInput</span><span class="mtk1"> </span><span class="mtk15">from</span><span class="mtk1"> </span><span class="mtk8">&#39;./WiredInput&#39;</span><span class="mtk1">;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk4">function</span><span class="mtk1"> </span><span class="mtk11">App</span><span class="mtk1">() {</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk4">function</span><span class="mtk1"> </span><span class="mtk11">handleInput</span><span class="mtk1">(</span><span class="mtk12">e</span><span class="mtk1">) {</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk10">console</span><span class="mtk1">.</span><span class="mtk11">log</span><span class="mtk1">(</span><span class="mtk12">e</span><span class="mtk1">.</span><span class="mtk12">target</span><span class="mtk1">.</span><span class="mtk12">value</span><span class="mtk1">);</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> }</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk15">return</span><span class="mtk1"> (</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk17">&lt;</span><span class="mtk4">div</span><span class="mtk1"> </span><span class="mtk12">className</span><span class="mtk1">=</span><span class="mtk8">&quot;App&quot;</span><span class="mtk17">&gt;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk17">&lt;</span><span class="mtk10">WiredInput</span><span class="mtk1"> </span><span class="mtk12">onChange</span><span class="mtk1">=</span><span class="mtk4">{</span><span class="mtk12">handleInput</span><span class="mtk4">}</span><span class="mtk17">&gt;&lt;/</span><span class="mtk10">WiredInput</span><span class="mtk17">&gt;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk17">&lt;/</span><span class="mtk4">div</span><span class="mtk17">&gt;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> );</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1">}</span></span></span> <span class="grvsc-line"><span class="grvsc-source"></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk15">export</span><span class="mtk1"> </span><span class="mtk15">default</span><span class="mtk1"> </span><span class="mtk12">App</span><span class="mtk1">;</span></span></span></code></pre> <p>Here is a demonstration of our final working code:</p> <p><img src="/69bfca75e4b186c39993c985baff152a/with-value.gif" alt=""></p> <p>You can access the <a href="https://github.com/muhimasri/react-webcomponent-example">complete repository here</a>.</p> <p>Bye for now 👋</p> <style class="grvsc-styles"> .grvsc-container { overflow: auto; position: relative; -webkit-overflow-scrolling: touch; padding-top: 1rem; padding-top: var(--grvsc-padding-top, var(--grvsc-padding-v, 1rem)); padding-bottom: 1rem; padding-bottom: var(--grvsc-padding-bottom, var(--grvsc-padding-v, 1rem)); border-radius: 8px; border-radius: var(--grvsc-border-radius, 8px); font-feature-settings: normal; line-height: 1.4; } .grvsc-code { display: table; } .grvsc-line { display: table-row; box-sizing: border-box; width: 100%; position: relative; } .grvsc-line > * { position: relative; } .grvsc-gutter-pad { display: table-cell; padding-left: 0.75rem; padding-left: calc(var(--grvsc-padding-left, var(--grvsc-padding-h, 1.5rem)) / 2); } .grvsc-gutter { display: table-cell; -webkit-user-select: none; -moz-user-select: none; user-select: none; } .grvsc-gutter::before { content: attr(data-content); } .grvsc-source { display: table-cell; padding-left: 1.5rem; padding-left: var(--grvsc-padding-left, var(--grvsc-padding-h, 1.5rem)); padding-right: 1.5rem; padding-right: var(--grvsc-padding-right, var(--grvsc-padding-h, 1.5rem)); } .grvsc-source:empty::after { content: ' '; -webkit-user-select: none; -moz-user-select: none; user-select: none; } .grvsc-gutter + .grvsc-source { padding-left: 0.75rem; padding-left: calc(var(--grvsc-padding-left, var(--grvsc-padding-h, 1.5rem)) / 2); } /* Line transformer styles */ .grvsc-has-line-highlighting > .grvsc-code > .grvsc-line::before { content: ' '; position: absolute; width: 100%; } .grvsc-line-diff-add::before { background-color: var(--grvsc-line-diff-add-background-color, rgba(0, 255, 60, 0.2)); } .grvsc-line-diff-del::before { background-color: var(--grvsc-line-diff-del-background-color, rgba(255, 0, 20, 0.2)); } .grvsc-line-number { padding: 0 2px; text-align: right; opacity: 0.7; } .default-dark { background-color: #1E1E1E; color: #D4D4D4; } .default-dark .mtk15 { color: #C586C0; } .default-dark .mtk1 { color: #D4D4D4; } .default-dark .mtk8 { color: #CE9178; } .default-dark .mtk4 { color: #569CD6; } .default-dark .mtk11 { color: #DCDCAA; } .default-dark .mtk12 { color: #9CDCFE; } .default-dark .mtk10 { color: #4EC9B0; } .default-dark .mtk17 { color: #808080; } .default-dark .grvsc-line-highlighted::before { background-color: var(--grvsc-line-highlighted-background-color, rgba(255, 255, 255, 0.1)); box-shadow: inset var(--grvsc-line-highlighted-border-width, 4px) 0 0 0 var(--grvsc-line-highlighted-border-color, rgba(255, 255, 255, 0.5)); } </style><![CDATA[[Part 1] Create an Editable Dynamic Table using Angular Material]]>https://muhimasri.comcreate-an-editable-dynamic-table-using-angular-materialhttps://muhimasri.comcreate-an-editable-dynamic-table-using-angular-material<p>This series focuses on implementing new features to the Angular Material table component that enable users to add, edit and delete data with dynamic and flexible schema.</p> <p>This part will explain a simple approach to creating a dynamic editable table where users can read and modify fields.</p> <p>The aim is to provide the data source with the columns schema, and the table can adapt accordingly. For example, if one of the column types changed from a <code>number</code> to a <code>date</code> type, the table will respond dynamically and populate a <code>date</code> input field instead of a <code>number</code> field.</p> <p>Let’s take a basic scenario:</p> <ul> <li>Data source:</li> </ul> <pre class="grvsc-container default-dark" data-language="json" data-index="0"><code class="grvsc-code"><span class="grvsc-line"><span class="grvsc-source"><span class="mtk1">[</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> {</span><span class="mtk12">&quot;name&quot;</span><span class="mtk1">: </span><span class="mtk8">&quot;John Smith&quot;</span><span class="mtk1">, </span><span class="mtk12">&quot;occupation&quot;</span><span class="mtk1">: </span><span class="mtk8">&quot;Advisor&quot;</span><span class="mtk1">, </span><span class="mtk12">&quot;age&quot;</span><span class="mtk1">: </span><span class="mtk7">36</span><span class="mtk1">},</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> {</span><span class="mtk12">&quot;name&quot;</span><span class="mtk1">: </span><span class="mtk8">&quot;Muhi Masri&quot;</span><span class="mtk1">, </span><span class="mtk12">&quot;occupation&quot;</span><span class="mtk1">: </span><span class="mtk8">&quot;Developer&quot;</span><span class="mtk1">, </span><span class="mtk12">&quot;age&quot;</span><span class="mtk1">: </span><span class="mtk7">28</span><span class="mtk1">},</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> {</span><span class="mtk12">&quot;name&quot;</span><span class="mtk1">: </span><span class="mtk8">&quot;Peter Adams&quot;</span><span class="mtk1">, </span><span class="mtk12">&quot;occupation&quot;</span><span class="mtk1">: </span><span class="mtk8">&quot;HR&quot;</span><span class="mtk1">, </span><span class="mtk12">&quot;age&quot;</span><span class="mtk1">: </span><span class="mtk7">20</span><span class="mtk1">},</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> {</span><span class="mtk12">&quot;name&quot;</span><span class="mtk1">: </span><span class="mtk8">&quot;Lora Bay&quot;</span><span class="mtk1">, </span><span class="mtk12">&quot;occupation&quot;</span><span class="mtk1">: </span><span class="mtk8">&quot;Marketing&quot;</span><span class="mtk1">, </span><span class="mtk12">&quot;age&quot;</span><span class="mtk1">: </span><span class="mtk7">43</span><span class="mtk1">}</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1">]</span></span></span></code></pre> <ul> <li>Columns schema:</li> </ul> <pre class="grvsc-container default-dark" data-language="json" data-index="1"><code class="grvsc-code"><span class="grvsc-line"><span class="grvsc-source"><span class="mtk1">[</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> {</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk14">key</span><span class="mtk1">: </span><span class="mtk8">&quot;name&quot;</span><span class="mtk1">,</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk14">type</span><span class="mtk1">: </span><span class="mtk8">&quot;text&quot;</span><span class="mtk1">,</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk14">label</span><span class="mtk1">: </span><span class="mtk8">&quot;Full Name&quot;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> },</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> {</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk14">key</span><span class="mtk1">: </span><span class="mtk8">&quot;occupation&quot;</span><span class="mtk1">,</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk14">type</span><span class="mtk1">: </span><span class="mtk8">&quot;text&quot;</span><span class="mtk1">,</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk14">label</span><span class="mtk1">: </span><span class="mtk8">&quot;Occupation&quot;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> },</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> {</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk14">key</span><span class="mtk1">: </span><span class="mtk8">&quot;age&quot;</span><span class="mtk1">,</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk14">type</span><span class="mtk1">: </span><span class="mtk8">&quot;text&quot;</span><span class="mtk1">,</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk14">label</span><span class="mtk1">: </span><span class="mtk8">&quot;Age&quot;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> }</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1">]</span></span></span></code></pre> <p>When the Material table consumes the data source and columns schema, we’ll get the following results:</p> <!-- <a data-youtube="oBZuQWKRzNk" href="https://www.youtube.com/watch?v=oBZuQWKRzNk"> Watch "The Bigger Picture" by Lil Baby </a> --> <div data-youtube="oBZuQWKRzNk"> <button>Play Example</button> </div> <p>As you can see above, editing a row will change the field to a <code>text</code> input. Now let’s add a new “dateOfBirth” column with a <code>date</code> type and change the “age” column to a <code>number</code> type:</p> <pre class="grvsc-container default-dark" data-language="json" data-index="2"><code class="grvsc-code"><span class="grvsc-line"><span class="grvsc-source"><span class="mtk1">[</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> {</span><span class="mtk12">&quot;name&quot;</span><span class="mtk1">: </span><span class="mtk8">&quot;John Smith&quot;</span><span class="mtk1">, </span><span class="mtk12">&quot;occupation&quot;</span><span class="mtk1">: </span><span class="mtk8">&quot;Advisor&quot;</span><span class="mtk1">, </span><span class="mtk12">&quot;dateOfBirth&quot;</span><span class="mtk1">: </span><span class="mtk8">&quot;1984-05-05&quot;</span><span class="mtk1">, </span><span class="mtk12">&quot;age&quot;</span><span class="mtk1">: </span><span class="mtk7">36</span><span class="mtk1">},</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> {</span><span class="mtk12">&quot;name&quot;</span><span class="mtk1">: </span><span class="mtk8">&quot;Muhi Masri&quot;</span><span class="mtk1">, </span><span class="mtk12">&quot;occupation&quot;</span><span class="mtk1">: </span><span class="mtk8">&quot;Developer&quot;</span><span class="mtk1">, </span><span class="mtk12">&quot;dateOfBirth&quot;</span><span class="mtk1">: </span><span class="mtk8">&quot;1992-02-02&quot;</span><span class="mtk1">, </span><span class="mtk12">&quot;age&quot;</span><span class="mtk1">: </span><span class="mtk7">28</span><span class="mtk1">},</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> {</span><span class="mtk12">&quot;name&quot;</span><span class="mtk1">: </span><span class="mtk8">&quot;Peter Adams&quot;</span><span class="mtk1">, </span><span class="mtk12">&quot;occupation&quot;</span><span class="mtk1">: </span><span class="mtk8">&quot;HR&quot;</span><span class="mtk1">, </span><span class="mtk12">&quot;dateOfBirth&quot;</span><span class="mtk1">: </span><span class="mtk8">&quot;2000-01-01&quot;</span><span class="mtk1">, </span><span class="mtk12">&quot;age&quot;</span><span class="mtk1">: </span><span class="mtk7">20</span><span class="mtk1">},</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> {</span><span class="mtk12">&quot;name&quot;</span><span class="mtk1">: </span><span class="mtk8">&quot;Lora Bay&quot;</span><span class="mtk1">, </span><span class="mtk12">&quot;occupation&quot;</span><span class="mtk1">: </span><span class="mtk8">&quot;Marketing&quot;</span><span class="mtk1">, </span><span class="mtk12">&quot;dateOfBirth&quot;</span><span class="mtk1">: </span><span class="mtk8">&quot;1977-03-03&quot;</span><span class="mtk1">, </span><span class="mtk12">&quot;age&quot;</span><span class="mtk1">: </span><span class="mtk7">43</span><span class="mtk1">},</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1">]</span></span></span></code></pre> <pre class="grvsc-container grvsc-has-line-highlighting default-dark" data-language="json" data-index="3"><code class="grvsc-code"><span class="grvsc-line"><span class="grvsc-source"><span class="mtk1">[</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> {</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk14">key</span><span class="mtk1">: </span><span class="mtk8">&quot;name&quot;</span><span class="mtk1">,</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk14">type</span><span class="mtk1">: </span><span class="mtk8">&quot;text&quot;</span><span class="mtk1">,</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk14">label</span><span class="mtk1">: </span><span class="mtk8">&quot;Full Name&quot;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> },</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> {</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk14">key</span><span class="mtk1">: </span><span class="mtk8">&quot;occupation&quot;</span><span class="mtk1">,</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk14">type</span><span class="mtk1">: </span><span class="mtk8">&quot;text&quot;</span><span class="mtk1">,</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk14">label</span><span class="mtk1">: </span><span class="mtk8">&quot;Occupation&quot;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> },</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> {</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk14">key</span><span class="mtk1">: </span><span class="mtk8">&quot;dateOfBirth&quot;</span><span class="mtk1">,</span></span></span> <span class="grvsc-line grvsc-line-highlighted"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk14">type</span><span class="mtk1">: </span><span class="mtk8">&quot;date&quot;</span><span class="mtk1">,</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk14">label</span><span class="mtk1">: </span><span class="mtk8">&quot;Date of Birth&quot;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> },</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> {</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk14">key</span><span class="mtk1">: </span><span class="mtk8">&quot;age&quot;</span><span class="mtk1">,</span></span></span> <span class="grvsc-line grvsc-line-highlighted"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk14">type</span><span class="mtk1">: </span><span class="mtk8">&quot;number&quot;</span><span class="mtk1">,</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk14">label</span><span class="mtk1">: </span><span class="mtk8">&quot;Age&quot;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> }</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1">]</span></span></span></code></pre> <p>The table should now update and behave as follows:</p> <div data-youtube="v852YYzYe9s"> <button>Play Example</button> </div> <p>As demonstrated above, and without any changes to the code, the same table was able to dynamically display the proper input field type based on the schema provided.</p> <p>Before we begin, the <a href="https://github.com/muhimasri/angular-editable-table">complete repository is accessible here</a> and a working example is available below:</p> <div data-stackblitz="angular-editable-table-part-1"> <button>Run Code</button> </div> <h2 id="setup-an-angular-app-with-material-ui" style="position:relative;"><a href="#setup-an-angular-app-with-material-ui" aria-label="setup an angular app with material ui permalink" class="anchor before"><svg aria-hidden="true" focusable="false" height="16" version="1.1" viewBox="0 0 16 16" width="16"><path fill-rule="evenodd" d="M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z"></path></svg></a>Setup an Angular app with Material UI</h2> <p>Create a new Angular app using <a href="https://cli.angular.io/">Angular CLI</a> and install the latest <a href="https://material.angular.io/guide/getting-started">Angular Material</a>.</p> <pre class="grvsc-container default-dark" data-language="" data-index="4"><code class="grvsc-code"><span class="grvsc-line"><span class="grvsc-source">ng new angular-editable-table</span></span> <span class="grvsc-line"><span class="grvsc-source">ng add @angular/material</span></span></code></pre> <h2 id="create-a-basic-read-only-material-table" style="position:relative;"><a href="#create-a-basic-read-only-material-table" aria-label="create a basic read only material table permalink" class="anchor before"><svg aria-hidden="true" focusable="false" height="16" version="1.1" viewBox="0 0 16 16" width="16"><path fill-rule="evenodd" d="M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z"></path></svg></a>Create a basic read-only Material table</h2> <p>In the <code>app.component.ts</code> file, let’s add a fake <code>USER_DATA</code> array (this typically comes from the back-end via an API call):</p> <pre class="grvsc-container default-dark" data-language="typescript" data-index="5"><code class="grvsc-code"><span class="grvsc-line"><span class="grvsc-source"><span class="mtk15">import</span><span class="mtk1"> { </span><span class="mtk12">Component</span><span class="mtk1"> } </span><span class="mtk15">from</span><span class="mtk1"> </span><span class="mtk8">&#39;@angular/core&#39;</span><span class="mtk1">;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk4">const</span><span class="mtk1"> </span><span class="mtk12">USER_DATA</span><span class="mtk1"> = [</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> {</span><span class="mtk8">&quot;name&quot;</span><span class="mtk12">:</span><span class="mtk1"> </span><span class="mtk8">&quot;John Smith&quot;</span><span class="mtk1">, </span><span class="mtk8">&quot;occupation&quot;</span><span class="mtk12">:</span><span class="mtk1"> </span><span class="mtk8">&quot;Advisor&quot;</span><span class="mtk1">, </span><span class="mtk8">&quot;age&quot;</span><span class="mtk12">:</span><span class="mtk1"> </span><span class="mtk7">36</span><span class="mtk1">},</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> {</span><span class="mtk8">&quot;name&quot;</span><span class="mtk12">:</span><span class="mtk1"> </span><span class="mtk8">&quot;Muhi Masri&quot;</span><span class="mtk1">, </span><span class="mtk8">&quot;occupation&quot;</span><span class="mtk12">:</span><span class="mtk1"> </span><span class="mtk8">&quot;Developer&quot;</span><span class="mtk1">, </span><span class="mtk8">&quot;age&quot;</span><span class="mtk12">:</span><span class="mtk1"> </span><span class="mtk7">28</span><span class="mtk1">},</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> {</span><span class="mtk8">&quot;name&quot;</span><span class="mtk12">:</span><span class="mtk1"> </span><span class="mtk8">&quot;Peter Adams&quot;</span><span class="mtk1">, </span><span class="mtk8">&quot;occupation&quot;</span><span class="mtk12">:</span><span class="mtk1"> </span><span class="mtk8">&quot;HR&quot;</span><span class="mtk1">, </span><span class="mtk8">&quot;age&quot;</span><span class="mtk12">:</span><span class="mtk1"> </span><span class="mtk7">20</span><span class="mtk1">},</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> {</span><span class="mtk8">&quot;name&quot;</span><span class="mtk12">:</span><span class="mtk1"> </span><span class="mtk8">&quot;Lora Bay&quot;</span><span class="mtk1">, </span><span class="mtk8">&quot;occupation&quot;</span><span class="mtk12">:</span><span class="mtk1"> </span><span class="mtk8">&quot;Marketing&quot;</span><span class="mtk1">, </span><span class="mtk8">&quot;age&quot;</span><span class="mtk12">:</span><span class="mtk1"> </span><span class="mtk7">43</span><span class="mtk1">}</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1">];</span></span></span> <span class="grvsc-line"><span class="grvsc-source"></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1">@</span><span class="mtk11">Component</span><span class="mtk1">({</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">selector:</span><span class="mtk1"> </span><span class="mtk8">&#39;app-root&#39;</span><span class="mtk1">,</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">templateUrl:</span><span class="mtk1"> </span><span class="mtk8">&#39;./app.component.html&#39;</span><span class="mtk1">,</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">styleUrls:</span><span class="mtk1"> [</span><span class="mtk8">&#39;./app.component.scss&#39;</span><span class="mtk1">]</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1">})</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk15">export</span><span class="mtk1"> </span><span class="mtk4">class</span><span class="mtk1"> </span><span class="mtk10">AppComponent</span><span class="mtk1"> {</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">displayedColumns</span><span class="mtk1">: </span><span class="mtk10">string</span><span class="mtk1">[] = [</span><span class="mtk8">&#39;name&#39;</span><span class="mtk1">, </span><span class="mtk8">&#39;occupation&#39;</span><span class="mtk1">, </span><span class="mtk8">&#39;age&#39;</span><span class="mtk1">];</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">dataSource</span><span class="mtk1">: </span><span class="mtk10">any</span><span class="mtk1"> = </span><span class="mtk12">USER_DATA</span><span class="mtk1">;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1">}</span></span></span></code></pre> <p>Then, in the <code>app.component.html</code> file, we will add the required columns and display the list from the <code>dataSource</code> property:</p> <pre class="grvsc-container default-dark" data-language="html" data-index="6"><code class="grvsc-code"><span class="grvsc-line"><span class="grvsc-source"><span class="mtk17">&lt;</span><span class="mtk4">article</span><span class="mtk17">&gt;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk17">&lt;</span><span class="mtk4">table</span><span class="mtk1"> </span><span class="mtk12">mat-table</span><span class="mtk1"> </span><span class="mtk12">[dataSource]</span><span class="mtk1">=</span><span class="mtk8">&quot;dataSource&quot;</span><span class="mtk17">&gt;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk17">&lt;</span><span class="mtk4">ng-container</span><span class="mtk1"> </span><span class="mtk12">[matColumnDef]</span><span class="mtk1">=</span><span class="mtk8">&quot;col&quot;</span><span class="mtk1"> </span><span class="mtk12">*ngFor</span><span class="mtk1">=</span><span class="mtk8">&quot;let col of displayedColumns&quot;</span><span class="mtk17">&gt;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk17">&lt;</span><span class="mtk4">th</span><span class="mtk1"> </span><span class="mtk12">mat-header-cell</span><span class="mtk1"> </span><span class="mtk12">*matHeaderCellDef</span><span class="mtk17">&gt;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> {{col}}</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk17">&lt;/</span><span class="mtk4">th</span><span class="mtk17">&gt;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk17">&lt;</span><span class="mtk4">td</span><span class="mtk1"> </span><span class="mtk12">mat-cell</span><span class="mtk1"> </span><span class="mtk12">*matCellDef</span><span class="mtk1">=</span><span class="mtk8">&quot;let element&quot;</span><span class="mtk17">&gt;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> {{element[col]}}</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk17">&lt;/</span><span class="mtk4">td</span><span class="mtk17">&gt;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk17">&lt;/</span><span class="mtk4">ng-container</span><span class="mtk17">&gt;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk17">&lt;</span><span class="mtk4">tr</span><span class="mtk1"> </span><span class="mtk12">mat-header-row</span><span class="mtk1"> </span><span class="mtk12">*matHeaderRowDef</span><span class="mtk1">=</span><span class="mtk8">&quot;displayedColumns&quot;</span><span class="mtk17">&gt;&lt;/</span><span class="mtk4">tr</span><span class="mtk17">&gt;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk17">&lt;</span><span class="mtk4">tr</span><span class="mtk1"> </span><span class="mtk12">mat-row</span><span class="mtk1"> </span><span class="mtk12">*matRowDef</span><span class="mtk1">=</span><span class="mtk8">&quot;let row; columns: displayedColumns;&quot;</span><span class="mtk17">&gt;&lt;/</span><span class="mtk4">tr</span><span class="mtk17">&gt;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk17">&lt;/</span><span class="mtk4">table</span><span class="mtk17">&gt;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk17">&lt;/</span><span class="mtk4">article</span><span class="mtk17">&gt;</span></span></span></code></pre> <h2 id="create-a-dynamic-table-using-columns-schema" style="position:relative;"><a href="#create-a-dynamic-table-using-columns-schema" aria-label="create a dynamic table using columns schema permalink" class="anchor before"><svg aria-hidden="true" focusable="false" height="16" version="1.1" viewBox="0 0 16 16" width="16"><path fill-rule="evenodd" d="M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z"></path></svg></a>Create a dynamic table using columns schema</h2> <p>Now that the basic table is working let’s go through the steps for adding dynamic input fields based on columns schema. For now, we’re going to replace text fields with HTML input elements, but we’ll add an edit functionality to toggle between read-only and edit mode in the next section.</p> <ol> <li>Loop through the columns and display them dynamically instead of hard coding each one.</li> </ol> <pre class="grvsc-container default-dark" data-language="html" data-index="7"><code class="grvsc-code"><span class="grvsc-line"><span class="grvsc-source"><span class="mtk17">&lt;</span><span class="mtk4">article</span><span class="mtk17">&gt;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk17">&lt;</span><span class="mtk4">table</span><span class="mtk1"> </span><span class="mtk12">mat-table</span><span class="mtk1"> </span><span class="mtk12">[dataSource]</span><span class="mtk1">=</span><span class="mtk8">&quot;dataSource&quot;</span><span class="mtk17">&gt;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk17">&lt;</span><span class="mtk4">ng-container</span><span class="mtk1"> </span><span class="mtk12">[matColumnDef]</span><span class="mtk1">=</span><span class="mtk8">&quot;col&quot;</span><span class="mtk1"> </span><span class="mtk12">*ngFor</span><span class="mtk1">=</span><span class="mtk8">&quot;let col of displayedColumns&quot;</span><span class="mtk17">&gt;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk17">&lt;</span><span class="mtk4">th</span><span class="mtk1"> </span><span class="mtk12">mat-header-cell</span><span class="mtk1"> </span><span class="mtk12">*matHeaderCellDef</span><span class="mtk17">&gt;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> {{col}}</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk17">&lt;/</span><span class="mtk4">th</span><span class="mtk17">&gt;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk17">&lt;</span><span class="mtk4">td</span><span class="mtk1"> </span><span class="mtk12">mat-cell</span><span class="mtk1"> </span><span class="mtk12">*matCellDef</span><span class="mtk1">=</span><span class="mtk8">&quot;let element&quot;</span><span class="mtk17">&gt;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> {{element[col]}}</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk17">&lt;/</span><span class="mtk4">td</span><span class="mtk17">&gt;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk17">&lt;/</span><span class="mtk4">ng-container</span><span class="mtk17">&gt;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk17">&lt;</span><span class="mtk4">tr</span><span class="mtk1"> </span><span class="mtk12">mat-header-row</span><span class="mtk1"> </span><span class="mtk12">*matHeaderRowDef</span><span class="mtk1">=</span><span class="mtk8">&quot;displayedColumns&quot;</span><span class="mtk17">&gt;&lt;/</span><span class="mtk4">tr</span><span class="mtk17">&gt;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk17">&lt;</span><span class="mtk4">tr</span><span class="mtk1"> </span><span class="mtk12">mat-row</span><span class="mtk1"> </span><span class="mtk12">*matRowDef</span><span class="mtk1">=</span><span class="mtk8">&quot;let row; columns: displayedColumns;&quot;</span><span class="mtk17">&gt;&lt;/</span><span class="mtk4">tr</span><span class="mtk17">&gt;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk17">&lt;/</span><span class="mtk4">table</span><span class="mtk17">&gt;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk17">&lt;/</span><span class="mtk4">article</span><span class="mtk17">&gt;</span></span></span></code></pre> <ol start="2"> <li>Define the columns schema with key, type and label:</li> </ol> <pre class="grvsc-container grvsc-has-line-highlighting default-dark" data-language="typescript" data-index="8"><code class="grvsc-code"><span class="grvsc-line"><span class="grvsc-source"><span class="mtk15">import</span><span class="mtk1"> { </span><span class="mtk12">Component</span><span class="mtk1"> } </span><span class="mtk15">from</span><span class="mtk1"> </span><span class="mtk8">&#39;@angular/core&#39;</span><span class="mtk1">;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk4">const</span><span class="mtk1"> </span><span class="mtk12">USER_DATA</span><span class="mtk1"> = [</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> {</span><span class="mtk8">&quot;name&quot;</span><span class="mtk12">:</span><span class="mtk1"> </span><span class="mtk8">&quot;John Smith&quot;</span><span class="mtk1">, </span><span class="mtk8">&quot;occupation&quot;</span><span class="mtk12">:</span><span class="mtk1"> </span><span class="mtk8">&quot;Advisor&quot;</span><span class="mtk1">, </span><span class="mtk8">&quot;age&quot;</span><span class="mtk12">:</span><span class="mtk1"> </span><span class="mtk7">36</span><span class="mtk1">},</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> {</span><span class="mtk8">&quot;name&quot;</span><span class="mtk12">:</span><span class="mtk1"> </span><span class="mtk8">&quot;Muhi Masri&quot;</span><span class="mtk1">, </span><span class="mtk8">&quot;occupation&quot;</span><span class="mtk12">:</span><span class="mtk1"> </span><span class="mtk8">&quot;Developer&quot;</span><span class="mtk1">, </span><span class="mtk8">&quot;age&quot;</span><span class="mtk12">:</span><span class="mtk1"> </span><span class="mtk7">28</span><span class="mtk1">},</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> {</span><span class="mtk8">&quot;name&quot;</span><span class="mtk12">:</span><span class="mtk1"> </span><span class="mtk8">&quot;Peter Adams&quot;</span><span class="mtk1">, </span><span class="mtk8">&quot;occupation&quot;</span><span class="mtk12">:</span><span class="mtk1"> </span><span class="mtk8">&quot;HR&quot;</span><span class="mtk1">, </span><span class="mtk8">&quot;age&quot;</span><span class="mtk12">:</span><span class="mtk1"> </span><span class="mtk7">20</span><span class="mtk1">},</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> {</span><span class="mtk8">&quot;name&quot;</span><span class="mtk12">:</span><span class="mtk1"> </span><span class="mtk8">&quot;Lora Bay&quot;</span><span class="mtk1">, </span><span class="mtk8">&quot;occupation&quot;</span><span class="mtk12">:</span><span class="mtk1"> </span><span class="mtk8">&quot;Marketing&quot;</span><span class="mtk1">, </span><span class="mtk8">&quot;age&quot;</span><span class="mtk12">:</span><span class="mtk1"> </span><span class="mtk7">43</span><span class="mtk1">}</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1">];</span></span></span> <span class="grvsc-line"><span class="grvsc-source"></span></span> <span class="grvsc-line grvsc-line-highlighted"><span class="grvsc-source"><span class="mtk4">const</span><span class="mtk1"> </span><span class="mtk12">COLUMNS_SCHEMA</span><span class="mtk1"> = [</span></span></span> <span class="grvsc-line grvsc-line-highlighted"><span class="grvsc-source"><span class="mtk1"> {</span></span></span> <span class="grvsc-line grvsc-line-highlighted"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">key:</span><span class="mtk1"> </span><span class="mtk8">&quot;name&quot;</span><span class="mtk1">,</span></span></span> <span class="grvsc-line grvsc-line-highlighted"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">type:</span><span class="mtk1"> </span><span class="mtk8">&quot;text&quot;</span><span class="mtk1">,</span></span></span> <span class="grvsc-line grvsc-line-highlighted"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">label:</span><span class="mtk1"> </span><span class="mtk8">&quot;Full Name&quot;</span></span></span> <span class="grvsc-line grvsc-line-highlighted"><span class="grvsc-source"><span class="mtk1"> },</span></span></span> <span class="grvsc-line grvsc-line-highlighted"><span class="grvsc-source"><span class="mtk1"> {</span></span></span> <span class="grvsc-line grvsc-line-highlighted"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">key:</span><span class="mtk1"> </span><span class="mtk8">&quot;occupation&quot;</span><span class="mtk1">,</span></span></span> <span class="grvsc-line grvsc-line-highlighted"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">type:</span><span class="mtk1"> </span><span class="mtk8">&quot;text&quot;</span><span class="mtk1">,</span></span></span> <span class="grvsc-line grvsc-line-highlighted"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">label:</span><span class="mtk1"> </span><span class="mtk8">&quot;Occupation&quot;</span></span></span> <span class="grvsc-line grvsc-line-highlighted"><span class="grvsc-source"><span class="mtk1"> },</span></span></span> <span class="grvsc-line grvsc-line-highlighted"><span class="grvsc-source"><span class="mtk1"> {</span></span></span> <span class="grvsc-line grvsc-line-highlighted"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">key:</span><span class="mtk1"> </span><span class="mtk8">&quot;age&quot;</span><span class="mtk1">,</span></span></span> <span class="grvsc-line grvsc-line-highlighted"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">type:</span><span class="mtk1"> </span><span class="mtk8">&quot;number&quot;</span><span class="mtk1">,</span></span></span> <span class="grvsc-line grvsc-line-highlighted"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">label:</span><span class="mtk1"> </span><span class="mtk8">&quot;Age&quot;</span></span></span> <span class="grvsc-line grvsc-line-highlighted"><span class="grvsc-source"><span class="mtk1"> }</span></span></span> <span class="grvsc-line grvsc-line-highlighted"><span class="grvsc-source"><span class="mtk1">]</span></span></span> <span class="grvsc-line"><span class="grvsc-source"></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1">@</span><span class="mtk11">Component</span><span class="mtk1">({</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">selector:</span><span class="mtk1"> </span><span class="mtk8">&#39;app-root&#39;</span><span class="mtk1">,</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">templateUrl:</span><span class="mtk1"> </span><span class="mtk8">&#39;./app.component.html&#39;</span><span class="mtk1">,</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">styleUrls:</span><span class="mtk1"> [</span><span class="mtk8">&#39;./app.component.scss&#39;</span><span class="mtk1">]</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1">})</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk15">export</span><span class="mtk1"> </span><span class="mtk4">class</span><span class="mtk1"> </span><span class="mtk10">AppComponent</span><span class="mtk1"> {</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">displayedColumns</span><span class="mtk1">: </span><span class="mtk10">string</span><span class="mtk1">[] = </span><span class="mtk12">COLUMNS_SCHEMA</span><span class="mtk1">.</span><span class="mtk11">map</span><span class="mtk1">((</span><span class="mtk12">col</span><span class="mtk1">) </span><span class="mtk4">=&gt;</span><span class="mtk1"> </span><span class="mtk12">col</span><span class="mtk1">.</span><span class="mtk12">key</span><span class="mtk1">);</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">dataSource</span><span class="mtk1">: </span><span class="mtk10">any</span><span class="mtk1"> = </span><span class="mtk12">USER_DATA</span><span class="mtk1">;</span></span></span> <span class="grvsc-line grvsc-line-highlighted"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">columnsSchema</span><span class="mtk1">: </span><span class="mtk10">any</span><span class="mtk1"> = </span><span class="mtk12">COLUMNS_SCHEMA</span><span class="mtk1">;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1">}</span></span></span></code></pre> <p><code>displayColumns</code> used to have a static list of column keys but now we changed it to read directly from <code>COLUMNS_SCHEMA</code> using the <code>map</code> function.</p> <ol start="3"> <li>Update the template to dynamically add input fields based on the column type</li> </ol> <pre class="grvsc-container grvsc-has-line-highlighting default-dark" data-language="html" data-index="9"><code class="grvsc-code"><span class="grvsc-line"><span class="grvsc-source"><span class="mtk17">&lt;</span><span class="mtk4">article</span><span class="mtk17">&gt;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk17">&lt;</span><span class="mtk4">table</span><span class="mtk1"> </span><span class="mtk12">mat-table</span><span class="mtk1"> </span><span class="mtk12">[dataSource]</span><span class="mtk1">=</span><span class="mtk8">&quot;dataSource&quot;</span><span class="mtk17">&gt;</span></span></span> <span class="grvsc-line grvsc-line-highlighted"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk17">&lt;</span><span class="mtk4">ng-container</span><span class="mtk1"> </span><span class="mtk12">[matColumnDef]</span><span class="mtk1">=</span><span class="mtk8">&quot;col.key&quot;</span><span class="mtk1"> </span><span class="mtk12">*ngFor</span><span class="mtk1">=</span><span class="mtk8">&quot;let col of columnsSchema&quot;</span><span class="mtk17">&gt;</span></span></span> <span class="grvsc-line grvsc-line-highlighted"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk17">&lt;</span><span class="mtk4">th</span><span class="mtk1"> </span><span class="mtk12">mat-header-cell</span><span class="mtk1"> </span><span class="mtk12">*matHeaderCellDef</span><span class="mtk17">&gt;</span></span></span> <span class="grvsc-line grvsc-line-highlighted"><span class="grvsc-source"><span class="mtk1"> {{col.label}}</span></span></span> <span class="grvsc-line grvsc-line-highlighted"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk17">&lt;/</span><span class="mtk4">th</span><span class="mtk17">&gt;</span></span></span> <span class="grvsc-line grvsc-line-highlighted"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk17">&lt;</span><span class="mtk4">td</span><span class="mtk1"> </span><span class="mtk12">mat-cell</span><span class="mtk1"> </span><span class="mtk12">*matCellDef</span><span class="mtk1">=</span><span class="mtk8">&quot;let element&quot;</span><span class="mtk17">&gt;</span></span></span> <span class="grvsc-line grvsc-line-highlighted"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk17">&lt;</span><span class="mtk4">mat-form-field</span><span class="mtk17">&gt;</span></span></span> <span class="grvsc-line grvsc-line-highlighted"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk17">&lt;</span><span class="mtk4">input</span><span class="mtk1"> </span><span class="mtk12">[type]</span><span class="mtk1">=</span><span class="mtk8">&quot;col.type&quot;</span><span class="mtk1"> </span><span class="mtk12">matInput</span><span class="mtk1"> </span><span class="mtk12">[(ngModel)]</span><span class="mtk1">=</span><span class="mtk8">&quot;element[col.key]&quot;</span><span class="mtk17">&gt;</span></span></span> <span class="grvsc-line grvsc-line-highlighted"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk17">&lt;/</span><span class="mtk4">mat-form-field</span><span class="mtk17">&gt;</span></span></span> <span class="grvsc-line grvsc-line-highlighted"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk17">&lt;/</span><span class="mtk4">td</span><span class="mtk17">&gt;</span></span></span> <span class="grvsc-line grvsc-line-highlighted"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk17">&lt;/</span><span class="mtk4">ng-container</span><span class="mtk17">&gt;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk17">&lt;</span><span class="mtk4">tr</span><span class="mtk1"> </span><span class="mtk12">mat-header-row</span><span class="mtk1"> </span><span class="mtk12">*matHeaderRowDef</span><span class="mtk1">=</span><span class="mtk8">&quot;displayedColumns&quot;</span><span class="mtk17">&gt;&lt;/</span><span class="mtk4">tr</span><span class="mtk17">&gt;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk17">&lt;</span><span class="mtk4">tr</span><span class="mtk1"> </span><span class="mtk12">mat-row</span><span class="mtk1"> </span><span class="mtk12">*matRowDef</span><span class="mtk1">=</span><span class="mtk8">&quot;let row; columns: displayedColumns;&quot;</span><span class="mtk17">&gt;&lt;/</span><span class="mtk4">tr</span><span class="mtk17">&gt;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk17">&lt;/</span><span class="mtk4">table</span><span class="mtk17">&gt;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk17">&lt;/</span><span class="mtk4">article</span><span class="mtk17">&gt;</span></span></span></code></pre> <p><em>We’re now looping through <code>columnsSchema</code> instead of the <code>displayColumns</code> array as it has the new required properties (key, type and label).</em></p> <p>Using <code>col.type</code>, we can conveniently pass the input type (text, number, date…) to the HTML input element.</p> <h2 id="enable-inline-row-editing" style="position:relative;"><a href="#enable-inline-row-editing" aria-label="enable inline row editing permalink" class="anchor before"><svg aria-hidden="true" focusable="false" height="16" version="1.1" viewBox="0 0 16 16" width="16"><path fill-rule="evenodd" d="M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z"></path></svg></a>Enable inline row editing</h2> <p>In a real-life scenario, the user would want to have a read-only mode by default and edit a row when required.</p> <p>To achieve this, we first need to add an edit button for each row. That will require adding a new column in the <code>columnsSchema</code> list. Let’s name it <code>isEdit</code> for now, but it could be anything as long as it does not conflict with other column names.</p> <pre class="grvsc-container default-dark" data-language="typescript" data-index="10"><code class="grvsc-code"><span class="grvsc-line"><span class="grvsc-source"><span class="mtk4">const</span><span class="mtk1"> </span><span class="mtk12">COLUMNS_SCHEMA</span><span class="mtk1"> = [</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> {</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">key:</span><span class="mtk1"> </span><span class="mtk8">&quot;name&quot;</span><span class="mtk1">,</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">type:</span><span class="mtk1"> </span><span class="mtk8">&quot;text&quot;</span><span class="mtk1">,</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">label:</span><span class="mtk1"> </span><span class="mtk8">&quot;Full Name&quot;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> },</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> {</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">key:</span><span class="mtk1"> </span><span class="mtk8">&quot;occupation&quot;</span><span class="mtk1">,</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">type:</span><span class="mtk1"> </span><span class="mtk8">&quot;text&quot;</span><span class="mtk1">,</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">label:</span><span class="mtk1"> </span><span class="mtk8">&quot;Occupation&quot;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> },</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> {</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">key:</span><span class="mtk1"> </span><span class="mtk8">&quot;age&quot;</span><span class="mtk1">,</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">type:</span><span class="mtk1"> </span><span class="mtk8">&quot;number&quot;</span><span class="mtk1">,</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">label:</span><span class="mtk1"> </span><span class="mtk8">&quot;Age&quot;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> },</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> {</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">key:</span><span class="mtk1"> </span><span class="mtk8">&quot;isEdit&quot;</span><span class="mtk1">,</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">type:</span><span class="mtk1"> </span><span class="mtk8">&quot;isEdit&quot;</span><span class="mtk1">,</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">label:</span><span class="mtk1"> </span><span class="mtk8">&quot;&quot;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> }</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1">]</span></span></span></code></pre> <p><em><code>isEdit</code> column has an empty label as it will not require a title in this scenario.</em></p> <p>Now let’s add a condition in the template to toggle between read-only and edit mode based on the <code>isEdit</code> value.</p> <pre class="grvsc-container grvsc-has-line-highlighting default-dark" data-language="html" data-index="11"><code class="grvsc-code"><span class="grvsc-line"><span class="grvsc-source"><span class="mtk17">&lt;</span><span class="mtk4">table</span><span class="mtk1"> </span><span class="mtk12">mat-table</span><span class="mtk1"> </span><span class="mtk12">[dataSource]</span><span class="mtk1">=</span><span class="mtk8">&quot;dataSource&quot;</span><span class="mtk17">&gt;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk17">&lt;</span><span class="mtk4">ng-container</span><span class="mtk1"> </span><span class="mtk12">[matColumnDef]</span><span class="mtk1">=</span><span class="mtk8">&quot;col.key&quot;</span><span class="mtk1"> </span><span class="mtk12">*ngFor</span><span class="mtk1">=</span><span class="mtk8">&quot;let col of columnsSchema&quot;</span><span class="mtk17">&gt;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk17">&lt;</span><span class="mtk4">th</span><span class="mtk1"> </span><span class="mtk12">mat-header-cell</span><span class="mtk1"> </span><span class="mtk12">*matHeaderCellDef</span><span class="mtk17">&gt;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> {{ col.label }}</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk17">&lt;/</span><span class="mtk4">th</span><span class="mtk17">&gt;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk17">&lt;</span><span class="mtk4">td</span><span class="mtk1"> </span><span class="mtk12">mat-cell</span><span class="mtk1"> </span><span class="mtk12">*matCellDef</span><span class="mtk1">=</span><span class="mtk8">&quot;let element&quot;</span><span class="mtk17">&gt;</span></span></span> <span class="grvsc-line grvsc-line-highlighted"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk17">&lt;</span><span class="mtk4">div</span><span class="mtk1"> </span><span class="mtk12">[ngSwitch]</span><span class="mtk1">=</span><span class="mtk8">&quot;col.type&quot;</span><span class="mtk1"> </span><span class="mtk12">*ngIf</span><span class="mtk1">=</span><span class="mtk8">&quot;!element.isEdit&quot;</span><span class="mtk17">&gt;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk17">&lt;</span><span class="mtk4">div</span><span class="mtk1"> </span><span class="mtk12">class</span><span class="mtk1">=</span><span class="mtk8">&quot;btn-edit&quot;</span><span class="mtk1"> </span><span class="mtk12">*ngSwitchCase</span><span class="mtk1">=</span><span class="mtk8">&quot;&#39;isEdit&#39;&quot;</span><span class="mtk17">&gt;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk17">&lt;</span><span class="mtk4">button</span><span class="mtk1"> </span><span class="mtk12">mat-button</span><span class="mtk1"> </span><span class="mtk12">(click)</span><span class="mtk1">=</span><span class="mtk8">&quot;element.isEdit = !element.isEdit&quot;</span><span class="mtk17">&gt;</span><span class="mtk1">Edit</span><span class="mtk17">&lt;/</span><span class="mtk4">button</span><span class="mtk17">&gt;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk17">&lt;/</span><span class="mtk4">div</span><span class="mtk17">&gt;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk17">&lt;</span><span class="mtk4">span</span><span class="mtk1"> </span><span class="mtk12">*ngSwitchDefault</span><span class="mtk17">&gt;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> {{ element[col.key] }}</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk17">&lt;/</span><span class="mtk4">span</span><span class="mtk17">&gt;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk17">&lt;/</span><span class="mtk4">div</span><span class="mtk17">&gt;</span></span></span> <span class="grvsc-line grvsc-line-highlighted"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk17">&lt;</span><span class="mtk4">div</span><span class="mtk1"> </span><span class="mtk12">*ngIf</span><span class="mtk1">=</span><span class="mtk8">&quot;element.isEdit&quot;</span><span class="mtk17">&gt;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk17">&lt;</span><span class="mtk4">div</span><span class="mtk1"> </span><span class="mtk12">class</span><span class="mtk1">=</span><span class="mtk8">&quot;btn-edit&quot;</span><span class="mtk1"> </span><span class="mtk12">*ngIf</span><span class="mtk1">=</span><span class="mtk8">&quot;col.key === &#39;isEdit&#39;; else dataField&quot;</span><span class="mtk17">&gt;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk17">&lt;</span><span class="mtk4">button</span><span class="mtk1"> </span><span class="mtk12">mat-button</span><span class="mtk1"> </span><span class="mtk12">(click)</span><span class="mtk1">=</span><span class="mtk8">&quot;element.isEdit = !element.isEdit&quot;</span><span class="mtk17">&gt;</span><span class="mtk1">Done</span><span class="mtk17">&lt;/</span><span class="mtk4">button</span><span class="mtk17">&gt;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk17">&lt;/</span><span class="mtk4">div</span><span class="mtk17">&gt;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk17">&lt;</span><span class="mtk4">ng-template</span><span class="mtk1"> </span><span class="mtk12">#dataField</span><span class="mtk17">&gt;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk17">&lt;</span><span class="mtk4">mat-form-field</span><span class="mtk17">&gt;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk17">&lt;</span><span class="mtk4">input</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">[type]</span><span class="mtk1">=</span><span class="mtk8">&quot;col.type&quot;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">matInput</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">[(ngModel)]</span><span class="mtk1">=</span><span class="mtk8">&quot;element[col.key]&quot;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk17">/&gt;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk17">&lt;/</span><span class="mtk4">mat-form-field</span><span class="mtk17">&gt;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk17">&lt;/</span><span class="mtk4">ng-template</span><span class="mtk17">&gt;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk17">&lt;/</span><span class="mtk4">div</span><span class="mtk17">&gt;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk17">&lt;/</span><span class="mtk4">td</span><span class="mtk17">&gt;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk17">&lt;/</span><span class="mtk4">ng-container</span><span class="mtk17">&gt;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk17">&lt;</span><span class="mtk4">tr</span><span class="mtk1"> </span><span class="mtk12">mat-header-row</span><span class="mtk1"> </span><span class="mtk12">*matHeaderRowDef</span><span class="mtk1">=</span><span class="mtk8">&quot;displayedColumns&quot;</span><span class="mtk17">&gt;&lt;/</span><span class="mtk4">tr</span><span class="mtk17">&gt;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk17">&lt;</span><span class="mtk4">tr</span><span class="mtk1"> </span><span class="mtk12">mat-row</span><span class="mtk1"> </span><span class="mtk12">*matRowDef</span><span class="mtk1">=</span><span class="mtk8">&quot;let row; columns: displayedColumns&quot;</span><span class="mtk17">&gt;&lt;/</span><span class="mtk4">tr</span><span class="mtk17">&gt;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk17">&lt;/</span><span class="mtk4">table</span><span class="mtk17">&gt;</span></span></span></code></pre> <p>By default, the <code>isEdit</code> value is <code>undefined</code> (or <code>false</code>). However, when clicking the button, the value is added to the element’s object as <code>true</code>.</p> <h2 id="support-other-data-types" style="position:relative;"><a href="#support-other-data-types" aria-label="support other data types permalink" class="anchor before"><svg aria-hidden="true" focusable="false" height="16" version="1.1" viewBox="0 0 16 16" width="16"><path fill-rule="evenodd" d="M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z"></path></svg></a>Support other data types</h2> <p>What we just implemented supports basic HTML types such as input number, text…</p> <p>One approach to supporting custom elements is simply adding new conditions in the Angular template. For example, let’s assume we want to add a Material date element instead of the built-in HTML one. We can add <code>ngSwitch</code> statements to support date and other custom types:</p> <pre class="grvsc-container grvsc-has-line-highlighting default-dark" data-language="html" data-index="12"><code class="grvsc-code"><span class="grvsc-line"><span class="grvsc-source"><span class="mtk17">&lt;</span><span class="mtk4">table</span><span class="mtk1"> </span><span class="mtk12">mat-table</span><span class="mtk1"> </span><span class="mtk12">[dataSource]</span><span class="mtk1">=</span><span class="mtk8">&quot;dataSource&quot;</span><span class="mtk17">&gt;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk17">&lt;</span><span class="mtk4">ng-container</span><span class="mtk1"> </span><span class="mtk12">[matColumnDef]</span><span class="mtk1">=</span><span class="mtk8">&quot;col.key&quot;</span><span class="mtk1"> </span><span class="mtk12">*ngFor</span><span class="mtk1">=</span><span class="mtk8">&quot;let col of columnsSchema&quot;</span><span class="mtk17">&gt;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk17">&lt;</span><span class="mtk4">th</span><span class="mtk1"> </span><span class="mtk12">mat-header-cell</span><span class="mtk1"> </span><span class="mtk12">*matHeaderCellDef</span><span class="mtk17">&gt;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> {{ col.label }}</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk17">&lt;/</span><span class="mtk4">th</span><span class="mtk17">&gt;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk17">&lt;</span><span class="mtk4">td</span><span class="mtk1"> </span><span class="mtk12">mat-cell</span><span class="mtk1"> </span><span class="mtk12">*matCellDef</span><span class="mtk1">=</span><span class="mtk8">&quot;let element&quot;</span><span class="mtk17">&gt;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk17">&lt;</span><span class="mtk4">div</span><span class="mtk1"> </span><span class="mtk12">[ngSwitch]</span><span class="mtk1">=</span><span class="mtk8">&quot;col.type&quot;</span><span class="mtk1"> </span><span class="mtk12">*ngIf</span><span class="mtk1">=</span><span class="mtk8">&quot;!element.isEdit&quot;</span><span class="mtk17">&gt;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk17">&lt;</span><span class="mtk4">div</span><span class="mtk1"> </span><span class="mtk12">class</span><span class="mtk1">=</span><span class="mtk8">&quot;btn-edit&quot;</span><span class="mtk1"> </span><span class="mtk12">*ngSwitchCase</span><span class="mtk1">=</span><span class="mtk8">&quot;&#39;isEdit&#39;&quot;</span><span class="mtk17">&gt;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk17">&lt;</span><span class="mtk4">button</span><span class="mtk1"> </span><span class="mtk12">mat-button</span><span class="mtk1"> </span><span class="mtk12">(click)</span><span class="mtk1">=</span><span class="mtk8">&quot;element.isEdit = !element.isEdit&quot;</span><span class="mtk17">&gt;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> Edit</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk17">&lt;/</span><span class="mtk4">button</span><span class="mtk17">&gt;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk17">&lt;/</span><span class="mtk4">div</span><span class="mtk17">&gt;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk17">&lt;</span><span class="mtk4">span</span><span class="mtk1"> </span><span class="mtk12">*ngSwitchDefault</span><span class="mtk17">&gt;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> {{ element[col.key] }}</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk17">&lt;/</span><span class="mtk4">span</span><span class="mtk17">&gt;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk17">&lt;/</span><span class="mtk4">div</span><span class="mtk17">&gt;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk17">&lt;</span><span class="mtk4">div</span><span class="mtk1"> </span><span class="mtk12">[ngSwitch]</span><span class="mtk1">=</span><span class="mtk8">&quot;col.type&quot;</span><span class="mtk1"> </span><span class="mtk12">*ngIf</span><span class="mtk1">=</span><span class="mtk8">&quot;element.isEdit&quot;</span><span class="mtk17">&gt;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk17">&lt;</span><span class="mtk4">div</span><span class="mtk1"> </span><span class="mtk12">class</span><span class="mtk1">=</span><span class="mtk8">&quot;btn-edit&quot;</span><span class="mtk1"> </span><span class="mtk12">*ngSwitchCase</span><span class="mtk1">=</span><span class="mtk8">&quot;&#39;isEdit&#39;&quot;</span><span class="mtk17">&gt;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk17">&lt;</span><span class="mtk4">button</span><span class="mtk1"> </span><span class="mtk12">mat-button</span><span class="mtk1"> </span><span class="mtk12">(click)</span><span class="mtk1">=</span><span class="mtk8">&quot;element.isEdit = !element.isEdit&quot;</span><span class="mtk17">&gt;</span><span class="mtk1">Done</span><span class="mtk17">&lt;/</span><span class="mtk4">button</span><span class="mtk17">&gt;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk17">&lt;/</span><span class="mtk4">div</span><span class="mtk17">&gt;</span></span></span> <span class="grvsc-line grvsc-line-highlighted"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk17">&lt;</span><span class="mtk4">mat-form-field</span><span class="mtk1"> </span><span class="mtk12">*ngSwitchCase</span><span class="mtk1">=</span><span class="mtk8">&quot;&#39;date&#39;&quot;</span><span class="mtk1"> </span><span class="mtk12">appearance</span><span class="mtk1">=</span><span class="mtk8">&quot;fill&quot;</span><span class="mtk17">&gt;</span></span></span> <span class="grvsc-line grvsc-line-highlighted"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk17">&lt;</span><span class="mtk4">mat-label</span><span class="mtk17">&gt;</span><span class="mtk1">Choose a date</span><span class="mtk17">&lt;/</span><span class="mtk4">mat-label</span><span class="mtk17">&gt;</span></span></span> <span class="grvsc-line grvsc-line-highlighted"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk17">&lt;</span><span class="mtk4">input</span><span class="mtk1"> </span><span class="mtk12">matInput</span><span class="mtk1"> </span><span class="mtk12">[matDatepicker]</span><span class="mtk1">=</span><span class="mtk8">&quot;picker&quot;</span><span class="mtk1"> </span><span class="mtk12">[(ngModel)]</span><span class="mtk1">=</span><span class="mtk8">&quot;element[col.key]&quot;</span><span class="mtk1"> </span><span class="mtk17">/&gt;</span></span></span> <span class="grvsc-line grvsc-line-highlighted"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk17">&lt;</span><span class="mtk4">mat-datepicker-toggle</span></span></span> <span class="grvsc-line grvsc-line-highlighted"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">matSuffix</span></span></span> <span class="grvsc-line grvsc-line-highlighted"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">[for]</span><span class="mtk1">=</span><span class="mtk8">&quot;picker&quot;</span></span></span> <span class="grvsc-line grvsc-line-highlighted"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk17">&gt;&lt;/</span><span class="mtk4">mat-datepicker-toggle</span><span class="mtk17">&gt;</span></span></span> <span class="grvsc-line grvsc-line-highlighted"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk17">&lt;</span><span class="mtk4">mat-datepicker</span><span class="mtk1"> </span><span class="mtk12">#picker</span><span class="mtk17">&gt;&lt;/</span><span class="mtk4">mat-datepicker</span><span class="mtk17">&gt;</span></span></span> <span class="grvsc-line grvsc-line-highlighted"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk17">&lt;/</span><span class="mtk4">mat-form-field</span><span class="mtk17">&gt;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk17">&lt;</span><span class="mtk4">mat-form-field</span><span class="mtk1"> </span><span class="mtk12">*ngSwitchDefault</span><span class="mtk17">&gt;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk17">&lt;</span><span class="mtk4">input</span><span class="mtk1"> </span><span class="mtk12">[type]</span><span class="mtk1">=</span><span class="mtk8">&quot;col.type&quot;</span><span class="mtk1"> </span><span class="mtk12">matInput</span><span class="mtk1"> </span><span class="mtk12">[(ngModel)]</span><span class="mtk1">=</span><span class="mtk8">&quot;element[col.key]&quot;</span><span class="mtk1"> </span><span class="mtk17">/&gt;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk17">&lt;/</span><span class="mtk4">mat-form-field</span><span class="mtk17">&gt;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk17">&lt;/</span><span class="mtk4">div</span><span class="mtk17">&gt;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk17">&lt;/</span><span class="mtk4">td</span><span class="mtk17">&gt;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk17">&lt;/</span><span class="mtk4">ng-container</span><span class="mtk17">&gt;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk17">&lt;</span><span class="mtk4">tr</span><span class="mtk1"> </span><span class="mtk12">mat-header-row</span><span class="mtk1"> </span><span class="mtk12">*matHeaderRowDef</span><span class="mtk1">=</span><span class="mtk8">&quot;displayedColumns&quot;</span><span class="mtk17">&gt;&lt;/</span><span class="mtk4">tr</span><span class="mtk17">&gt;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk17">&lt;</span><span class="mtk4">tr</span><span class="mtk1"> </span><span class="mtk12">mat-row</span><span class="mtk1"> </span><span class="mtk12">*matRowDef</span><span class="mtk1">=</span><span class="mtk8">&quot;let row; columns: displayedColumns&quot;</span><span class="mtk17">&gt;&lt;/</span><span class="mtk4">tr</span><span class="mtk17">&gt;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk17">&lt;/</span><span class="mtk4">table</span><span class="mtk17">&gt;</span></span></span></code></pre> <p>To test the new data type, we need to change the <code>USER_DATA</code> and <code>COLUMNS_SCHEMA</code> to include a date field:</p> <pre class="grvsc-container default-dark" data-language="json" data-index="13"><code class="grvsc-code"><span class="grvsc-line"><span class="grvsc-source"><span class="mtk1">[</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> {</span><span class="mtk12">&quot;name&quot;</span><span class="mtk1">: </span><span class="mtk8">&quot;John Smith&quot;</span><span class="mtk1">, </span><span class="mtk12">&quot;occupation&quot;</span><span class="mtk1">: </span><span class="mtk8">&quot;Advisor&quot;</span><span class="mtk1">, </span><span class="mtk12">&quot;dateOfBirth&quot;</span><span class="mtk1">: </span><span class="mtk8">&quot;1984-05-05&quot;</span><span class="mtk1">, </span><span class="mtk12">&quot;age&quot;</span><span class="mtk1">: </span><span class="mtk7">36</span><span class="mtk1">},</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> {</span><span class="mtk12">&quot;name&quot;</span><span class="mtk1">: </span><span class="mtk8">&quot;Muhi Masri&quot;</span><span class="mtk1">, </span><span class="mtk12">&quot;occupation&quot;</span><span class="mtk1">: </span><span class="mtk8">&quot;Developer&quot;</span><span class="mtk1">, </span><span class="mtk12">&quot;dateOfBirth&quot;</span><span class="mtk1">: </span><span class="mtk8">&quot;1992-02-02&quot;</span><span class="mtk1">, </span><span class="mtk12">&quot;age&quot;</span><span class="mtk1">: </span><span class="mtk7">28</span><span class="mtk1">},</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> {</span><span class="mtk12">&quot;name&quot;</span><span class="mtk1">: </span><span class="mtk8">&quot;Peter Adams&quot;</span><span class="mtk1">, </span><span class="mtk12">&quot;occupation&quot;</span><span class="mtk1">: </span><span class="mtk8">&quot;HR&quot;</span><span class="mtk1">, </span><span class="mtk12">&quot;dateOfBirth&quot;</span><span class="mtk1">: </span><span class="mtk8">&quot;2000-01-01&quot;</span><span class="mtk1">, </span><span class="mtk12">&quot;age&quot;</span><span class="mtk1">: </span><span class="mtk7">20</span><span class="mtk1">},</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> {</span><span class="mtk12">&quot;name&quot;</span><span class="mtk1">: </span><span class="mtk8">&quot;Lora Bay&quot;</span><span class="mtk1">, </span><span class="mtk12">&quot;occupation&quot;</span><span class="mtk1">: </span><span class="mtk8">&quot;Marketing&quot;</span><span class="mtk1">, </span><span class="mtk12">&quot;dateOfBirth&quot;</span><span class="mtk1">: </span><span class="mtk8">&quot;1977-03-03&quot;</span><span class="mtk1">, </span><span class="mtk12">&quot;age&quot;</span><span class="mtk1">: </span><span class="mtk7">43</span><span class="mtk1">},</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1">]</span></span></span></code></pre> <pre class="grvsc-container grvsc-has-line-highlighting default-dark" data-language="json" data-index="14"><code class="grvsc-code"><span class="grvsc-line"><span class="grvsc-source"><span class="mtk1">[</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> {</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk14">key</span><span class="mtk1">: </span><span class="mtk8">&quot;name&quot;</span><span class="mtk1">,</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk14">type</span><span class="mtk1">: </span><span class="mtk8">&quot;text&quot;</span><span class="mtk1">,</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk14">label</span><span class="mtk1">: </span><span class="mtk8">&quot;Full Name&quot;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> },</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> {</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk14">key</span><span class="mtk1">: </span><span class="mtk8">&quot;occupation&quot;</span><span class="mtk1">,</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk14">type</span><span class="mtk1">: </span><span class="mtk8">&quot;text&quot;</span><span class="mtk1">,</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk14">label</span><span class="mtk1">: </span><span class="mtk8">&quot;Occupation&quot;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> },</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> {</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk14">key</span><span class="mtk1">: </span><span class="mtk8">&quot;dateOfBirth&quot;</span><span class="mtk1">,</span></span></span> <span class="grvsc-line grvsc-line-highlighted"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk14">type</span><span class="mtk1">: </span><span class="mtk8">&quot;date&quot;</span><span class="mtk1">,</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk14">label</span><span class="mtk1">: </span><span class="mtk8">&quot;Date of Birth&quot;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> },</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> {</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk14">key</span><span class="mtk1">: </span><span class="mtk8">&quot;age&quot;</span><span class="mtk1">,</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk14">type</span><span class="mtk1">: </span><span class="mtk8">&quot;number&quot;</span><span class="mtk1">,</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk14">label</span><span class="mtk1">: </span><span class="mtk8">&quot;Age&quot;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> },</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> {</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk14">key</span><span class="mtk1">: </span><span class="mtk8">&quot;isEdit&quot;</span><span class="mtk1">,</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk14">type</span><span class="mtk1">: </span><span class="mtk8">&quot;isEdit&quot;</span><span class="mtk1">,</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk14">label</span><span class="mtk1">: </span><span class="mtk8">&quot;&quot;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> }</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1">]</span></span></span></code></pre> <h2 id="summary" style="position:relative;"><a href="#summary" aria-label="summary permalink" class="anchor before"><svg aria-hidden="true" focusable="false" height="16" version="1.1" viewBox="0 0 16 16" width="16"><path fill-rule="evenodd" d="M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z"></path></svg></a>Summary</h2> <p>If you made it to this section, pat yourself on the back! You just learned how to:</p> <ul> <li>Setup an Angular Material project</li> <li>Populate data using Material Table component</li> <li>Create dynamic columns</li> <li>Enable inline row editing</li> </ul> <p><a href="https://muhimasri.com/blogs/add-and-remove-table-rows-using-angular-material/">In the next part, we are going to learn how to add and remove table rows.</a></p> <p>You can access the <a href="https://github.com/muhimasri/angular-editable-table">complete repository here</a>.</p> <p>Bye for now 👋</p> <style class="grvsc-styles"> .grvsc-container { overflow: auto; position: relative; -webkit-overflow-scrolling: touch; padding-top: 1rem; padding-top: var(--grvsc-padding-top, var(--grvsc-padding-v, 1rem)); padding-bottom: 1rem; padding-bottom: var(--grvsc-padding-bottom, var(--grvsc-padding-v, 1rem)); border-radius: 8px; border-radius: var(--grvsc-border-radius, 8px); font-feature-settings: normal; line-height: 1.4; } .grvsc-code { display: table; } .grvsc-line { display: table-row; box-sizing: border-box; width: 100%; position: relative; } .grvsc-line > * { position: relative; } .grvsc-gutter-pad { display: table-cell; padding-left: 0.75rem; padding-left: calc(var(--grvsc-padding-left, var(--grvsc-padding-h, 1.5rem)) / 2); } .grvsc-gutter { display: table-cell; -webkit-user-select: none; -moz-user-select: none; user-select: none; } .grvsc-gutter::before { content: attr(data-content); } .grvsc-source { display: table-cell; padding-left: 1.5rem; padding-left: var(--grvsc-padding-left, var(--grvsc-padding-h, 1.5rem)); padding-right: 1.5rem; padding-right: var(--grvsc-padding-right, var(--grvsc-padding-h, 1.5rem)); } .grvsc-source:empty::after { content: ' '; -webkit-user-select: none; -moz-user-select: none; user-select: none; } .grvsc-gutter + .grvsc-source { padding-left: 0.75rem; padding-left: calc(var(--grvsc-padding-left, var(--grvsc-padding-h, 1.5rem)) / 2); } /* Line transformer styles */ .grvsc-has-line-highlighting > .grvsc-code > .grvsc-line::before { content: ' '; position: absolute; width: 100%; } .grvsc-line-diff-add::before { background-color: var(--grvsc-line-diff-add-background-color, rgba(0, 255, 60, 0.2)); } .grvsc-line-diff-del::before { background-color: var(--grvsc-line-diff-del-background-color, rgba(255, 0, 20, 0.2)); } .grvsc-line-number { padding: 0 2px; text-align: right; opacity: 0.7; } .default-dark { background-color: #1E1E1E; color: #D4D4D4; } .default-dark .mtk1 { color: #D4D4D4; } .default-dark .mtk12 { color: #9CDCFE; } .default-dark .mtk8 { color: #CE9178; } .default-dark .mtk7 { color: #B5CEA8; } .default-dark .mtk14 { color: #F44747; } .default-dark .mtk15 { color: #C586C0; } .default-dark .mtk4 { color: #569CD6; } .default-dark .mtk11 { color: #DCDCAA; } .default-dark .mtk10 { color: #4EC9B0; } .default-dark .mtk17 { color: #808080; } .default-dark .grvsc-line-highlighted::before { background-color: var(--grvsc-line-highlighted-background-color, rgba(255, 255, 255, 0.1)); box-shadow: inset var(--grvsc-line-highlighted-border-width, 4px) 0 0 0 var(--grvsc-line-highlighted-border-color, rgba(255, 255, 255, 0.5)); } </style><![CDATA[Create a Custom Checkbox Component with Vue]]>https://muhimasri.comcreating-a-custom-checkbox-component-with-html-css-and-vuehttps://muhimasri.comcreating-a-custom-checkbox-component-with-html-css-and-vue<p>In this article I’d like to share with you how to create a reusable custom checkbox element using CSS and VueJS. Most of us are used to having custom UI elements out of the box when using Bootstrap, Material or other libraries but in my recent project I was asked not to use any of the UI libraries. So I accepted the challenge, rolled up my sleeves and went right into it 💪</p> <p>The goal here is to change the styling of the checkbox using pure CSS (with SCSS support) and enable color customization for developers</p> <p><img src="/823855f8b0ff01aa1d88d3e9b4a7282d/ezgif.com-crop-1-2.gif" alt=""></p> <h2 id="initialize-a-vue-app-with-a-checkbox-component" style="position:relative;"><a href="#initialize-a-vue-app-with-a-checkbox-component" aria-label="initialize a vue app with a checkbox component permalink" class="anchor before"><svg aria-hidden="true" focusable="false" height="16" version="1.1" viewBox="0 0 16 16" width="16"><path fill-rule="evenodd" d="M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z"></path></svg></a>Initialize a Vue app with a checkbox component</h2> <p>We will use <a href="https://cli.vuejs.org/">Vue CLI</a> to setup and create a new project. If you already have Vue CLI installed and don’t want to start a new project you can skip this part.</p> <pre class="grvsc-container default-dark" data-language="" data-index="0"><code class="grvsc-code"><span class="grvsc-line"><span class="grvsc-source">npm install -g @vue/cli</span></span> <span class="grvsc-line"><span class="grvsc-source">vue create vue-custom-checkbox</span></span></code></pre> <p>When creating a new Vue project, choosing the default settings will enable SCSS out of the box.</p> <p>Now, let’s create an empty checkbox component with SCSS enabled for styling.</p> <pre class="grvsc-container default-dark" data-language="html" data-index="1"><code class="grvsc-code"><span class="grvsc-line"><span class="grvsc-source"><span class="mtk17">&lt;</span><span class="mtk4">template</span><span class="mtk17">&gt;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk17">&lt;/</span><span class="mtk4">template</span><span class="mtk17">&gt;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk17">&lt;</span><span class="mtk4">script</span><span class="mtk17">&gt;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk15">export</span><span class="mtk1"> </span><span class="mtk15">default</span><span class="mtk1"> {}</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk17">&lt;/</span><span class="mtk4">script</span><span class="mtk17">&gt;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk17">&lt;</span><span class="mtk4">style</span><span class="mtk1"> </span><span class="mtk12">lang</span><span class="mtk1">=</span><span class="mtk8">&quot;scss&quot;</span><span class="mtk17">&gt;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk17">&lt;/</span><span class="mtk4">style</span><span class="mtk17">&gt;</span></span></span></code></pre> <h2 id="customize-html" style="position:relative;"><a href="#customize-html" aria-label="customize html permalink" class="anchor before"><svg aria-hidden="true" focusable="false" height="16" version="1.1" viewBox="0 0 16 16" width="16"><path fill-rule="evenodd" d="M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z"></path></svg></a>Customize HTML</h2> <p>Add the required HTML elements to customize a checkbox.</p> <pre class="grvsc-container default-dark" data-language="html" data-index="2"><code class="grvsc-code"><span class="grvsc-line"><span class="grvsc-source"><span class="mtk17">&lt;</span><span class="mtk4">template</span><span class="mtk17">&gt;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk17">&lt;</span><span class="mtk4">label</span><span class="mtk17">&gt;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk17">&lt;</span><span class="mtk4">input</span><span class="mtk1"> </span><span class="mtk12">type</span><span class="mtk1">=</span><span class="mtk8">&quot;checkbox&quot;</span><span class="mtk1"> </span><span class="mtk17">/&gt;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk17">&lt;</span><span class="mtk4">span</span><span class="mtk17">&gt;&lt;/</span><span class="mtk4">span</span><span class="mtk17">&gt;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk17">&lt;/</span><span class="mtk4">label</span><span class="mtk17">&gt;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk17">&lt;/</span><span class="mtk4">template</span><span class="mtk17">&gt;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk17">&lt;</span><span class="mtk4">script</span><span class="mtk17">&gt;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk15">export</span><span class="mtk1"> </span><span class="mtk15">default</span><span class="mtk1"> {};</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk17">&lt;/</span><span class="mtk4">script</span><span class="mtk17">&gt;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk17">&lt;</span><span class="mtk4">style</span><span class="mtk1"> </span><span class="mtk12">lang</span><span class="mtk1">=</span><span class="mtk8">&quot;scss&quot;</span><span class="mtk17">&gt;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk17">&lt;/</span><span class="mtk4">style</span><span class="mtk17">&gt;</span></span></span></code></pre> <p>As you’ve already noticed, everything is wrapped in a label element to enable the input to react when clicking anywhere within that region. The label element has a built in feature that can automatically toggles the input within it. The span will be used to customize and replace the look and feel of the native html input.</p> <h2 id="customize-css" style="position:relative;"><a href="#customize-css" aria-label="customize css permalink" class="anchor before"><svg aria-hidden="true" focusable="false" height="16" version="1.1" viewBox="0 0 16 16" width="16"><path fill-rule="evenodd" d="M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z"></path></svg></a>Customize CSS</h2> <p>The trick here is to hide the input but still make use of the <code>checked</code> attribute to toggle the style change of the span whenever the state is checked or unchecked. Below is a basic code that triggers the span style change as we click on the label</p> <p><img src="/75f7f91724e6908db3a9834bb38fc4c2/ezgif.com-crop-1-1.gif" alt=""></p> <pre class="grvsc-container default-dark" data-language="html" data-index="3"><code class="grvsc-code"><span class="grvsc-line"><span class="grvsc-source"><span class="mtk17">&lt;</span><span class="mtk4">template</span><span class="mtk17">&gt;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk17">&lt;</span><span class="mtk4">label</span><span class="mtk17">&gt;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk17">&lt;</span><span class="mtk4">input</span><span class="mtk1"> </span><span class="mtk12">type</span><span class="mtk1">=</span><span class="mtk8">&quot;checkbox&quot;</span><span class="mtk1"> </span><span class="mtk17">/&gt;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk17">&lt;</span><span class="mtk4">span</span><span class="mtk17">&gt;&lt;/</span><span class="mtk4">span</span><span class="mtk17">&gt;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk17">&lt;/</span><span class="mtk4">label</span><span class="mtk17">&gt;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk17">&lt;/</span><span class="mtk4">template</span><span class="mtk17">&gt;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk17">&lt;</span><span class="mtk4">script</span><span class="mtk17">&gt;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk15">export</span><span class="mtk1"> </span><span class="mtk15">default</span><span class="mtk1"> {};</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk17">&lt;/</span><span class="mtk4">script</span><span class="mtk17">&gt;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk17">&lt;</span><span class="mtk4">style</span><span class="mtk1"> </span><span class="mtk12">lang</span><span class="mtk1">=</span><span class="mtk8">&quot;scss&quot;</span><span class="mtk17">&gt;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk6">:root</span><span class="mtk1"> {</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">span</span><span class="mtk1"> {</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">width</span><span class="mtk1">: </span><span class="mtk7">15px</span><span class="mtk1">;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">height</span><span class="mtk1">: </span><span class="mtk7">15px</span><span class="mtk1">;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">border</span><span class="mtk1">: </span><span class="mtk7">1px</span><span class="mtk1"> </span><span class="mtk8">solid</span><span class="mtk1"> </span><span class="mtk8">#cccccc</span><span class="mtk1">;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">display</span><span class="mtk1">: </span><span class="mtk8">inline-block</span><span class="mtk1">;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> }</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk6">input</span><span class="mtk1"> {</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">display</span><span class="mtk1">: </span><span class="mtk8">none</span><span class="mtk1">;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> &amp;:checked ~ span {</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk14">background</span><span class="mtk1">: </span><span class="mtk8">#cccccc</span><span class="mtk1">;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> }</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> }</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1">}</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk17">&lt;/</span><span class="mtk4">style</span><span class="mtk17">&gt;</span></span></span></code></pre> <p>Simply all what we did is hide the input using display:none and when the attribute is checked, we change the span background color. Notice that we are using the ”~” operator and it means selecting the sibling. Since span is not a child element of input, we need to let CSS know to change the element right next to the input rather than the child (which is the default behavior).</p> <p>Awesome! Now that we understand how to replace the native input with a span, let’s have some fun and make it look good 🙂</p> <p>Below is the code for styling it as a circle with a check mark:</p> <p><img src="/870a8037a8021d11d8dacd9a5df15d6b/ezgif.com-crop-4.gif" alt=""></p> <pre class="grvsc-container default-dark" data-language="html" data-index="4"><code class="grvsc-code"><span class="grvsc-line"><span class="grvsc-source"><span class="mtk17">&lt;</span><span class="mtk4">template</span><span class="mtk17">&gt;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk17">&lt;</span><span class="mtk4">label</span><span class="mtk17">&gt;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk17">&lt;</span><span class="mtk4">input</span><span class="mtk1"> </span><span class="mtk12">type</span><span class="mtk1">=</span><span class="mtk8">&quot;checkbox&quot;</span><span class="mtk1"> </span><span class="mtk17">/&gt;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk17">&lt;</span><span class="mtk4">span</span><span class="mtk17">&gt;&lt;/</span><span class="mtk4">span</span><span class="mtk17">&gt;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk17">&lt;/</span><span class="mtk4">label</span><span class="mtk17">&gt;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk17">&lt;/</span><span class="mtk4">template</span><span class="mtk17">&gt;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk17">&lt;</span><span class="mtk4">script</span><span class="mtk17">&gt;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk15">export</span><span class="mtk1"> </span><span class="mtk15">default</span><span class="mtk1"> {</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">name:</span><span class="mtk1"> </span><span class="mtk8">&#39;c-checkbox&#39;</span><span class="mtk1">,</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1">};</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk17">&lt;/</span><span class="mtk4">script</span><span class="mtk17">&gt;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk17">&lt;</span><span class="mtk4">style</span><span class="mtk1"> </span><span class="mtk12">lang</span><span class="mtk1">=</span><span class="mtk8">&quot;scss&quot;</span><span class="mtk17">&gt;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk6">:root</span><span class="mtk1"> {</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">label</span><span class="mtk1"> {</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">position</span><span class="mtk1">: </span><span class="mtk8">relative</span><span class="mtk1">;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> }</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk6">span</span><span class="mtk1"> {</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">width</span><span class="mtk1">: </span><span class="mtk7">16px</span><span class="mtk1">;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">height</span><span class="mtk1">: </span><span class="mtk7">16px</span><span class="mtk1">;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">border</span><span class="mtk1">: </span><span class="mtk7">1px</span><span class="mtk1"> </span><span class="mtk8">solid</span><span class="mtk1"> </span><span class="mtk8">#ccc</span><span class="mtk1">;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">display</span><span class="mtk1">: </span><span class="mtk8">inline-block</span><span class="mtk1">;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">border-radius</span><span class="mtk1">: </span><span class="mtk7">50%</span><span class="mtk1">;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">transition</span><span class="mtk1">: </span><span class="mtk8">all</span><span class="mtk1"> </span><span class="mtk8">linear</span><span class="mtk1"> </span><span class="mtk7">0.3s</span><span class="mtk1">;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> &amp;:after {</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk8">content</span><span class="mtk1">: </span><span class="mtk8">&quot;&quot;</span><span class="mtk1">;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">position</span><span class="mtk1">: </span><span class="mtk8">absolute</span><span class="mtk1">;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">top</span><span class="mtk1">: </span><span class="mtk7">-1px</span><span class="mtk1">;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">left</span><span class="mtk1">: </span><span class="mtk7">6px</span><span class="mtk1">;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">border-bottom</span><span class="mtk1">: </span><span class="mtk7">2px</span><span class="mtk1"> </span><span class="mtk8">solid</span><span class="mtk1"> </span><span class="mtk8">#fff</span><span class="mtk1">;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">border-right</span><span class="mtk1">: </span><span class="mtk7">2px</span><span class="mtk1"> </span><span class="mtk8">solid</span><span class="mtk1"> </span><span class="mtk8">#fff</span><span class="mtk1">;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">height</span><span class="mtk1">: </span><span class="mtk7">9px</span><span class="mtk1">;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">width</span><span class="mtk1">: </span><span class="mtk7">4px</span><span class="mtk1">;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">transform</span><span class="mtk1">: </span><span class="mtk11">rotate</span><span class="mtk1">(</span><span class="mtk7">45deg</span><span class="mtk1">);</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">visibility</span><span class="mtk1">: </span><span class="mtk8">hidden</span><span class="mtk1">;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> }</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> }</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk6">input</span><span class="mtk1"> {</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">display</span><span class="mtk1">: </span><span class="mtk8">none</span><span class="mtk1">;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> &amp;:checked ~ span {</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk14">background</span><span class="mtk1">: </span><span class="mtk8">#ccc</span><span class="mtk1">;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> &amp;:after {</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> visibility: </span><span class="mtk8">visible</span><span class="mtk1">;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> }</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> }</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> }</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1">}</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk17">&lt;/</span><span class="mtk4">style</span><span class="mtk17">&gt;</span></span></span></code></pre> <p>Quick summary:</p> <ol> <li>Change the span to a circle by adding a radius 50%.</li> <li>Use <code>::after</code> selector to add content (check mark) within the span element. It will be initially set to visibility:hidden until the element is checked.</li> <li>Create a check mark by making half a rectangle then rotating it 45 degrees using transform:rotate.</li> <li>Finally, when the input is checked, change span:after visibility to visible.</li> <li>The rest is just fine tuning work including some transition to improve the UX.</li> </ol> <h2 id="enable-data-binding" style="position:relative;"><a href="#enable-data-binding" aria-label="enable data binding permalink" class="anchor before"><svg aria-hidden="true" focusable="false" height="16" version="1.1" viewBox="0 0 16 16" width="16"><path fill-rule="evenodd" d="M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z"></path></svg></a>Enable data binding</h2> <p>In many scenarios, the checkbox is used in a form where you need to use <code>v-model</code> for two way binding. To be able to make our custom component work with <code>v-model</code>, we simply need to emit the ‘input’ event with the current checked value.</p> <pre class="grvsc-container default-dark" data-language="html" data-index="5"><code class="grvsc-code"><span class="grvsc-line"><span class="grvsc-source"><span class="mtk17">&lt;</span><span class="mtk4">input</span><span class="mtk1"> </span><span class="mtk12">type</span><span class="mtk1">=</span><span class="mtk8">&quot;checkbox&quot;</span><span class="mtk1"> </span><span class="mtk12">@change</span><span class="mtk1">=</span><span class="mtk8">&quot;$emit(&#39;input&#39;, $event.target.checked)&quot;</span><span class="mtk1"> </span><span class="mtk17">/&gt;</span></span></span></code></pre> <p>Now let’s test data binding in the main home page. We will create a reactive value and attach it to the <code>v-model</code>. Then, display it anywhere on the screen to validate data change when checkbox is toggled.</p> <p><img src="/7dfdb96f2e47f8dd946307db9298e27e/ezgif.com-crop-5.gif" alt=""></p> <pre class="grvsc-container default-dark" data-language="html" data-index="6"><code class="grvsc-code"><span class="grvsc-line"><span class="grvsc-source"><span class="mtk17">&lt;</span><span class="mtk4">template</span><span class="mtk17">&gt;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk17">&lt;</span><span class="mtk4">main</span><span class="mtk17">&gt;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk17">&lt;</span><span class="mtk4">h2</span><span class="mtk17">&gt;</span><span class="mtk1">Custom Checkbox</span><span class="mtk17">&lt;/</span><span class="mtk4">h2</span><span class="mtk17">&gt;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk17">&lt;</span><span class="mtk4">div</span><span class="mtk17">&gt;</span><span class="mtk1">{{ checkedValue }}</span><span class="mtk17">&lt;/</span><span class="mtk4">div</span><span class="mtk17">&gt;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk17">&lt;</span><span class="mtk4">c-checkbox</span><span class="mtk1"> </span><span class="mtk12">v-model</span><span class="mtk1">=</span><span class="mtk8">&quot;checkedValue&quot;</span><span class="mtk17">&gt;&lt;/</span><span class="mtk4">c-checkbox</span><span class="mtk17">&gt;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk17">&lt;/</span><span class="mtk4">main</span><span class="mtk17">&gt;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk17">&lt;/</span><span class="mtk4">template</span><span class="mtk17">&gt;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk17">&lt;</span><span class="mtk4">script</span><span class="mtk17">&gt;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk15">import</span><span class="mtk1"> </span><span class="mtk12">CCheckbox</span><span class="mtk1"> </span><span class="mtk15">from</span><span class="mtk1"> </span><span class="mtk8">&#39;@/components/c-checkbox.vue&#39;</span><span class="mtk1">;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk15">import</span><span class="mtk1"> { </span><span class="mtk12">ref</span><span class="mtk1"> } </span><span class="mtk15">from</span><span class="mtk1"> </span><span class="mtk8">&#39;@vue/composition-api&#39;</span><span class="mtk1">;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk15">export</span><span class="mtk1"> </span><span class="mtk15">default</span><span class="mtk1"> {</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">components:</span><span class="mtk1"> {</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">CCheckbox</span><span class="mtk1">,</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> },</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk11">setup</span><span class="mtk1">() {</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk4">const</span><span class="mtk1"> </span><span class="mtk12">checkedValue</span><span class="mtk1"> = </span><span class="mtk11">ref</span><span class="mtk1">(</span><span class="mtk4">false</span><span class="mtk1">);</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk15">return</span><span class="mtk1"> { </span><span class="mtk12">checkedValue</span><span class="mtk1"> };</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> },</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1">};</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk17">&lt;/</span><span class="mtk4">script</span><span class="mtk17">&gt;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk17">&lt;</span><span class="mtk4">style</span><span class="mtk1"> </span><span class="mtk12">lang</span><span class="mtk1">=</span><span class="mtk8">&quot;scss&quot;</span><span class="mtk17">&gt;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk17">&lt;/</span><span class="mtk4">style</span><span class="mtk17">&gt;</span></span></span></code></pre> <p>Notice that we are using <code>ref(false)</code> and a setup function. This is from Vue’s new <a href="https://www.npmjs.com/package/@vue/composition-api">composition api</a>. You can learn more about it in the <a href="https://composition-api.vuejs.org/">official site’s documentation</a>.</p> <h2 id="enable-color-customization" style="position:relative;"><a href="#enable-color-customization" aria-label="enable color customization permalink" class="anchor before"><svg aria-hidden="true" focusable="false" height="16" version="1.1" viewBox="0 0 16 16" width="16"><path fill-rule="evenodd" d="M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z"></path></svg></a>Enable color customization</h2> <p>Of course, one of the main reasons why we create encapsulated UI components is to make it reusable, modular and customizable all across the project (or multiple projects).</p> <p>Let’s suppose that the developer who is using the component requires to apply different colors in certain scenarios. There are multiple ways to achieve this but today we will explore CSS variables.</p> <p>First, we have three places in our code that requires changes:</p> <ol> <li>Checkbox border color</li> <li>Checkbox background color (when checked)</li> <li>Check mark color</li> </ol> <p>Let’s go ahead and declare variables with default colors at the root of our component. Line 14 and 15.</p> <pre class="grvsc-container default-dark" data-language="html" data-index="7"><code class="grvsc-code"><span class="grvsc-line"><span class="grvsc-source"><span class="mtk17">&lt;</span><span class="mtk4">template</span><span class="mtk17">&gt;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk17">&lt;</span><span class="mtk4">label</span><span class="mtk17">&gt;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk17">&lt;</span><span class="mtk4">input</span><span class="mtk1"> </span><span class="mtk12">type</span><span class="mtk1">=</span><span class="mtk8">&quot;checkbox&quot;</span><span class="mtk1"> </span><span class="mtk12">@change</span><span class="mtk1">=</span><span class="mtk8">&quot;$emit(&#39;input&#39;, $event.target.checked)&quot;</span><span class="mtk1"> </span><span class="mtk17">/&gt;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk17">&lt;</span><span class="mtk4">span</span><span class="mtk17">&gt;&lt;/</span><span class="mtk4">span</span><span class="mtk17">&gt;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk17">&lt;/</span><span class="mtk4">label</span><span class="mtk17">&gt;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk17">&lt;/</span><span class="mtk4">template</span><span class="mtk17">&gt;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk17">&lt;</span><span class="mtk4">script</span><span class="mtk17">&gt;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk15">export</span><span class="mtk1"> </span><span class="mtk15">default</span><span class="mtk1"> {</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">name:</span><span class="mtk1"> </span><span class="mtk8">&#39;c-checkbox&#39;</span><span class="mtk1">,</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1">};</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk17">&lt;/</span><span class="mtk4">script</span><span class="mtk17">&gt;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk17">&lt;</span><span class="mtk4">style</span><span class="mtk1"> </span><span class="mtk12">lang</span><span class="mtk1">=</span><span class="mtk8">&quot;scss&quot;</span><span class="mtk17">&gt;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk6">:root</span><span class="mtk1"> {</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">--checkbox-color</span><span class="mtk1">: </span><span class="mtk8">grey</span><span class="mtk1">;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">--checkmark-color</span><span class="mtk1">: </span><span class="mtk8">white</span><span class="mtk1">;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">label</span><span class="mtk1"> {</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">position</span><span class="mtk1">: </span><span class="mtk8">relative</span><span class="mtk1">;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> }</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk6">span</span><span class="mtk1"> {</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">width</span><span class="mtk1">: </span><span class="mtk7">16px</span><span class="mtk1">;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">height</span><span class="mtk1">: </span><span class="mtk7">16px</span><span class="mtk1">;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">border</span><span class="mtk1">: </span><span class="mtk7">1px</span><span class="mtk1"> </span><span class="mtk8">solid</span><span class="mtk1"> </span><span class="mtk8">#ccc</span><span class="mtk1">;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">display</span><span class="mtk1">: </span><span class="mtk8">inline-block</span><span class="mtk1">;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">border-radius</span><span class="mtk1">: </span><span class="mtk7">50%</span><span class="mtk1">;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">transition</span><span class="mtk1">: </span><span class="mtk8">all</span><span class="mtk1"> </span><span class="mtk8">linear</span><span class="mtk1"> </span><span class="mtk7">0.3s</span><span class="mtk1">;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> &amp;:after {</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk8">content</span><span class="mtk1">: </span><span class="mtk8">&quot;&quot;</span><span class="mtk1">;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">position</span><span class="mtk1">: </span><span class="mtk8">absolute</span><span class="mtk1">;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">top</span><span class="mtk1">: </span><span class="mtk7">-1px</span><span class="mtk1">;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">left</span><span class="mtk1">: </span><span class="mtk7">6px</span><span class="mtk1">;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">border-bottom</span><span class="mtk1">: </span><span class="mtk7">2px</span><span class="mtk1"> </span><span class="mtk8">solid</span><span class="mtk1"> </span><span class="mtk8">#fff</span><span class="mtk1">;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">border-right</span><span class="mtk1">: </span><span class="mtk7">2px</span><span class="mtk1"> </span><span class="mtk8">solid</span><span class="mtk1"> </span><span class="mtk8">#fff</span><span class="mtk1">;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">height</span><span class="mtk1">: </span><span class="mtk7">9px</span><span class="mtk1">;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">width</span><span class="mtk1">: </span><span class="mtk7">4px</span><span class="mtk1">;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">transform</span><span class="mtk1">: </span><span class="mtk11">rotate</span><span class="mtk1">(</span><span class="mtk7">45deg</span><span class="mtk1">);</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">visibility</span><span class="mtk1">: </span><span class="mtk8">hidden</span><span class="mtk1">;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> }</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> }</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk6">input</span><span class="mtk1"> {</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">display</span><span class="mtk1">: </span><span class="mtk8">none</span><span class="mtk1">;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> &amp;:checked ~ span {</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk14">background</span><span class="mtk1">: </span><span class="mtk8">#ccc</span><span class="mtk1">;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> &amp;:after {</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> visibility: </span><span class="mtk8">visible</span><span class="mtk1">;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> }</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> }</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> }</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1">}</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk17">&lt;/</span><span class="mtk4">style</span><span class="mtk17">&gt;</span></span></span></code></pre> <p>Then, let’s replace line 22, 32, 33 and 43 with the appropriate variables.</p> <pre class="grvsc-container default-dark" data-language="html" data-index="8"><code class="grvsc-code"><span class="grvsc-line"><span class="grvsc-source"><span class="mtk17">&lt;</span><span class="mtk4">template</span><span class="mtk17">&gt;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk17">&lt;</span><span class="mtk4">label</span><span class="mtk17">&gt;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk17">&lt;</span><span class="mtk4">input</span><span class="mtk1"> </span><span class="mtk12">type</span><span class="mtk1">=</span><span class="mtk8">&quot;checkbox&quot;</span><span class="mtk1"> </span><span class="mtk12">@change</span><span class="mtk1">=</span><span class="mtk8">&quot;$emit(&#39;input&#39;, $event.target.checked)&quot;</span><span class="mtk1"> </span><span class="mtk17">/&gt;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk17">&lt;</span><span class="mtk4">span</span><span class="mtk17">&gt;&lt;/</span><span class="mtk4">span</span><span class="mtk17">&gt;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk17">&lt;/</span><span class="mtk4">label</span><span class="mtk17">&gt;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk17">&lt;/</span><span class="mtk4">template</span><span class="mtk17">&gt;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk17">&lt;</span><span class="mtk4">script</span><span class="mtk17">&gt;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk15">export</span><span class="mtk1"> </span><span class="mtk15">default</span><span class="mtk1"> {</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">name:</span><span class="mtk1"> </span><span class="mtk8">&#39;c-checkbox&#39;</span><span class="mtk1">,</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1">};</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk17">&lt;/</span><span class="mtk4">script</span><span class="mtk17">&gt;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk17">&lt;</span><span class="mtk4">style</span><span class="mtk1"> </span><span class="mtk12">lang</span><span class="mtk1">=</span><span class="mtk8">&quot;scss&quot;</span><span class="mtk17">&gt;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk6">:root</span><span class="mtk1"> {</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">--checkbox-color</span><span class="mtk1">: </span><span class="mtk8">grey</span><span class="mtk1">;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">--checkmark-color</span><span class="mtk1">: </span><span class="mtk8">white</span><span class="mtk1">;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">label</span><span class="mtk1"> {</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">position</span><span class="mtk1">: </span><span class="mtk8">relative</span><span class="mtk1">;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> }</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk6">span</span><span class="mtk1"> {</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">width</span><span class="mtk1">: </span><span class="mtk7">16px</span><span class="mtk1">;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">height</span><span class="mtk1">: </span><span class="mtk7">16px</span><span class="mtk1">;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">border</span><span class="mtk1">: </span><span class="mtk7">1px</span><span class="mtk1"> </span><span class="mtk8">solid</span><span class="mtk1"> </span><span class="mtk11">var</span><span class="mtk1">(</span><span class="mtk12">--checkbox-color</span><span class="mtk1">);</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">display</span><span class="mtk1">: </span><span class="mtk8">inline-block</span><span class="mtk1">;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">border-radius</span><span class="mtk1">: </span><span class="mtk7">50%</span><span class="mtk1">;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">transition</span><span class="mtk1">: </span><span class="mtk8">all</span><span class="mtk1"> </span><span class="mtk8">linear</span><span class="mtk1"> </span><span class="mtk7">0.3s</span><span class="mtk1">;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> &amp;:after {</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk8">content</span><span class="mtk1">: </span><span class="mtk8">&quot;&quot;</span><span class="mtk1">;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">position</span><span class="mtk1">: </span><span class="mtk8">absolute</span><span class="mtk1">;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">top</span><span class="mtk1">: </span><span class="mtk7">-1px</span><span class="mtk1">;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">left</span><span class="mtk1">: </span><span class="mtk7">6px</span><span class="mtk1">;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">border-bottom</span><span class="mtk1">: </span><span class="mtk7">2px</span><span class="mtk1"> </span><span class="mtk8">solid</span><span class="mtk1"> </span><span class="mtk11">var</span><span class="mtk1">(</span><span class="mtk12">--checkmark-color</span><span class="mtk1">);</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">border-right</span><span class="mtk1">: </span><span class="mtk7">2px</span><span class="mtk1"> </span><span class="mtk8">solid</span><span class="mtk1"> </span><span class="mtk11">var</span><span class="mtk1">(</span><span class="mtk12">--checkmark-color</span><span class="mtk1">);</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">height</span><span class="mtk1">: </span><span class="mtk7">9px</span><span class="mtk1">;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">width</span><span class="mtk1">: </span><span class="mtk7">4px</span><span class="mtk1">;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">transform</span><span class="mtk1">: </span><span class="mtk11">rotate</span><span class="mtk1">(</span><span class="mtk7">45deg</span><span class="mtk1">);</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">visibility</span><span class="mtk1">: </span><span class="mtk8">hidden</span><span class="mtk1">;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> }</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> }</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk6">input</span><span class="mtk1"> {</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">display</span><span class="mtk1">: </span><span class="mtk8">none</span><span class="mtk1">;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> &amp;:checked ~ span {</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk14">background</span><span class="mtk1">: </span><span class="mtk11">var</span><span class="mtk1">(</span><span class="mtk12">--checkbox-color</span><span class="mtk1">);</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> &amp;:after {</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> visibility: </span><span class="mtk8">visible</span><span class="mtk1">;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> }</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> }</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> }</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1">}</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk17">&lt;/</span><span class="mtk4">style</span><span class="mtk17">&gt;</span></span></span></code></pre> <p>Finally, let’s create multiple checkbox components in the home page and assign each different colors.</p> <pre class="grvsc-container default-dark" data-language="html" data-index="9"><code class="grvsc-code"><span class="grvsc-line"><span class="grvsc-source"><span class="mtk17">&lt;</span><span class="mtk4">template</span><span class="mtk17">&gt;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk17">&lt;</span><span class="mtk4">main</span><span class="mtk17">&gt;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk17">&lt;</span><span class="mtk4">h2</span><span class="mtk17">&gt;</span><span class="mtk1">Custom Checkbox</span><span class="mtk17">&lt;/</span><span class="mtk4">h2</span><span class="mtk17">&gt;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk17">&lt;</span><span class="mtk4">div</span><span class="mtk17">&gt;</span><span class="mtk1">{{ checkedValue }}</span><span class="mtk17">&lt;/</span><span class="mtk4">div</span><span class="mtk17">&gt;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk17">&lt;</span><span class="mtk4">c-checkbox</span><span class="mtk1"> </span><span class="mtk12">v-model</span><span class="mtk1">=</span><span class="mtk8">&quot;checkedValue&quot;</span><span class="mtk17">&gt;&lt;/</span><span class="mtk4">c-checkbox</span><span class="mtk17">&gt;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk17">&lt;</span><span class="mtk4">section</span><span class="mtk17">&gt;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk17">&lt;</span><span class="mtk4">c-checkbox</span><span class="mtk1"> </span><span class="mtk12">class</span><span class="mtk1">=</span><span class="mtk8">&quot;checkbox-1&quot;</span><span class="mtk17">&gt;&lt;/</span><span class="mtk4">c-checkbox</span><span class="mtk17">&gt;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk17">&lt;</span><span class="mtk4">c-checkbox</span><span class="mtk1"> </span><span class="mtk12">class</span><span class="mtk1">=</span><span class="mtk8">&quot;checkbox-2&quot;</span><span class="mtk17">&gt;&lt;/</span><span class="mtk4">c-checkbox</span><span class="mtk17">&gt;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk17">&lt;</span><span class="mtk4">c-checkbox</span><span class="mtk1"> </span><span class="mtk12">class</span><span class="mtk1">=</span><span class="mtk8">&quot;checkbox-3&quot;</span><span class="mtk17">&gt;&lt;/</span><span class="mtk4">c-checkbox</span><span class="mtk17">&gt;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk17">&lt;</span><span class="mtk4">c-checkbox</span><span class="mtk1"> </span><span class="mtk12">class</span><span class="mtk1">=</span><span class="mtk8">&quot;checkbox-4&quot;</span><span class="mtk17">&gt;&lt;/</span><span class="mtk4">c-checkbox</span><span class="mtk17">&gt;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk17">&lt;/</span><span class="mtk4">section</span><span class="mtk17">&gt;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk17">&lt;/</span><span class="mtk4">main</span><span class="mtk17">&gt;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk17">&lt;/</span><span class="mtk4">template</span><span class="mtk17">&gt;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk17">&lt;</span><span class="mtk4">script</span><span class="mtk17">&gt;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk15">import</span><span class="mtk1"> </span><span class="mtk12">CCheckbox</span><span class="mtk1"> </span><span class="mtk15">from</span><span class="mtk1"> </span><span class="mtk8">&#39;@/components/c-checkbox.vue&#39;</span><span class="mtk1">;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk15">import</span><span class="mtk1"> { </span><span class="mtk12">ref</span><span class="mtk1"> } </span><span class="mtk15">from</span><span class="mtk1"> </span><span class="mtk8">&#39;@vue/composition-api&#39;</span><span class="mtk1">;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk15">export</span><span class="mtk1"> </span><span class="mtk15">default</span><span class="mtk1"> {</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">components:</span><span class="mtk1"> {</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">CCheckbox</span><span class="mtk1">,</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> },</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk11">setup</span><span class="mtk1">() {</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk4">const</span><span class="mtk1"> </span><span class="mtk12">checkedValue</span><span class="mtk1"> = </span><span class="mtk11">ref</span><span class="mtk1">(</span><span class="mtk4">false</span><span class="mtk1">);</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk15">return</span><span class="mtk1"> { </span><span class="mtk12">checkedValue</span><span class="mtk1"> };</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> },</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1">};</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk17">&lt;/</span><span class="mtk4">script</span><span class="mtk17">&gt;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk17">&lt;</span><span class="mtk4">style</span><span class="mtk1"> </span><span class="mtk12">lang</span><span class="mtk1">=</span><span class="mtk8">&quot;scss&quot;</span><span class="mtk17">&gt;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk6">:root</span><span class="mtk1"> {</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">label</span><span class="mtk1"> {</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">margin-right</span><span class="mtk1">: </span><span class="mtk7">5px</span><span class="mtk1">;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> }</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk6">.checkbox-1</span><span class="mtk1"> {</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">--checkbox-color</span><span class="mtk1">: </span><span class="mtk8">gainsboro</span><span class="mtk1">;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> }</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk6">.checkbox-2</span><span class="mtk1"> {</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">--checkbox-color</span><span class="mtk1">: </span><span class="mtk8">lightpink</span><span class="mtk1">;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">--checkmark-color</span><span class="mtk1">: </span><span class="mtk8">black</span><span class="mtk1">;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> }</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk6">.checkbox-3</span><span class="mtk1"> {</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">--checkbox-color</span><span class="mtk1">: </span><span class="mtk8">paleturquoise</span><span class="mtk1">;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> }</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk6">.checkbox-4</span><span class="mtk1"> {</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">--checkbox-color</span><span class="mtk1">: </span><span class="mtk8">greenyellow</span><span class="mtk1">;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">--checkmark-color</span><span class="mtk1">: </span><span class="mtk8">purple</span><span class="mtk1">;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> }</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1">}</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk17">&lt;/</span><span class="mtk4">style</span><span class="mtk17">&gt;</span></span></span></code></pre> <h2 id="demo" style="position:relative;"><a href="#demo" aria-label="demo permalink" class="anchor before"><svg aria-hidden="true" focusable="false" height="16" version="1.1" viewBox="0 0 16 16" width="16"><path fill-rule="evenodd" d="M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z"></path></svg></a>Demo</h2> <iframe src="https://codesandbox.io/embed/github/muhimasri/vue-custom-checkbox/tree/master/?fontsize=14&amp;hidenavigation=1&amp;theme=dark" style="width:100%; height:500px; border:0; border-radius: 4px; overflow:hidden;" title="custom-checkbox" allow="accelerometer; ambient-light-sensor; camera; encrypted-media; geolocation; gyroscope; hid; microphone; midi; payment; usb; vr; xr-spatial-tracking" sandbox="allow-forms allow-modals allow-popups allow-presentation allow-same-origin allow-scripts"></iframe> <p>You can access the <a href="https://github.com/muhimasri/vue-custom-checkbox">complete repository here</a>.</p> <p>Bye for now 👋</p> <style class="grvsc-styles"> .grvsc-container { overflow: auto; position: relative; -webkit-overflow-scrolling: touch; padding-top: 1rem; padding-top: var(--grvsc-padding-top, var(--grvsc-padding-v, 1rem)); padding-bottom: 1rem; padding-bottom: var(--grvsc-padding-bottom, var(--grvsc-padding-v, 1rem)); border-radius: 8px; border-radius: var(--grvsc-border-radius, 8px); font-feature-settings: normal; line-height: 1.4; } .grvsc-code { display: table; } .grvsc-line { display: table-row; box-sizing: border-box; width: 100%; position: relative; } .grvsc-line > * { position: relative; } .grvsc-gutter-pad { display: table-cell; padding-left: 0.75rem; padding-left: calc(var(--grvsc-padding-left, var(--grvsc-padding-h, 1.5rem)) / 2); } .grvsc-gutter { display: table-cell; -webkit-user-select: none; -moz-user-select: none; user-select: none; } .grvsc-gutter::before { content: attr(data-content); } .grvsc-source { display: table-cell; padding-left: 1.5rem; padding-left: var(--grvsc-padding-left, var(--grvsc-padding-h, 1.5rem)); padding-right: 1.5rem; padding-right: var(--grvsc-padding-right, var(--grvsc-padding-h, 1.5rem)); } .grvsc-source:empty::after { content: ' '; -webkit-user-select: none; -moz-user-select: none; user-select: none; } .grvsc-gutter + .grvsc-source { padding-left: 0.75rem; padding-left: calc(var(--grvsc-padding-left, var(--grvsc-padding-h, 1.5rem)) / 2); } /* Line transformer styles */ .grvsc-has-line-highlighting > .grvsc-code > .grvsc-line::before { content: ' '; position: absolute; width: 100%; } .grvsc-line-diff-add::before { background-color: var(--grvsc-line-diff-add-background-color, rgba(0, 255, 60, 0.2)); } .grvsc-line-diff-del::before { background-color: var(--grvsc-line-diff-del-background-color, rgba(255, 0, 20, 0.2)); } .grvsc-line-number { padding: 0 2px; text-align: right; opacity: 0.7; } .default-dark { background-color: #1E1E1E; color: #D4D4D4; } .default-dark .mtk17 { color: #808080; } .default-dark .mtk4 { color: #569CD6; } .default-dark .mtk15 { color: #C586C0; } .default-dark .mtk1 { color: #D4D4D4; } .default-dark .mtk12 { color: #9CDCFE; } .default-dark .mtk8 { color: #CE9178; } .default-dark .mtk6 { color: #D7BA7D; } .default-dark .mtk7 { color: #B5CEA8; } .default-dark .mtk14 { color: #F44747; } .default-dark .mtk11 { color: #DCDCAA; } .default-dark .grvsc-line-highlighted::before { background-color: var(--grvsc-line-highlighted-background-color, rgba(255, 255, 255, 0.1)); box-shadow: inset var(--grvsc-line-highlighted-border-width, 4px) 0 0 0 var(--grvsc-line-highlighted-border-color, rgba(255, 255, 255, 0.5)); } </style><![CDATA[Convert a form image to an HTML form using Amazon Textract and NodeJS]]>https://muhimasri.comconvert-a-form-image-to-an-html-form-using-amazon-textract-and-nodejshttps://muhimasri.comconvert-a-form-image-to-an-html-form-using-amazon-textract-and-nodejs<p>In this article we will learn how to convert an image (containing a simple form) to an HTML form using Amazon Textract and NodeJS. <a href="https://aws.amazon.com/textract/">Amazon Textract</a> is a service that automatically extracts text and data from scanned documents. It’s an AI powered optical character recognition (OCR) that makes it very simple to accurately pull out content from an image.</p> <p>One of Textract’s strengths is the ability to identify a form in an image and extract the data with its associated relationship. Meaning, if we look at a basic form:</p> <p><span class="gatsby-resp-image-wrapper" style="position: relative; display: block; margin-left: auto; margin-right: auto; max-width: 720px; " > <a class="gatsby-resp-image-link" href="/static/7217c3c7a280159c54c5e1db6171e441/72e01/simple-application-1024x301.jpg" style="display: block" target="_blank" rel="noopener" > <span class="gatsby-resp-image-background-image" style="padding-bottom: 29.444444444444446%; position: relative; bottom: 0; left: 0; background-image: url('data:image/jpeg;base64,/9j/2wBDABALDA4MChAODQ4SERATGCgaGBYWGDEjJR0oOjM9PDkzODdASFxOQERXRTc4UG1RV19iZ2hnPk1xeXBkeFxlZ2P/2wBDARESEhgVGC8aGi9jQjhCY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2P/wgARCAAGABQDASIAAhEBAxEB/8QAFwABAAMAAAAAAAAAAAAAAAAAAAEEBf/EABQBAQAAAAAAAAAAAAAAAAAAAAD/2gAMAwEAAhADEAAAAdSwEg//xAAZEAACAwEAAAAAAAAAAAAAAAAAAQMRISL/2gAIAQEAAQUCUW9Cs//EABQRAQAAAAAAAAAAAAAAAAAAABD/2gAIAQMBAT8BP//EABQRAQAAAAAAAAAAAAAAAAAAABD/2gAIAQIBAT8BP//EABoQAAICAwAAAAAAAAAAAAAAAAARAZECITH/2gAIAQEABj8Caxo7FG0f/8QAGxABAAEFAQAAAAAAAAAAAAAAASEAEBFBgfD/2gAIAQEAAT8hIwCnu7VDLgr/2gAMAwEAAgADAAAAEIPP/8QAFBEBAAAAAAAAAAAAAAAAAAAAEP/aAAgBAwEBPxA//8QAFBEBAAAAAAAAAAAAAAAAAAAAEP/aAAgBAgEBPxA//8QAHBABAAIBBQAAAAAAAAAAAAAAAQARYSExQcHR/9oACAEBAAE/EDy5sRaMVwoyvYNxOQ7n/9k='); background-size: cover; display: block;" ></span> <img class="gatsby-resp-image-image" alt="simple application 1024x301" title="" src="/static/7217c3c7a280159c54c5e1db6171e441/80e3c/simple-application-1024x301.jpg" srcset="/static/7217c3c7a280159c54c5e1db6171e441/4ec73/simple-application-1024x301.jpg 180w, /static/7217c3c7a280159c54c5e1db6171e441/158ba/simple-application-1024x301.jpg 360w, /static/7217c3c7a280159c54c5e1db6171e441/80e3c/simple-application-1024x301.jpg 720w, /static/7217c3c7a280159c54c5e1db6171e441/72e01/simple-application-1024x301.jpg 1024w" sizes="(max-width: 720px) 100vw, 720px" style="width:100%;height:100%;margin:0;vertical-align:middle;position:absolute;top:0;left:0;" loading="lazy" decoding="async" /> </a> </span></p> <p>Textract provides an API that enable us to output the results as follows:</p> <pre class="grvsc-container default-dark" data-language="json" data-index="0"><code class="grvsc-code"><span class="grvsc-line"><span class="grvsc-source"><span class="mtk1">{</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">&quot;Position&quot;</span><span class="mtk1">: </span><span class="mtk8">&quot;Software Developer&quot;</span><span class="mtk1">,</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">&quot;First Name&quot;</span><span class="mtk1">: </span><span class="mtk8">&quot;Muhi&quot;</span><span class="mtk1">,</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">&quot;Last Name&quot;</span><span class="mtk1">: </span><span class="mtk8">&quot;Masri&quot;</span><span class="mtk1">,</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">&quot;Address&quot;</span><span class="mtk1">: </span><span class="mtk8">&quot;Planet Earth&quot;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1">}</span></span></span></code></pre> <p>Pretty cool, right! But getting the desired JSON object is not as simple as calling one function from Textract’s API and in this article we will look at a simplified solution to achieve this.</p> <p>This article will assume that you have an AWS account including S3 storage, access key and secret key. If not, you can still continue reading but I highly recommend to create an <a href="https://aws.amazon.com/account/">AWS Account</a> and get a bit familiar with how it works.</p> <h2 id="create-a-simple-nodejs-app" style="position:relative;"><a href="#create-a-simple-nodejs-app" aria-label="create a simple nodejs app permalink" class="anchor before"><svg aria-hidden="true" focusable="false" height="16" version="1.1" viewBox="0 0 16 16" width="16"><path fill-rule="evenodd" d="M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z"></path></svg></a>Create a simple NodeJS app</h2> <p>We are going to use <a href="https://expressjs.com/en/starter/generator.html">express application generator</a>. It automatically creates a project with html views (using pug) and a routing system. This way, we can easily add an upload function and post the result in a different view</p> <pre class="grvsc-container default-dark" data-language="" data-index="1"><code class="grvsc-code"><span class="grvsc-line"><span class="grvsc-source">mkdir aws-textract-app</span></span> <span class="grvsc-line"><span class="grvsc-source">cd aws-textract-app</span></span> <span class="grvsc-line"><span class="grvsc-source">npx express-generator --view=pug</span></span> <span class="grvsc-line"><span class="grvsc-source">npm install</span></span></code></pre> <p>We simply created a folder and installed express-generator with all the npm dependencies. Here is how your project structure should look like:</p> <p><span class="gatsby-resp-image-wrapper" style="position: relative; display: block; margin-left: auto; margin-right: auto; max-width: 263px; " > <a class="gatsby-resp-image-link" href="/static/0205c9e388fc30c4ab04b77424f33bef/17741/project-structure.png" style="display: block" target="_blank" rel="noopener" > <span class="gatsby-resp-image-background-image" style="padding-bottom: 93.33333333333333%; position: relative; bottom: 0; left: 0; background-image: url('data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABQAAAATCAIAAAAf7rriAAAACXBIWXMAAAsTAAALEwEAmpwYAAABiElEQVR42qWTX2+CMBTF/f4fZtmyl73sfckUHEFEAZWW/w5QwAKlt+yqWdyLotlJQ9qEw49z7+2olwJKreOHsqw45/2vpOwHNZLQyuy9yANFVdM0Pdnu8J3NR/LBxk9w3tV13XUdb9umbXHPeQsgB8iQvlW7UNf0saKs1itjZqjql6JOp8pkX1Q3/gXJIGuKfCEAkYwxAMCD6I4PkAPkBpLXfUbV8XTy+WFa9t2Rz+TGF13TYNC25R3v79Ypc/J8KCJzZmJUTdNk/xg5BsGbumYMF3uU/MTKWNdnWN8gjO5v9UhixaoEy3xgrCj2GPwBMo7BZPKyMHXTnFuOQymRfzRsdl0rS5MkiaM4yne7B8g4j9QL8jxzHMe2LGtp6jNjjXNmGFmW4xs4MzfIgLSyKsIw3G63vofycRNHUd00A2ScQT8MsFRoct0NIS6hNEki4gVkbbvEIxtXXLkeIxCQ5cjObMemhFjLhTE30/Sbev7aWW4IDYNQXL0Y/9DFjOHP7YFLp+B2w34A3TdP77Ro/6wAAAAASUVORK5CYII='); background-size: cover; display: block;" ></span> <img class="gatsby-resp-image-image" alt="project structure" title="" src="/static/0205c9e388fc30c4ab04b77424f33bef/17741/project-structure.png" srcset="/static/0205c9e388fc30c4ab04b77424f33bef/e9ff0/project-structure.png 180w, /static/0205c9e388fc30c4ab04b77424f33bef/17741/project-structure.png 263w" sizes="(max-width: 263px) 100vw, 263px" style="width:100%;height:100%;margin:0;vertical-align:middle;position:absolute;top:0;left:0;" loading="lazy" decoding="async" /> </a> </span></p> <h2 id="upload-an-image-to-your-s3-storage" style="position:relative;"><a href="#upload-an-image-to-your-s3-storage" aria-label="upload an image to your s3 storage permalink" class="anchor before"><svg aria-hidden="true" focusable="false" height="16" version="1.1" viewBox="0 0 16 16" width="16"><path fill-rule="evenodd" d="M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z"></path></svg></a>Upload an image to your S3 storage:</h2> <p>For simplicity sake, we will use the image we have at the beginning of the article that contains 4 inputs (Position, First Name, Last Name and Address)</p> <p>First, let’s add all the required elements to upload a file in the <code>index.pug</code> view</p> <pre class="grvsc-container default-dark" data-language="pug" data-index="2"><code class="grvsc-code"><span class="grvsc-line"><span class="grvsc-source"><span class="mtk4">extends</span><span class="mtk1"> </span><span class="mtk12">layout</span></span></span> <span class="grvsc-line"><span class="grvsc-source"></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk4">block</span><span class="mtk1"> </span><span class="mtk12">content</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk4">h1</span><span class="mtk1">= </span><span class="mtk12">title</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk4">p</span><span class="mtk1"> Welcome to </span><span class="mtk8">#{</span><span class="mtk12">title</span><span class="mtk8">}</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk4">form</span><span class="mtk1">(</span><span class="mtk12">action</span><span class="mtk1">=</span><span class="mtk8">&quot;fileupload&quot;</span><span class="mtk1">, </span><span class="mtk12">method</span><span class="mtk1">=</span><span class="mtk8">&quot;post&quot;</span><span class="mtk1">, </span><span class="mtk12">enctype</span><span class="mtk1">=</span><span class="mtk8">&quot;multipart/form-data&quot;</span><span class="mtk1">) </span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk4">input</span><span class="mtk1">(</span><span class="mtk12">type</span><span class="mtk1">=</span><span class="mtk8">&quot;file&quot;</span><span class="mtk1">, </span><span class="mtk12">name</span><span class="mtk1">=</span><span class="mtk8">&quot;filetoupload&quot;</span><span class="mtk1">)</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk4">input</span><span class="mtk1">(</span><span class="mtk12">type</span><span class="mtk1">=</span><span class="mtk8">&quot;submit&quot;</span><span class="mtk1">, </span><span class="mtk12">value</span><span class="mtk1">=</span><span class="mtk8">&quot;Upload File&quot;</span><span class="mtk1">)</span></span></span></code></pre> <p>Then let’s create a new <code>fileupload.pug</code> view in the view folder to post the results. Also, we will add a simple form to bind the extracted data later on.</p> <pre class="grvsc-container default-dark" data-language="pug" data-index="3"><code class="grvsc-code"><span class="grvsc-line"><span class="grvsc-source"><span class="mtk4">extends</span><span class="mtk1"> </span><span class="mtk12">layout</span></span></span> <span class="grvsc-line"><span class="grvsc-source"></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk4">block</span><span class="mtk1"> </span><span class="mtk12">content</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk4">h1</span><span class="mtk1">= </span><span class="mtk12">title</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk4">div</span><span class="mtk1"> </span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk4">span</span><span class="mtk1"> Position:</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk4">input</span><span class="mtk1">(</span><span class="mtk12">type</span><span class="mtk1">=</span><span class="mtk8">&quot;text&quot;</span><span class="mtk1">, </span><span class="mtk12">name</span><span class="mtk1">=</span><span class="mtk8">&quot;position&quot;</span><span class="mtk1">, </span><span class="mtk12">value</span><span class="mtk1">=</span><span class="mtk8">`</span><span class="mtk4">${</span><span class="mtk12">formData</span><span class="mtk1">[</span><span class="mtk8">&#39;Position&#39;</span><span class="mtk1">]</span><span class="mtk4">}</span><span class="mtk8">`</span><span class="mtk1">)</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk4">div</span><span class="mtk1"> </span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk4">span</span><span class="mtk1"> First Name:</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk4">input</span><span class="mtk1">(</span><span class="mtk12">type</span><span class="mtk1">=</span><span class="mtk8">&quot;text&quot;</span><span class="mtk1">, </span><span class="mtk12">name</span><span class="mtk1">=</span><span class="mtk8">&quot;firstName&quot;</span><span class="mtk1">, </span><span class="mtk12">value</span><span class="mtk1">=</span><span class="mtk8">`</span><span class="mtk4">${</span><span class="mtk12">formData</span><span class="mtk1">[</span><span class="mtk8">&#39;First Name&#39;</span><span class="mtk1">]</span><span class="mtk4">}</span><span class="mtk8">`</span><span class="mtk1">)</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk4">div</span><span class="mtk1"> </span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk4">span</span><span class="mtk1"> Last Name:</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk4">input</span><span class="mtk1">(</span><span class="mtk12">type</span><span class="mtk1">=</span><span class="mtk8">&quot;text&quot;</span><span class="mtk1">, </span><span class="mtk12">name</span><span class="mtk1">=</span><span class="mtk8">&quot;lastName&quot;</span><span class="mtk1">, </span><span class="mtk12">value</span><span class="mtk1">=</span><span class="mtk8">`</span><span class="mtk4">${</span><span class="mtk12">formData</span><span class="mtk1">[</span><span class="mtk8">&#39;Last Name&#39;</span><span class="mtk1">]</span><span class="mtk4">}</span><span class="mtk8">`</span><span class="mtk1">)</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk4">div</span><span class="mtk1"> </span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk4">span</span><span class="mtk1"> Address:</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk4">input</span><span class="mtk1">(</span><span class="mtk12">type</span><span class="mtk1">=</span><span class="mtk8">&quot;text&quot;</span><span class="mtk1">, </span><span class="mtk12">name</span><span class="mtk1">=</span><span class="mtk8">&quot;address&quot;</span><span class="mtk1">, </span><span class="mtk12">value</span><span class="mtk1">=</span><span class="mtk8">`</span><span class="mtk4">${</span><span class="mtk12">formData</span><span class="mtk1">[</span><span class="mtk8">&#39;Address&#39;</span><span class="mtk1">]</span><span class="mtk4">}</span><span class="mtk8">`</span><span class="mtk1">)</span></span></span></code></pre> <p>Now that we have the HTML part done, let’s go ahead and start writing the logic for uploading the file.</p> <p>Let’s start with installing all the dependencies to intercept a file and upload it to the S3 storage.</p> <pre class="grvsc-container default-dark" data-language="" data-index="4"><code class="grvsc-code"><span class="grvsc-line"><span class="grvsc-source">npm i formidable</span></span> <span class="grvsc-line"><span class="grvsc-source">npm i fs</span></span> <span class="grvsc-line"><span class="grvsc-source">npm i aws-sdk</span></span></code></pre> <p>In the routes folder, you should find an <code>index.js</code> file that already has the following code:</p> <pre class="grvsc-container default-dark" data-language="javascript" data-index="5"><code class="grvsc-code"><span class="grvsc-line"><span class="grvsc-source"><span class="mtk4">var</span><span class="mtk1"> </span><span class="mtk12">express</span><span class="mtk1"> = </span><span class="mtk11">require</span><span class="mtk1">(</span><span class="mtk8">&#39;express&#39;</span><span class="mtk1">);</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk4">var</span><span class="mtk1"> </span><span class="mtk12">router</span><span class="mtk1"> = </span><span class="mtk12">express</span><span class="mtk1">.</span><span class="mtk11">Router</span><span class="mtk1">();</span></span></span> <span class="grvsc-line"><span class="grvsc-source"></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk3">/* GET home page. */</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk12">router</span><span class="mtk1">.</span><span class="mtk11">get</span><span class="mtk1">(</span><span class="mtk8">&#39;/&#39;</span><span class="mtk1">, </span><span class="mtk4">function</span><span class="mtk1">(</span><span class="mtk12">req</span><span class="mtk1">, </span><span class="mtk12">res</span><span class="mtk1">, </span><span class="mtk12">next</span><span class="mtk1">) {</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">res</span><span class="mtk1">.</span><span class="mtk11">render</span><span class="mtk1">(</span><span class="mtk8">&#39;index&#39;</span><span class="mtk1">, { </span><span class="mtk12">title:</span><span class="mtk1"> </span><span class="mtk8">&#39;Express&#39;</span><span class="mtk1"> });</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1">});</span></span></span> <span class="grvsc-line"><span class="grvsc-source"></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk10">module</span><span class="mtk1">.</span><span class="mtk10">exports</span><span class="mtk1"> = </span><span class="mtk12">router</span><span class="mtk1">;</span></span></span></code></pre> <p>In the same file, we will include all the dependencies we just installed and add a new post router that handles the <code>fileupload</code> post action in index.pug view.</p> <pre class="grvsc-container default-dark" data-language="javascript" data-index="6"><code class="grvsc-code"><span class="grvsc-line"><span class="grvsc-source"><span class="mtk4">var</span><span class="mtk1"> </span><span class="mtk12">express</span><span class="mtk1"> = </span><span class="mtk11">require</span><span class="mtk1">(</span><span class="mtk8">&#39;express&#39;</span><span class="mtk1">);</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk4">var</span><span class="mtk1"> </span><span class="mtk12">router</span><span class="mtk1"> = </span><span class="mtk12">express</span><span class="mtk1">.</span><span class="mtk11">Router</span><span class="mtk1">();</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk4">const</span><span class="mtk1"> </span><span class="mtk12">formidable</span><span class="mtk1"> = </span><span class="mtk11">require</span><span class="mtk1">(</span><span class="mtk8">&#39;formidable&#39;</span><span class="mtk1">)</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk4">const</span><span class="mtk1"> </span><span class="mtk12">AWS</span><span class="mtk1"> = </span><span class="mtk11">require</span><span class="mtk1">(</span><span class="mtk8">&#39;aws-sdk&#39;</span><span class="mtk1">)</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk4">const</span><span class="mtk1"> </span><span class="mtk12">fs</span><span class="mtk1"> = </span><span class="mtk11">require</span><span class="mtk1">(</span><span class="mtk8">&#39;fs&#39;</span><span class="mtk1">)</span></span></span> <span class="grvsc-line"><span class="grvsc-source"></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk3">/* GET home page. */</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk12">router</span><span class="mtk1">.</span><span class="mtk11">get</span><span class="mtk1">(</span><span class="mtk8">&#39;/&#39;</span><span class="mtk1">, </span><span class="mtk4">function</span><span class="mtk1">(</span><span class="mtk12">req</span><span class="mtk1">, </span><span class="mtk12">res</span><span class="mtk1">, </span><span class="mtk12">next</span><span class="mtk1">) {</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">res</span><span class="mtk1">.</span><span class="mtk11">render</span><span class="mtk1">(</span><span class="mtk8">&#39;index&#39;</span><span class="mtk1">, { </span><span class="mtk12">title:</span><span class="mtk1"> </span><span class="mtk8">&#39;Express&#39;</span><span class="mtk1"> });</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1">});</span></span></span> <span class="grvsc-line"><span class="grvsc-source"></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk12">router</span><span class="mtk1">.</span><span class="mtk11">post</span><span class="mtk1">(</span><span class="mtk8">&#39;/fileupload&#39;</span><span class="mtk1">, (</span><span class="mtk12">req</span><span class="mtk1">, </span><span class="mtk12">res</span><span class="mtk1">, </span><span class="mtk12">next</span><span class="mtk1">) </span><span class="mtk4">=&gt;</span><span class="mtk1"> {</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk3">// Upload logic</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1">}</span></span></span> <span class="grvsc-line"><span class="grvsc-source"></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk10">module</span><span class="mtk1">.</span><span class="mtk10">exports</span><span class="mtk1"> = </span><span class="mtk12">router</span><span class="mtk1">;</span></span></span></code></pre> <p>And then below we will add the implementation for the upload logic:</p> <pre class="grvsc-container default-dark" data-language="javascript" data-index="7"><code class="grvsc-code"><span class="grvsc-line"><span class="grvsc-source"><span class="mtk12">router</span><span class="mtk1">.</span><span class="mtk11">post</span><span class="mtk1">(</span><span class="mtk8">&#39;/fileupload&#39;</span><span class="mtk1">, (</span><span class="mtk12">req</span><span class="mtk1">, </span><span class="mtk12">res</span><span class="mtk1">, </span><span class="mtk12">next</span><span class="mtk1">) </span><span class="mtk4">=&gt;</span><span class="mtk1"> {</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk3">// Upload logic</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk4">const</span><span class="mtk1"> </span><span class="mtk12">form</span><span class="mtk1"> = </span><span class="mtk4">new</span><span class="mtk1"> </span><span class="mtk10">formidable</span><span class="mtk1">.</span><span class="mtk10">IncomingForm</span><span class="mtk1">()</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">form</span><span class="mtk1">.</span><span class="mtk11">parse</span><span class="mtk1">(</span><span class="mtk12">req</span><span class="mtk1">, </span><span class="mtk4">async</span><span class="mtk1"> (</span><span class="mtk12">err</span><span class="mtk1">, </span><span class="mtk12">fields</span><span class="mtk1">, </span><span class="mtk12">files</span><span class="mtk1">) </span><span class="mtk4">=&gt;</span><span class="mtk1"> {</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk15">if</span><span class="mtk1"> (</span><span class="mtk12">err</span><span class="mtk1">) {</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk10">console</span><span class="mtk1">.</span><span class="mtk11">error</span><span class="mtk1">(</span><span class="mtk12">err</span><span class="mtk1">)</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> }</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk4">const</span><span class="mtk1"> </span><span class="mtk12">fileContent</span><span class="mtk1"> = </span><span class="mtk12">fs</span><span class="mtk1">.</span><span class="mtk11">readFileSync</span><span class="mtk1">(</span><span class="mtk12">files</span><span class="mtk1">.</span><span class="mtk12">filetoupload</span><span class="mtk1">.</span><span class="mtk12">path</span><span class="mtk1">)</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk4">const</span><span class="mtk1"> </span><span class="mtk12">s3Params</span><span class="mtk1"> = {</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">Bucket:</span><span class="mtk1"> </span><span class="mtk12">process</span><span class="mtk1">.</span><span class="mtk12">env</span><span class="mtk1">.</span><span class="mtk12">AWS_BUCKET</span><span class="mtk1">,</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">Key:</span><span class="mtk1"> </span><span class="mtk8">`</span><span class="mtk4">${</span><span class="mtk10">Date</span><span class="mtk1">.</span><span class="mtk11">now</span><span class="mtk1">().</span><span class="mtk11">toString</span><span class="mtk1">()</span><span class="mtk4">}</span><span class="mtk8">-</span><span class="mtk4">${</span><span class="mtk12">files</span><span class="mtk1">.</span><span class="mtk12">filetoupload</span><span class="mtk1">.</span><span class="mtk12">name</span><span class="mtk4">}</span><span class="mtk8">`</span><span class="mtk1">,</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">Body:</span><span class="mtk1"> </span><span class="mtk12">fileContent</span><span class="mtk1">,</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">ContentType:</span><span class="mtk1"> </span><span class="mtk12">files</span><span class="mtk1">.</span><span class="mtk12">filetoupload</span><span class="mtk1">.</span><span class="mtk12">type</span><span class="mtk1">,</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">ACL:</span><span class="mtk1"> </span><span class="mtk8">&#39;public-read&#39;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> }</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk4">const</span><span class="mtk1"> </span><span class="mtk12">s3Content</span><span class="mtk1"> = </span><span class="mtk15">await</span><span class="mtk1"> </span><span class="mtk11">s3Upload</span><span class="mtk1">(</span><span class="mtk12">s3Params</span><span class="mtk1">)</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk3">// Textract code will be added here</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> })</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1">})</span></span></span> <span class="grvsc-line"><span class="grvsc-source"></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk4">async</span><span class="mtk1"> </span><span class="mtk4">function</span><span class="mtk1"> </span><span class="mtk11">s3Upload</span><span class="mtk1"> (</span><span class="mtk12">params</span><span class="mtk1">) {</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk4">const</span><span class="mtk1"> </span><span class="mtk12">s3</span><span class="mtk1"> = </span><span class="mtk4">new</span><span class="mtk1"> </span><span class="mtk10">AWS</span><span class="mtk1">.</span><span class="mtk10">S3</span><span class="mtk1">({</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">accessKeyId:</span><span class="mtk1"> </span><span class="mtk12">process</span><span class="mtk1">.</span><span class="mtk12">env</span><span class="mtk1">.</span><span class="mtk12">AWS_ACCESS_KEY</span><span class="mtk1">,</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">secretAccessKey:</span><span class="mtk1"> </span><span class="mtk12">process</span><span class="mtk1">.</span><span class="mtk12">env</span><span class="mtk1">.</span><span class="mtk12">AWS_SECRET_KEY</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> })</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk15">return</span><span class="mtk1"> </span><span class="mtk4">new</span><span class="mtk1"> </span><span class="mtk10">Promise</span><span class="mtk1">(</span><span class="mtk12">resolve</span><span class="mtk1"> </span><span class="mtk4">=&gt;</span><span class="mtk1"> {</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">s3</span><span class="mtk1">.</span><span class="mtk11">upload</span><span class="mtk1">(</span><span class="mtk12">params</span><span class="mtk1">, (</span><span class="mtk12">err</span><span class="mtk1">, </span><span class="mtk12">data</span><span class="mtk1">) </span><span class="mtk4">=&gt;</span><span class="mtk1"> {</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk15">if</span><span class="mtk1"> (</span><span class="mtk12">err</span><span class="mtk1">) {</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk10">console</span><span class="mtk1">.</span><span class="mtk11">error</span><span class="mtk1">(</span><span class="mtk12">err</span><span class="mtk1">)</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk11">resolve</span><span class="mtk1">(</span><span class="mtk12">err</span><span class="mtk1">)</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> } </span><span class="mtk15">else</span><span class="mtk1"> {</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk11">resolve</span><span class="mtk1">(</span><span class="mtk12">data</span><span class="mtk1">)</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> }</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> })</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> })</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1">}</span></span></span></code></pre> <p>Quick summary of what we just did:</p> <ol> <li>Parsed the form using formidable.</li> <li>Read the content of the file and assigned it as a value to the <code>Body</code> property (along with other required properties) in the AWS upload parameters.</li> <li>Created an async <code>s3Upload</code> function that returns the results in the variable <code>s3Content</code>. The information in this variable will be used for the Textract reader in the next step.</li> </ol> <p>At this point, you should be able to run the Node app and upload an image directly to your S3 bucket. Awesome job!</p> <h2 id="analyse-a-document-directly-from-s3-bucket-usingtextractapi" style="position:relative;"><a href="#analyse-a-document-directly-from-s3-bucket-usingtextractapi" aria-label="analyse a document directly from s3 bucket usingtextractapi permalink" class="anchor before"><svg aria-hidden="true" focusable="false" height="16" version="1.1" viewBox="0 0 16 16" width="16"><path fill-rule="evenodd" d="M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z"></path></svg></a>Analyse a document directly from S3 bucket using Textract API</h2> <p>Let’s create a function called <code>documentExtract</code> that takes the S3 object key as a parameter and then returns all the data extracted from the image.</p> <pre class="grvsc-container default-dark" data-language="javascript" data-index="8"><code class="grvsc-code"><span class="grvsc-line"><span class="grvsc-source"><span class="mtk4">async</span><span class="mtk1"> </span><span class="mtk4">function</span><span class="mtk1"> </span><span class="mtk11">documentExtract</span><span class="mtk1"> (</span><span class="mtk12">key</span><span class="mtk1">) {</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk15">return</span><span class="mtk1"> </span><span class="mtk4">new</span><span class="mtk1"> </span><span class="mtk10">Promise</span><span class="mtk1">(</span><span class="mtk12">resolve</span><span class="mtk1"> </span><span class="mtk4">=&gt;</span><span class="mtk1"> {</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk4">var</span><span class="mtk1"> </span><span class="mtk12">textract</span><span class="mtk1"> = </span><span class="mtk4">new</span><span class="mtk1"> </span><span class="mtk10">AWS</span><span class="mtk1">.</span><span class="mtk10">Textract</span><span class="mtk1">({</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">region:</span><span class="mtk1"> </span><span class="mtk12">process</span><span class="mtk1">.</span><span class="mtk12">env</span><span class="mtk1">.</span><span class="mtk12">AWS_REGION</span><span class="mtk1">,</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">endpoint:</span><span class="mtk1"> </span><span class="mtk8">`https://textract.</span><span class="mtk4">${</span><span class="mtk12">process</span><span class="mtk1">.</span><span class="mtk12">env</span><span class="mtk1">.</span><span class="mtk12">AWS_REGION</span><span class="mtk4">}</span><span class="mtk8">.amazonaws.com/`</span><span class="mtk1">,</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">accessKeyId:</span><span class="mtk1"> </span><span class="mtk12">process</span><span class="mtk1">.</span><span class="mtk12">env</span><span class="mtk1">.</span><span class="mtk12">AWS_ACCESS_KEY</span><span class="mtk1">,</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">secretAccessKey:</span><span class="mtk1"> </span><span class="mtk12">process</span><span class="mtk1">.</span><span class="mtk12">env</span><span class="mtk1">.</span><span class="mtk12">AWS_SECRET_KEY</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> })</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk4">var</span><span class="mtk1"> </span><span class="mtk12">params</span><span class="mtk1"> = {</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">Document:</span><span class="mtk1"> {</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">S3Object:</span><span class="mtk1"> {</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">Bucket:</span><span class="mtk1"> </span><span class="mtk12">process</span><span class="mtk1">.</span><span class="mtk12">env</span><span class="mtk1">.</span><span class="mtk12">AWS_BUCKET</span><span class="mtk1">,</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">Name:</span><span class="mtk1"> </span><span class="mtk12">key</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> }</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> },</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">FeatureTypes:</span><span class="mtk1"> [</span><span class="mtk8">&#39;FORMS&#39;</span><span class="mtk1">]</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> }</span></span></span> <span class="grvsc-line"><span class="grvsc-source"></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">textract</span><span class="mtk1">.</span><span class="mtk11">analyzeDocument</span><span class="mtk1">(</span><span class="mtk12">params</span><span class="mtk1">, (</span><span class="mtk12">err</span><span class="mtk1">, </span><span class="mtk12">data</span><span class="mtk1">) </span><span class="mtk4">=&gt;</span><span class="mtk1"> {</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk15">if</span><span class="mtk1"> (</span><span class="mtk12">err</span><span class="mtk1">) {</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk15">return</span><span class="mtk1"> </span><span class="mtk11">resolve</span><span class="mtk1">(</span><span class="mtk12">err</span><span class="mtk1">)</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> } </span><span class="mtk15">else</span><span class="mtk1"> {</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk11">resolve</span><span class="mtk1">(</span><span class="mtk12">data</span><span class="mtk1">)</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> }</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> })</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> })</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1">}</span></span></span></code></pre> <p>Similar to the S3 upload process we did earlier, the Textract API will require information about your region, access key, bucket name…</p> <p>You will notice that we have a property called <code>FeatureTypes</code> and a value <code>FORMS</code>, this is very important as it let Textract do its magic and return Key-Value sets to help us associate input fields with the proper labels (i.e. “Software Developer” belongs to “Position”, “Planet Earth” belongs to “Address” and so on)</p> <p>Now let’s insert this function right after the S3 upload process and log the results. Our <code>index.js</code> code should look like this so far:</p> <pre class="grvsc-container default-dark" data-language="javascript" data-index="9"><code class="grvsc-code"><span class="grvsc-line"><span class="grvsc-source"><span class="mtk4">const</span><span class="mtk1"> </span><span class="mtk12">express</span><span class="mtk1"> = </span><span class="mtk11">require</span><span class="mtk1">(</span><span class="mtk8">&#39;express&#39;</span><span class="mtk1">)</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk4">const</span><span class="mtk1"> </span><span class="mtk12">router</span><span class="mtk1"> = </span><span class="mtk12">express</span><span class="mtk1">.</span><span class="mtk11">Router</span><span class="mtk1">()</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk4">const</span><span class="mtk1"> </span><span class="mtk12">formidable</span><span class="mtk1"> = </span><span class="mtk11">require</span><span class="mtk1">(</span><span class="mtk8">&#39;formidable&#39;</span><span class="mtk1">)</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk4">const</span><span class="mtk1"> </span><span class="mtk12">AWS</span><span class="mtk1"> = </span><span class="mtk11">require</span><span class="mtk1">(</span><span class="mtk8">&#39;aws-sdk&#39;</span><span class="mtk1">)</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk4">const</span><span class="mtk1"> </span><span class="mtk12">fs</span><span class="mtk1"> = </span><span class="mtk11">require</span><span class="mtk1">(</span><span class="mtk8">&#39;fs&#39;</span><span class="mtk1">)</span></span></span> <span class="grvsc-line"><span class="grvsc-source"></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk3">/* GET home page. */</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk12">router</span><span class="mtk1">.</span><span class="mtk11">get</span><span class="mtk1">(</span><span class="mtk8">&#39;/&#39;</span><span class="mtk1">, (</span><span class="mtk12">req</span><span class="mtk1">, </span><span class="mtk12">res</span><span class="mtk1">, </span><span class="mtk12">next</span><span class="mtk1">) </span><span class="mtk4">=&gt;</span><span class="mtk1"> {</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">res</span><span class="mtk1">.</span><span class="mtk11">render</span><span class="mtk1">(</span><span class="mtk8">&#39;index&#39;</span><span class="mtk1">, { </span><span class="mtk12">title:</span><span class="mtk1"> </span><span class="mtk8">&#39;Textract Uploader&#39;</span><span class="mtk1"> })</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1">})</span></span></span> <span class="grvsc-line"><span class="grvsc-source"></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk12">router</span><span class="mtk1">.</span><span class="mtk11">post</span><span class="mtk1">(</span><span class="mtk8">&#39;/fileupload&#39;</span><span class="mtk1">, (</span><span class="mtk12">req</span><span class="mtk1">, </span><span class="mtk12">res</span><span class="mtk1">, </span><span class="mtk12">next</span><span class="mtk1">) </span><span class="mtk4">=&gt;</span><span class="mtk1"> {</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk3">// Upload logic</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk4">const</span><span class="mtk1"> </span><span class="mtk12">form</span><span class="mtk1"> = </span><span class="mtk4">new</span><span class="mtk1"> </span><span class="mtk10">formidable</span><span class="mtk1">.</span><span class="mtk10">IncomingForm</span><span class="mtk1">()</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">form</span><span class="mtk1">.</span><span class="mtk11">parse</span><span class="mtk1">(</span><span class="mtk12">req</span><span class="mtk1">, </span><span class="mtk4">async</span><span class="mtk1"> (</span><span class="mtk12">err</span><span class="mtk1">, </span><span class="mtk12">fields</span><span class="mtk1">, </span><span class="mtk12">files</span><span class="mtk1">) </span><span class="mtk4">=&gt;</span><span class="mtk1"> {</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk15">if</span><span class="mtk1"> (</span><span class="mtk12">err</span><span class="mtk1">) {</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk10">console</span><span class="mtk1">.</span><span class="mtk11">error</span><span class="mtk1">(</span><span class="mtk12">err</span><span class="mtk1">)</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> }</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk4">const</span><span class="mtk1"> </span><span class="mtk12">fileContent</span><span class="mtk1"> = </span><span class="mtk12">fs</span><span class="mtk1">.</span><span class="mtk11">readFileSync</span><span class="mtk1">(</span><span class="mtk12">files</span><span class="mtk1">.</span><span class="mtk12">filetoupload</span><span class="mtk1">.</span><span class="mtk12">path</span><span class="mtk1">)</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk4">const</span><span class="mtk1"> </span><span class="mtk12">s3Params</span><span class="mtk1"> = {</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">Bucket:</span><span class="mtk1"> </span><span class="mtk12">process</span><span class="mtk1">.</span><span class="mtk12">env</span><span class="mtk1">.</span><span class="mtk12">AWS_BUCKET</span><span class="mtk1">,</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">Key:</span><span class="mtk1"> </span><span class="mtk8">`</span><span class="mtk4">${</span><span class="mtk10">Date</span><span class="mtk1">.</span><span class="mtk11">now</span><span class="mtk1">().</span><span class="mtk11">toString</span><span class="mtk1">()</span><span class="mtk4">}</span><span class="mtk8">-</span><span class="mtk4">${</span><span class="mtk12">files</span><span class="mtk1">.</span><span class="mtk12">filetoupload</span><span class="mtk1">.</span><span class="mtk12">name</span><span class="mtk4">}</span><span class="mtk8">`</span><span class="mtk1">,</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">Body:</span><span class="mtk1"> </span><span class="mtk12">fileContent</span><span class="mtk1">,</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">ContentType:</span><span class="mtk1"> </span><span class="mtk12">files</span><span class="mtk1">.</span><span class="mtk12">filetoupload</span><span class="mtk1">.</span><span class="mtk12">type</span><span class="mtk1">,</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">ACL:</span><span class="mtk1"> </span><span class="mtk8">&#39;public-read&#39;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> }</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk4">const</span><span class="mtk1"> </span><span class="mtk12">s3Content</span><span class="mtk1"> = </span><span class="mtk15">await</span><span class="mtk1"> </span><span class="mtk11">s3Upload</span><span class="mtk1">(</span><span class="mtk12">s3Params</span><span class="mtk1">)</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk4">const</span><span class="mtk1"> </span><span class="mtk12">textractData</span><span class="mtk1"> = </span><span class="mtk15">await</span><span class="mtk1"> </span><span class="mtk11">documentExtract</span><span class="mtk1">(</span><span class="mtk12">s3Content</span><span class="mtk1">.</span><span class="mtk12">Key</span><span class="mtk1">)</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk10">console</span><span class="mtk1">.</span><span class="mtk11">log</span><span class="mtk1">(</span><span class="mtk12">textractData</span><span class="mtk1">)</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> })</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1">})</span></span></span> <span class="grvsc-line"><span class="grvsc-source"></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk4">async</span><span class="mtk1"> </span><span class="mtk4">function</span><span class="mtk1"> </span><span class="mtk11">s3Upload</span><span class="mtk1"> (</span><span class="mtk12">params</span><span class="mtk1">) {</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk4">const</span><span class="mtk1"> </span><span class="mtk12">s3</span><span class="mtk1"> = </span><span class="mtk4">new</span><span class="mtk1"> </span><span class="mtk10">AWS</span><span class="mtk1">.</span><span class="mtk10">S3</span><span class="mtk1">({</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">accessKeyId:</span><span class="mtk1"> </span><span class="mtk12">process</span><span class="mtk1">.</span><span class="mtk12">env</span><span class="mtk1">.</span><span class="mtk12">AWS_ACCESS_KEY</span><span class="mtk1">,</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">secretAccessKey:</span><span class="mtk1"> </span><span class="mtk12">process</span><span class="mtk1">.</span><span class="mtk12">env</span><span class="mtk1">.</span><span class="mtk12">AWS_SECRET_KEY</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> })</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk15">return</span><span class="mtk1"> </span><span class="mtk4">new</span><span class="mtk1"> </span><span class="mtk10">Promise</span><span class="mtk1">(</span><span class="mtk12">resolve</span><span class="mtk1"> </span><span class="mtk4">=&gt;</span><span class="mtk1"> {</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">s3</span><span class="mtk1">.</span><span class="mtk11">upload</span><span class="mtk1">(</span><span class="mtk12">params</span><span class="mtk1">, (</span><span class="mtk12">err</span><span class="mtk1">, </span><span class="mtk12">data</span><span class="mtk1">) </span><span class="mtk4">=&gt;</span><span class="mtk1"> {</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk15">if</span><span class="mtk1"> (</span><span class="mtk12">err</span><span class="mtk1">) {</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk10">console</span><span class="mtk1">.</span><span class="mtk11">error</span><span class="mtk1">(</span><span class="mtk12">err</span><span class="mtk1">)</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk11">resolve</span><span class="mtk1">(</span><span class="mtk12">err</span><span class="mtk1">)</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> } </span><span class="mtk15">else</span><span class="mtk1"> {</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk11">resolve</span><span class="mtk1">(</span><span class="mtk12">data</span><span class="mtk1">)</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> }</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> })</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> })</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1">}</span></span></span> <span class="grvsc-line"><span class="grvsc-source"></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk4">async</span><span class="mtk1"> </span><span class="mtk4">function</span><span class="mtk1"> </span><span class="mtk11">documentExtract</span><span class="mtk1"> (</span><span class="mtk12">key</span><span class="mtk1">) {</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk15">return</span><span class="mtk1"> </span><span class="mtk4">new</span><span class="mtk1"> </span><span class="mtk10">Promise</span><span class="mtk1">(</span><span class="mtk12">resolve</span><span class="mtk1"> </span><span class="mtk4">=&gt;</span><span class="mtk1"> {</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk4">var</span><span class="mtk1"> </span><span class="mtk12">textract</span><span class="mtk1"> = </span><span class="mtk4">new</span><span class="mtk1"> </span><span class="mtk10">AWS</span><span class="mtk1">.</span><span class="mtk10">Textract</span><span class="mtk1">({</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">region:</span><span class="mtk1"> </span><span class="mtk12">process</span><span class="mtk1">.</span><span class="mtk12">env</span><span class="mtk1">.</span><span class="mtk12">AWS_REGION</span><span class="mtk1">,</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">endpoint:</span><span class="mtk1"> </span><span class="mtk8">`https://textract.</span><span class="mtk4">${</span><span class="mtk12">process</span><span class="mtk1">.</span><span class="mtk12">env</span><span class="mtk1">.</span><span class="mtk12">AWS_REGION</span><span class="mtk4">}</span><span class="mtk8">.amazonaws.com/`</span><span class="mtk1">,</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">accessKeyId:</span><span class="mtk1"> </span><span class="mtk12">process</span><span class="mtk1">.</span><span class="mtk12">env</span><span class="mtk1">.</span><span class="mtk12">AWS_ACCESS_KEY</span><span class="mtk1">,</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">secretAccessKey:</span><span class="mtk1"> </span><span class="mtk12">process</span><span class="mtk1">.</span><span class="mtk12">env</span><span class="mtk1">.</span><span class="mtk12">AWS_SECRET_KEY</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> })</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk4">var</span><span class="mtk1"> </span><span class="mtk12">params</span><span class="mtk1"> = {</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">Document:</span><span class="mtk1"> {</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">S3Object:</span><span class="mtk1"> {</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">Bucket:</span><span class="mtk1"> </span><span class="mtk12">process</span><span class="mtk1">.</span><span class="mtk12">env</span><span class="mtk1">.</span><span class="mtk12">AWS_BUCKET</span><span class="mtk1">,</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">Name:</span><span class="mtk1"> </span><span class="mtk12">key</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> }</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> },</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">FeatureTypes:</span><span class="mtk1"> [</span><span class="mtk8">&#39;FORMS&#39;</span><span class="mtk1">]</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> }</span></span></span> <span class="grvsc-line"><span class="grvsc-source"></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">textract</span><span class="mtk1">.</span><span class="mtk11">analyzeDocument</span><span class="mtk1">(</span><span class="mtk12">params</span><span class="mtk1">, (</span><span class="mtk12">err</span><span class="mtk1">, </span><span class="mtk12">data</span><span class="mtk1">) </span><span class="mtk4">=&gt;</span><span class="mtk1"> {</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk15">if</span><span class="mtk1"> (</span><span class="mtk12">err</span><span class="mtk1">) {</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk15">return</span><span class="mtk1"> </span><span class="mtk11">resolve</span><span class="mtk1">(</span><span class="mtk12">err</span><span class="mtk1">)</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> } </span><span class="mtk15">else</span><span class="mtk1"> {</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk11">resolve</span><span class="mtk1">(</span><span class="mtk12">data</span><span class="mtk1">)</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> }</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> })</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> })</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1">}</span></span></span> <span class="grvsc-line"><span class="grvsc-source"></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk10">module</span><span class="mtk1">.</span><span class="mtk10">exports</span><span class="mtk1"> = </span><span class="mtk12">router</span></span></span></code></pre> <p>When running the code, the console will print a list of JSON objects were each object represents a block with a unique id, list of relationships and other related properties. Let’s take this as an example:</p> <pre class="grvsc-container default-dark" data-language="json" data-index="10"><code class="grvsc-code"><span class="grvsc-line"><span class="grvsc-source"><span class="mtk1">{</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">&quot;BlockType&quot;</span><span class="mtk1">: </span><span class="mtk8">&quot;KEY_VALUE_SET&quot;</span><span class="mtk1">,</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">&quot;Confidence&quot;</span><span class="mtk1">: </span><span class="mtk7">80.23428344726562</span><span class="mtk1">,</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">&quot;Geometry&quot;</span><span class="mtk1">: {</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">&quot;BoundingBox&quot;</span><span class="mtk1">: {</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">&quot;Width&quot;</span><span class="mtk1">: </span><span class="mtk7">0.0715109333395958</span><span class="mtk1">,</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">&quot;Height&quot;</span><span class="mtk1">: </span><span class="mtk7">0.043582554906606674</span><span class="mtk1">,</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">&quot;Left&quot;</span><span class="mtk1">: </span><span class="mtk7">0.018339848145842552</span><span class="mtk1">,</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">&quot;Top&quot;</span><span class="mtk1">: </span><span class="mtk7">0.4098675847053528</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> },</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">&quot;Polygon&quot;</span><span class="mtk1">: [{</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">&quot;X&quot;</span><span class="mtk1">: </span><span class="mtk7">0.018339848145842552</span><span class="mtk1">,</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">&quot;Y&quot;</span><span class="mtk1">: </span><span class="mtk7">0.4098675847053528</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> }, {</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">&quot;X&quot;</span><span class="mtk1">: </span><span class="mtk7">0.0898507833480835</span><span class="mtk1">,</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">&quot;Y&quot;</span><span class="mtk1">: </span><span class="mtk7">0.4098675847053528</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> }, {</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">&quot;X&quot;</span><span class="mtk1">: </span><span class="mtk7">0.0898507833480835</span><span class="mtk1">,</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">&quot;Y&quot;</span><span class="mtk1">: </span><span class="mtk7">0.45345014333724976</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> }, {</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">&quot;X&quot;</span><span class="mtk1">: </span><span class="mtk7">0.018339848145842552</span><span class="mtk1">,</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">&quot;Y&quot;</span><span class="mtk1">: </span><span class="mtk7">0.45345014333724976</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> }]</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> },</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">&quot;Id&quot;</span><span class="mtk1">: </span><span class="mtk8">&quot;c3d7521b-0371-4ca1-9607-0864f2edcfdd&quot;</span><span class="mtk1">,</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">&quot;Relationships&quot;</span><span class="mtk1">: [{</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">&quot;Type&quot;</span><span class="mtk1">: </span><span class="mtk8">&quot;VALUE&quot;</span><span class="mtk1">,</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">&quot;Ids&quot;</span><span class="mtk1">: [</span><span class="mtk8">&quot;e294a18d-8db3-4369-bec4-e15b882e6563&quot;</span><span class="mtk1">]</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> }, {</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">&quot;Type&quot;</span><span class="mtk1">: </span><span class="mtk8">&quot;CHILD&quot;</span><span class="mtk1">,</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">&quot;Ids&quot;</span><span class="mtk1">: [</span><span class="mtk8">&quot;9eaa014f-03ce-4722-9665-3bd94aea60ec&quot;</span><span class="mtk1">, </span><span class="mtk8">&quot;8471eed1-9caf-45df-bd6a-e639f6caa9d4&quot;</span><span class="mtk1">]</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> }],</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">&quot;EntityTypes&quot;</span><span class="mtk1">: [</span><span class="mtk8">&quot;KEY&quot;</span><span class="mtk1">]</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> }</span></span></span></code></pre> <p>Whenever the BlockType is <code>KEY_VALUE_SET</code>, it means that it has a relationship property that connects associated objects together. In this specific block, we can figure the relationship between “Position” and “Software Developer” by looking up the “Ids” in the “Relationships” object. To understand how it works in more details, you can checkout Amazon’s <a href="https://docs.aws.amazon.com/textract/latest/dg/how-it-works-kvp.html">Developers Guide</a>.</p> <h2 id="use-aws-textracthelper-to-extract-the-form-data-as-a-json-object" style="position:relative;"><a href="#use-aws-textracthelper-to-extract-the-form-data-as-a-json-object" aria-label="use aws textracthelper to extract the form data as a json object permalink" class="anchor before"><svg aria-hidden="true" focusable="false" height="16" version="1.1" viewBox="0 0 16 16" width="16"><path fill-rule="evenodd" d="M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z"></path></svg></a>Use AWS Textract Helper to extract the form data as a JSON object</h2> <p>To simplify the process of finding all relationships and save you from writing several functions, I created an <a href="https://www.npmjs.com/package/aws-textract-helper">AWS Textract Helper</a> module to do the job in just one hit.</p> <p>Let’s install the module and include it in our index.js file</p> <pre class="grvsc-container default-dark" data-language="" data-index="11"><code class="grvsc-code"><span class="grvsc-line"><span class="grvsc-source"> npm i aws-textract-helper</span></span></code></pre> <pre class="grvsc-container default-dark" data-language="javascript" data-index="12"><code class="grvsc-code"><span class="grvsc-line"><span class="grvsc-source"><span class="mtk4">const</span><span class="mtk1"> </span><span class="mtk12">textractHelper</span><span class="mtk1"> = </span><span class="mtk11">require</span><span class="mtk1">(</span><span class="mtk8">&#39;aws-textract-helper&#39;</span><span class="mtk1">)</span></span></span></code></pre> <p>There are multiple functions available in the API but for now you only need <code>createForm</code>. It takes two parameters, the data that we got back from the <code>documentExtract</code> function and a config (optional) which allows you to trim unwanted characters in the form keys such as a colon or an extra space.</p> <pre class="grvsc-container default-dark" data-language="javascript" data-index="13"><code class="grvsc-code"><span class="grvsc-line"><span class="grvsc-source"><span class="mtk4">const</span><span class="mtk1"> </span><span class="mtk12">textractData</span><span class="mtk1"> = </span><span class="mtk15">await</span><span class="mtk1"> </span><span class="mtk11">documentExtract</span><span class="mtk1">(</span><span class="mtk12">s3Content</span><span class="mtk1">.</span><span class="mtk12">Key</span><span class="mtk1">)</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk4">const</span><span class="mtk1"> </span><span class="mtk12">formData</span><span class="mtk1"> = </span><span class="mtk12">textractHelper</span><span class="mtk1">.</span><span class="mtk11">createForm</span><span class="mtk1">(</span><span class="mtk12">textractData</span><span class="mtk1">, { </span><span class="mtk12">trimChars:</span><span class="mtk1"> [</span><span class="mtk8">&#39;:&#39;</span><span class="mtk1">, </span><span class="mtk8">&#39; &#39;</span><span class="mtk1">] })</span></span></span></code></pre> <h2 id="display-the-results-in-an-html-form" style="position:relative;"><a href="#display-the-results-in-an-html-form" aria-label="display the results in an html form permalink" class="anchor before"><svg aria-hidden="true" focusable="false" height="16" version="1.1" viewBox="0 0 16 16" width="16"><path fill-rule="evenodd" d="M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z"></path></svg></a>Display the results in an HTML form</h2> <p>Last but not least, let’s render the <code>fileupload</code> view with the data generated from the textract helper function. Our final code for the upload function should look like this:</p> <pre class="grvsc-container default-dark" data-language="javascript" data-index="14"><code class="grvsc-code"><span class="grvsc-line"><span class="grvsc-source"><span class="mtk12">router</span><span class="mtk1">.</span><span class="mtk11">post</span><span class="mtk1">(</span><span class="mtk8">&#39;/fileupload&#39;</span><span class="mtk1">, (</span><span class="mtk12">req</span><span class="mtk1">, </span><span class="mtk12">res</span><span class="mtk1">, </span><span class="mtk12">next</span><span class="mtk1">) </span><span class="mtk4">=&gt;</span><span class="mtk1"> {</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk3">// Upload logic</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk4">const</span><span class="mtk1"> </span><span class="mtk12">form</span><span class="mtk1"> = </span><span class="mtk4">new</span><span class="mtk1"> </span><span class="mtk10">formidable</span><span class="mtk1">.</span><span class="mtk10">IncomingForm</span><span class="mtk1">()</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">form</span><span class="mtk1">.</span><span class="mtk11">parse</span><span class="mtk1">(</span><span class="mtk12">req</span><span class="mtk1">, </span><span class="mtk4">async</span><span class="mtk1"> (</span><span class="mtk12">err</span><span class="mtk1">, </span><span class="mtk12">fields</span><span class="mtk1">, </span><span class="mtk12">files</span><span class="mtk1">) </span><span class="mtk4">=&gt;</span><span class="mtk1"> {</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk15">if</span><span class="mtk1"> (</span><span class="mtk12">err</span><span class="mtk1">) {</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk10">console</span><span class="mtk1">.</span><span class="mtk11">error</span><span class="mtk1">(</span><span class="mtk12">err</span><span class="mtk1">)</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> }</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk4">const</span><span class="mtk1"> </span><span class="mtk12">fileContent</span><span class="mtk1"> = </span><span class="mtk12">fs</span><span class="mtk1">.</span><span class="mtk11">readFileSync</span><span class="mtk1">(</span><span class="mtk12">files</span><span class="mtk1">.</span><span class="mtk12">filetoupload</span><span class="mtk1">.</span><span class="mtk12">path</span><span class="mtk1">)</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk4">const</span><span class="mtk1"> </span><span class="mtk12">s3Params</span><span class="mtk1"> = {</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">Bucket:</span><span class="mtk1"> </span><span class="mtk12">process</span><span class="mtk1">.</span><span class="mtk12">env</span><span class="mtk1">.</span><span class="mtk12">AWS_BUCKET</span><span class="mtk1">,</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">Key:</span><span class="mtk1"> </span><span class="mtk8">`</span><span class="mtk4">${</span><span class="mtk10">Date</span><span class="mtk1">.</span><span class="mtk11">now</span><span class="mtk1">().</span><span class="mtk11">toString</span><span class="mtk1">()</span><span class="mtk4">}</span><span class="mtk8">-</span><span class="mtk4">${</span><span class="mtk12">files</span><span class="mtk1">.</span><span class="mtk12">filetoupload</span><span class="mtk1">.</span><span class="mtk12">name</span><span class="mtk4">}</span><span class="mtk8">`</span><span class="mtk1">,</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">Body:</span><span class="mtk1"> </span><span class="mtk12">fileContent</span><span class="mtk1">,</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">ContentType:</span><span class="mtk1"> </span><span class="mtk12">files</span><span class="mtk1">.</span><span class="mtk12">filetoupload</span><span class="mtk1">.</span><span class="mtk12">type</span><span class="mtk1">,</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">ACL:</span><span class="mtk1"> </span><span class="mtk8">&#39;public-read&#39;</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> }</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk4">const</span><span class="mtk1"> </span><span class="mtk12">s3Content</span><span class="mtk1"> = </span><span class="mtk15">await</span><span class="mtk1"> </span><span class="mtk11">s3Upload</span><span class="mtk1">(</span><span class="mtk12">s3Params</span><span class="mtk1">)</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk4">const</span><span class="mtk1"> </span><span class="mtk12">textractData</span><span class="mtk1"> = </span><span class="mtk15">await</span><span class="mtk1"> </span><span class="mtk11">documentExtract</span><span class="mtk1">(</span><span class="mtk12">s3Content</span><span class="mtk1">.</span><span class="mtk12">Key</span><span class="mtk1">)</span></span></span> <span class="grvsc-line"><span class="grvsc-source"></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk4">const</span><span class="mtk1"> </span><span class="mtk12">formData</span><span class="mtk1"> = </span><span class="mtk12">textractHelper</span><span class="mtk1">.</span><span class="mtk11">createForm</span><span class="mtk1">(</span><span class="mtk12">textractData</span><span class="mtk1">, { </span><span class="mtk12">trimChars:</span><span class="mtk1"> [</span><span class="mtk8">&#39;:&#39;</span><span class="mtk1">, </span><span class="mtk8">&#39; &#39;</span><span class="mtk1">] })</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> </span><span class="mtk12">res</span><span class="mtk1">.</span><span class="mtk11">render</span><span class="mtk1">(</span><span class="mtk8">&#39;fileupload&#39;</span><span class="mtk1">, { </span><span class="mtk12">title:</span><span class="mtk1"> </span><span class="mtk8">&#39;Upload Results&#39;</span><span class="mtk1">, </span><span class="mtk12">formData</span><span class="mtk1"> })</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1"> })</span></span></span> <span class="grvsc-line"><span class="grvsc-source"><span class="mtk1">})</span></span></span></code></pre> <p>Now when we run the code and upload the image, we should get the following results. Also, the full example is available publicly in this <a href="https://github.com/muhimasri/aws-textract-app">repository</a>.</p> <p><img src="/1d9a34cb9e7ee5d8baefbc22cb57ebc2/textract-uploader.gif" alt=""></p> <h2 id="conclusion" style="position:relative;"><a href="#conclusion" aria-label="conclusion permalink" class="anchor before"><svg aria-hidden="true" focusable="false" height="16" version="1.1" viewBox="0 0 16 16" width="16"><path fill-rule="evenodd" d="M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z"></path></svg></a>Conclusion</h2> <p>Amazon Textract is still relatively a new technology and a lot to discover and learn from but it is definitely worth looking at when you want to instantly and accurately analyse unstructured text from your customer’s captured data such as invoices or receipts.</p> <p>Bye for now 👋</p> <style class="grvsc-styles"> .grvsc-container { overflow: auto; position: relative; -webkit-overflow-scrolling: touch; padding-top: 1rem; padding-top: var(--grvsc-padding-top, var(--grvsc-padding-v, 1rem)); padding-bottom: 1rem; padding-bottom: var(--grvsc-padding-bottom, var(--grvsc-padding-v, 1rem)); border-radius: 8px; border-radius: var(--grvsc-border-radius, 8px); font-feature-settings: normal; line-height: 1.4; } .grvsc-code { display: table; } .grvsc-line { display: table-row; box-sizing: border-box; width: 100%; position: relative; } .grvsc-line > * { position: relative; } .grvsc-gutter-pad { display: table-cell; padding-left: 0.75rem; padding-left: calc(var(--grvsc-padding-left, var(--grvsc-padding-h, 1.5rem)) / 2); } .grvsc-gutter { display: table-cell; -webkit-user-select: none; -moz-user-select: none; user-select: none; } .grvsc-gutter::before { content: attr(data-content); } .grvsc-source { display: table-cell; padding-left: 1.5rem; padding-left: var(--grvsc-padding-left, var(--grvsc-padding-h, 1.5rem)); padding-right: 1.5rem; padding-right: var(--grvsc-padding-right, var(--grvsc-padding-h, 1.5rem)); } .grvsc-source:empty::after { content: ' '; -webkit-user-select: none; -moz-user-select: none; user-select: none; } .grvsc-gutter + .grvsc-source { padding-left: 0.75rem; padding-left: calc(var(--grvsc-padding-left, var(--grvsc-padding-h, 1.5rem)) / 2); } /* Line transformer styles */ .grvsc-has-line-highlighting > .grvsc-code > .grvsc-line::before { content: ' '; position: absolute; width: 100%; } .grvsc-line-diff-add::before { background-color: var(--grvsc-line-diff-add-background-color, rgba(0, 255, 60, 0.2)); } .grvsc-line-diff-del::before { background-color: var(--grvsc-line-diff-del-background-color, rgba(255, 0, 20, 0.2)); } .grvsc-line-number { padding: 0 2px; text-align: right; opacity: 0.7; } .default-dark { background-color: #1E1E1E; color: #D4D4D4; } .default-dark .mtk1 { color: #D4D4D4; } .default-dark .mtk12 { color: #9CDCFE; } .default-dark .mtk8 { color: #CE9178; } .default-dark .mtk4 { color: #569CD6; } .default-dark .mtk11 { color: #DCDCAA; } .default-dark .mtk3 { color: #6A9955; } .default-dark .mtk10 { color: #4EC9B0; } .default-dark .mtk15 { color: #C586C0; } .default-dark .mtk7 { color: #B5CEA8; } .default-dark .grvsc-line-highlighted::before { background-color: var(--grvsc-line-highlighted-background-color, rgba(255, 255, 255, 0.1)); box-shadow: inset var(--grvsc-line-highlighted-border-width, 4px) 0 0 0 var(--grvsc-line-highlighted-border-color, rgba(255, 255, 255, 0.5)); } </style>