<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:dc="http://purl.org/dc/elements/1.1/">
  <channel>
    <title>Forem: Abhishek I</title>
    <description>The latest articles on Forem by Abhishek I (@i_abhiseka).</description>
    <link>https://forem.com/i_abhiseka</link>
    <image>
      <url>https://media2.dev.to/dynamic/image/width=90,height=90,fit=cover,gravity=auto,format=auto/https:%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Fuser%2Fprofile_image%2F3490170%2Fc948e019-470c-493b-a0bc-077fdde8363b.jpg</url>
      <title>Forem: Abhishek I</title>
      <link>https://forem.com/i_abhiseka</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://forem.com/feed/i_abhiseka"/>
    <language>en</language>
    <item>
      <title>React 19.2’s &lt;Activity /&gt;: Because ‘display: none’ Shouldn’t Mean ‘Memory Loss’</title>
      <dc:creator>Abhishek I</dc:creator>
      <pubDate>Mon, 27 Oct 2025 10:02:45 +0000</pubDate>
      <link>https://forem.com/i_abhiseka/react-192s-because-display-none-shouldnt-mean-memory-loss-12o</link>
      <guid>https://forem.com/i_abhiseka/react-192s-because-display-none-shouldnt-mean-memory-loss-12o</guid>
      <description>&lt;p&gt;React 19.2 just dropped a feature that’s small in appearance but massive in impact, the new &lt;code&gt;&amp;lt;Activity /&amp;gt;&lt;/code&gt; component.&lt;/p&gt;

&lt;p&gt;Think of it as giving your components the power to &lt;em&gt;take a nap&lt;/em&gt; instead of being completely wiped out.&lt;/p&gt;

&lt;p&gt;Up until now, when you wanted to hide or show parts of your UI, you’d usually reach for &lt;strong&gt;conditional rendering&lt;/strong&gt;. It works, sure, but here’s the gotcha: once a component unmounts, everything inside it, its state, effects, and DOM, gets obliterated. When you bring it back, React rebuilds the whole thing from scratch.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Enter&lt;/strong&gt; &lt;code&gt;&amp;lt;Activity /&amp;gt;&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;Instead of unmounting, React can now &lt;strong&gt;pause&lt;/strong&gt; a component, cleaning up its side effects while keeping its DOM and state safely tucked away in memory until you need it again.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight jsx"&gt;&lt;code&gt;&lt;span class="c1"&gt;// Before&lt;/span&gt;
&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;activeView&lt;/span&gt; &lt;span class="o"&gt;===&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;list&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt; &lt;span class="o"&gt;&amp;amp;&amp;amp;&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;
          &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nc"&gt;NotesList&lt;/span&gt;
            &lt;span class="na"&gt;notes&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;notes&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;
            &lt;span class="na"&gt;onEdit&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;handleEdit&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;
            &lt;span class="na"&gt;onSelectNote&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;handleEdit&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;
          &lt;span class="p"&gt;/&amp;gt;&lt;/span&gt;
        &lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;

 &lt;span class="c1"&gt;// After &lt;/span&gt;
 &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nc"&gt;Activity&lt;/span&gt; &lt;span class="na"&gt;mode&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;activeView&lt;/span&gt; &lt;span class="o"&gt;===&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;list&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt; &lt;span class="p"&gt;?&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;visible&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt; &lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;hidden&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
          &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nc"&gt;NotesList&lt;/span&gt; 
            &lt;span class="na"&gt;notes&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;notes&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;
            &lt;span class="na"&gt;onEdit&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;handleEdit&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;
            &lt;span class="na"&gt;onSelectNote&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;handleEdit&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;
          &lt;span class="p"&gt;/&amp;gt;&lt;/span&gt;
 &lt;span class="p"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="nc"&gt;Activity&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;In React 19.2, Activity supports two modes: &lt;code&gt;visible&lt;/code&gt; and &lt;code&gt;hidden&lt;/code&gt;.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;code&gt;hidden&lt;/code&gt;: hides the children, unmounts effects, and defers all updates until React has nothing left to work on.&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;visible&lt;/code&gt;: shows the children, mounts effects, and allows updates to be processed normally.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;This means you can pre-render and keep rendering hidden parts of the app without impacting the performance of anything visible on screen.&lt;/p&gt;

&lt;h2&gt;
  
  
  One Example to Rule Them All: A “Remembering” Note Editor
&lt;/h2&gt;

&lt;p&gt;Let’s see &lt;code&gt;&amp;lt;Activity /&amp;gt;&lt;/code&gt; in action with a simple two-view notes app.&lt;/p&gt;

&lt;p&gt;Our app has:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;A &lt;strong&gt;Notes List&lt;/strong&gt; view&lt;/li&gt;
&lt;li&gt;A &lt;strong&gt;Note Editor&lt;/strong&gt; view&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;…and you can switch between them using buttons.&lt;/p&gt;

&lt;p&gt;Inside the editor, we have:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;A &lt;strong&gt;textarea&lt;/strong&gt; where users can type drafts (browser-managed DOM state).&lt;/li&gt;
&lt;li&gt;A &lt;strong&gt;“Show Details”&lt;/strong&gt; toggle (React-managed state).&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Now, in a typical React setup using conditional rendering, as soon as you hide the editor, both the draft text and toggle state vanish into the void. When you switch back, everything resets, not ideal.&lt;/p&gt;

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

&lt;h3&gt;
  
  
  What’s Different Now
&lt;/h3&gt;

&lt;p&gt;With &lt;code&gt;&amp;lt;Activity /&amp;gt;&lt;/code&gt;, React doesn’t destroy the editor when you hide it, it just applies a &lt;code&gt;display: none&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;That means:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Your &lt;strong&gt;React state&lt;/strong&gt; (&lt;code&gt;showDetails&lt;/code&gt;) stays alive.&lt;/li&gt;
&lt;li&gt;Your &lt;strong&gt;DOM state&lt;/strong&gt; (the text you typed) stays exactly where you left it.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;When you return, your note, toggle, and even your cursor position are waiting for you, no re-renders, no lost progress.&lt;/p&gt;

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

&lt;h2&gt;
  
  
  Why This Changes the Game
&lt;/h2&gt;

&lt;p&gt;&lt;code&gt;&amp;lt;Activity /&amp;gt;&lt;/code&gt; brings a new middle ground: &lt;strong&gt;“keep it alive, but deactivate it.”&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;It’s the perfect combo, your hidden components don’t hog performance, yet they don’t restart every time you bring them back.&lt;/p&gt;

&lt;p&gt;This opens up a bunch of UX upgrades for:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Modals or drawers&lt;/strong&gt; that reopen with user input still intact.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Multi-step forms&lt;/strong&gt; that remember your progress.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Tabbed or toggled layouts&lt;/strong&gt; that switch instantly without a re-render hit.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;It’s one of those upgrades that you don’t realize you’ve been missing until you try it.&lt;/p&gt;

&lt;h2&gt;
  
  
  Wrapping Up: Hidden, But Not Forgotten
&lt;/h2&gt;

&lt;p&gt;React 19.2’s &lt;code&gt;&amp;lt;Activity /&amp;gt;&lt;/code&gt; isn’t just another quality-of-life tweak, it’s a quiet redefinition of how React handles component lifecycles.&lt;/p&gt;

&lt;p&gt;It softens the hard boundary between “mounted” and “unmounted,” giving developers finer control over what stays alive behind the curtain.&lt;/p&gt;

&lt;p&gt;Hidden components are no longer “gone”, they’re simply &lt;em&gt;napping&lt;/em&gt;.&lt;/p&gt;

&lt;p&gt;And with that, React takes another step toward UIs that feel less like web pages, and more like living, breathing apps that &lt;em&gt;remember you&lt;/em&gt;.&lt;/p&gt;

&lt;p&gt;Find the complete documentation here:&lt;a href="https://react.dev/" rel="noopener noreferrer"&gt;https://react.dev/&lt;/a&gt;&lt;br&gt;
Blog post for React 19.2 &lt;a href="https://react.dev/blog/2025/10/01/react-19-2" rel="noopener noreferrer"&gt;https://react.dev/blog/2025/10/01/react-19-2&lt;/a&gt;&lt;/p&gt;

</description>
      <category>webdev</category>
      <category>react19</category>
      <category>programming</category>
      <category>javascript</category>
    </item>
    <item>
      <title>BOMs, But Make It Visual: Level Up Your Product Game</title>
      <dc:creator>Abhishek I</dc:creator>
      <pubDate>Sat, 04 Oct 2025 05:50:10 +0000</pubDate>
      <link>https://forem.com/i_abhiseka/boms-but-make-it-visual-level-up-your-product-game-1php</link>
      <guid>https://forem.com/i_abhiseka/boms-but-make-it-visual-level-up-your-product-game-1php</guid>
      <description>&lt;h2&gt;
  
  
  &lt;strong&gt;The Spreadsheet Struggle&lt;/strong&gt;
&lt;/h2&gt;

&lt;p&gt;Imagine managing a product with hundreds of components - a smartphone, a car engine, or even a simple pair of earbuds. Most teams start with Excel: endless rows of part numbers, suppliers, and costs. At first, it works. But as the product grows into multi-level assemblies (parts inside subassemblies, inside bigger assemblies), the spreadsheet becomes a nightmare to maintain. One missed update, one wrong formula, and suddenly… &lt;em&gt;chaos mode activated&lt;/em&gt;.&lt;/p&gt;

&lt;h2&gt;
  
  
  &lt;strong&gt;Frontend to the Rescue: Why Traditional BOM Management Falls Short&lt;/strong&gt;
&lt;/h2&gt;

&lt;p&gt;Traditional methods often rely on spreadsheets or siloed PLM/ERP systems, which create:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Errors &amp;amp; Duplicates&lt;/strong&gt; - Manual updates are prone to mistakes&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Data Silos&lt;/strong&gt; - Engineers, procurement, and quality teams work in isolation&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Limited Insights&lt;/strong&gt; - Hard to spot cost drivers or compliance risks quickly&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Complexity Blind Spots&lt;/strong&gt; - Multi-level hierarchies flattened into rows&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Here’s the key: &lt;strong&gt;frontend is not just about landing pages - it’s the whole interactive experience.&lt;/strong&gt; Modern frameworks like React, Angular, and Vue turn static BOM data into a dynamic environment where teams can explore, analyze, and act in real time.&lt;/p&gt;

&lt;h2&gt;
  
  
  &lt;strong&gt;How Frontend Tech Transforms BOMs&lt;/strong&gt;
&lt;/h2&gt;

&lt;p&gt;Modern web technologies allow you to visualize BOMs like never before:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Tree Structures &amp;amp; Expandable Views&lt;/strong&gt; – Click to drill down assemblies into subassemblies and parts&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Dynamic Filtering &amp;amp; Search&lt;/strong&gt; – Quickly locate suppliers, costs, or lifecycle risks&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Charts &amp;amp; Dashboards&lt;/strong&gt; – Visualize cost distribution, supply risk, or inventory status in real time&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Collaboration &amp;amp; Interactivity&lt;/strong&gt; – Frontend frameworks make it easy to sync updates, comments, and approvals across teams&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;In short: your BOM goes from static spreadsheet to &lt;strong&gt;interactive decision-making platform&lt;/strong&gt;.&lt;/p&gt;

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

&lt;h2&gt;
  
  
  Industrial Use Case: Wireless Earbuds
&lt;/h2&gt;

&lt;p&gt;Traditional table:&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Assembly&lt;/th&gt;
&lt;th&gt;Part Number&lt;/th&gt;
&lt;th&gt;Description&lt;/th&gt;
&lt;th&gt;Supplier&lt;/th&gt;
&lt;th&gt;Qty&lt;/th&gt;
&lt;th&gt;Cost ($)&lt;/th&gt;
&lt;th&gt;Lifecycle&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;Earbuds&lt;/td&gt;
&lt;td&gt;EB-001&lt;/td&gt;
&lt;td&gt;Left Earbud&lt;/td&gt;
&lt;td&gt;In-house&lt;/td&gt;
&lt;td&gt;1&lt;/td&gt;
&lt;td&gt;20&lt;/td&gt;
&lt;td&gt;Active&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Earbuds&lt;/td&gt;
&lt;td&gt;EB-002&lt;/td&gt;
&lt;td&gt;Right Earbud&lt;/td&gt;
&lt;td&gt;In-house&lt;/td&gt;
&lt;td&gt;1&lt;/td&gt;
&lt;td&gt;20&lt;/td&gt;
&lt;td&gt;Active&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Left Earbud&lt;/td&gt;
&lt;td&gt;EB-101&lt;/td&gt;
&lt;td&gt;Speaker Driver&lt;/td&gt;
&lt;td&gt;ABC Audio&lt;/td&gt;
&lt;td&gt;1&lt;/td&gt;
&lt;td&gt;5&lt;/td&gt;
&lt;td&gt;Active&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Left Earbud&lt;/td&gt;
&lt;td&gt;EB-102&lt;/td&gt;
&lt;td&gt;Microphone&lt;/td&gt;
&lt;td&gt;SoundTech&lt;/td&gt;
&lt;td&gt;1&lt;/td&gt;
&lt;td&gt;3&lt;/td&gt;
&lt;td&gt;Active&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Charging Case&lt;/td&gt;
&lt;td&gt;EB-301&lt;/td&gt;
&lt;td&gt;Battery&lt;/td&gt;
&lt;td&gt;PowerCell&lt;/td&gt;
&lt;td&gt;1&lt;/td&gt;
&lt;td&gt;7&lt;/td&gt;
&lt;td&gt;EOL soon&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Charging Case&lt;/td&gt;
&lt;td&gt;EB-302&lt;/td&gt;
&lt;td&gt;USB-C Port&lt;/td&gt;
&lt;td&gt;FastConnect&lt;/td&gt;
&lt;td&gt;1&lt;/td&gt;
&lt;td&gt;2&lt;/td&gt;
&lt;td&gt;Active&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;Looks okay… but spotting risks? &lt;em&gt;Big yikes.&lt;/em&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  With visualization:
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;Engineers see tree expansion (Earbuds → Left Earbud → Speaker)&lt;/li&gt;
&lt;li&gt;Procurement sees a Pareto chart of cost contribution (battery = main $$$ culprit)&lt;/li&gt;
&lt;li&gt;Compliance team spots “Battery supplier = EOL soon” #RedFlag&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;BOM, locked and loaded from boring list to &lt;strong&gt;collab beast&lt;/strong&gt;.&lt;/p&gt;

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

&lt;h2&gt;
  
  
  Data Sources
&lt;/h2&gt;

&lt;p&gt;BOM data typically comes from multiple systems across the product lifecycle:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;CAD&lt;/strong&gt; – Generates initial part lists from 3D models&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;PLM&lt;/strong&gt; – Manages engineering BOMs, revisions, compliance&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;ERP&lt;/strong&gt; – Captures supplier data, costs, inventory&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Spreadsheets&lt;/strong&gt; – Still hanging around in small orgs, but kinda sus for big ops&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Data Structure
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Core attributes&lt;/strong&gt; – Part number, description, supplier, cost, quantity, lifecycle&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Parent–child hierarchy&lt;/strong&gt; – Products → Subassemblies → Components&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Multi-level BOMs&lt;/strong&gt; – Reflect real-world product complexity&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Consistency is king&lt;/strong&gt; – Unique IDs, parent–child links, standardized attributes&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Architecture for BOM Visualization
&lt;/h2&gt;

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

&lt;h3&gt;
  
  
  Benefits of BOM Visualization
&lt;/h3&gt;

&lt;p&gt;&lt;strong&gt;Faster Decision-Making&lt;/strong&gt; – Spot risks at a glance&lt;br&gt;
&lt;strong&gt;Cross-functional Collab&lt;/strong&gt; – Engineers, buyers, managers on the same page&lt;br&gt;
&lt;strong&gt;Error Reduction&lt;/strong&gt; – Visual hierarchy = fewer oopsies&lt;br&gt;
&lt;strong&gt;Version Tracking&lt;/strong&gt; – Compare BOM revisions visually&lt;/p&gt;

&lt;h3&gt;
  
  
  Closing Thoughts
&lt;/h3&gt;

&lt;p&gt;BOM visualization transforms the way teams understand, manage, and optimize products. Instead of drowning in spreadsheets, companies get living, interactive dashboards that scale with product complexity.&lt;/p&gt;

&lt;p&gt;Whether you’re building earbuds or a jet engine, the principle is the same:&lt;/p&gt;

&lt;p&gt;See the product not just as a list of parts, but as a &lt;strong&gt;connected digital model&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Source Code&lt;/strong&gt;: &lt;a href="https://github.com/AbhishekIngle/bom-visualition" rel="noopener noreferrer"&gt;Github&lt;/a&gt;&lt;br&gt;
&lt;strong&gt;Try out on your own&lt;/strong&gt;: &lt;a href="http://bom-vizualizer.netlify.app/" rel="noopener noreferrer"&gt;Web App&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;That’s the real power of BOM visualization in modern industry.&lt;/p&gt;

</description>
      <category>teamcenter</category>
      <category>digitaltransformation</category>
      <category>plm</category>
      <category>react</category>
    </item>
    <item>
      <title>From Static Forms to Dynamic Configurator: Our Journey in PLM</title>
      <dc:creator>Abhishek I</dc:creator>
      <pubDate>Wed, 10 Sep 2025 17:03:44 +0000</pubDate>
      <link>https://forem.com/i_abhiseka/from-static-forms-to-dynamic-configurator-our-journey-in-plm-3n9i</link>
      <guid>https://forem.com/i_abhiseka/from-static-forms-to-dynamic-configurator-our-journey-in-plm-3n9i</guid>
      <description>&lt;p&gt;Imagine you’re asked to build a product configuration form. At first glance, it sounds simple-pick a model, select a few options, and you’re done. But what if that product comes in _thousands_of possible combinations? Suddenly, your neat little dropdown turns into a nightmare of tangled logic and endless updates.&lt;/p&gt;

&lt;p&gt;That’s the situation we found ourselves in. What began as a plain React form grew into a dynamic, rule-driven configurator that could scale gracefully and give users instant feedback. Here’s the story of how we got there.&lt;/p&gt;

&lt;h2&gt;
  
  
  Why Static Forms Fall Apart
&lt;/h2&gt;

&lt;p&gt;Our first approach looked something like this:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight html"&gt;&lt;code&gt;&lt;span class="nt"&gt;&amp;lt;form&amp;gt;&lt;/span&gt;
  &lt;span class="nt"&gt;&amp;lt;label&amp;gt;&lt;/span&gt;Model&lt;span class="nt"&gt;&amp;lt;/label&amp;gt;&lt;/span&gt;
  &lt;span class="nt"&gt;&amp;lt;select&amp;gt;&lt;/span&gt;
    &lt;span class="nt"&gt;&amp;lt;option&amp;gt;&lt;/span&gt;Model-A&lt;span class="nt"&gt;&amp;lt;/option&amp;gt;&lt;/span&gt;
    &lt;span class="nt"&gt;&amp;lt;option&amp;gt;&lt;/span&gt;Model-B&lt;span class="nt"&gt;&amp;lt;/option&amp;gt;&lt;/span&gt;
  &lt;span class="nt"&gt;&amp;lt;/select&amp;gt;&lt;/span&gt;
  &lt;span class="nt"&gt;&amp;lt;button&lt;/span&gt; &lt;span class="na"&gt;type=&lt;/span&gt;&lt;span class="s"&gt;"submit"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;Apply Configuration&lt;span class="nt"&gt;&amp;lt;/button&amp;gt;&lt;/span&gt;
&lt;span class="nt"&gt;&amp;lt;/form&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;It worked for two options. But once complexity kicked in, the cracks showed:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Hardcoding overload&lt;/strong&gt; – every new choice meant editing frontend code.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Validation lag&lt;/strong&gt; – errors only appeared after hitting submit.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Scattered rules&lt;/strong&gt; – logic was split between frontend and backend.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Scaling issues&lt;/strong&gt; – hundreds of interdependent options were impossible to manage.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Clearly, this wasn’t sustainable.&lt;/p&gt;

&lt;h2&gt;
  
  
  The Pivot: Building Dynamically
&lt;/h2&gt;

&lt;p&gt;We set four principles for the new system:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;strong&gt;Schema-driven forms&lt;/strong&gt; – UI should generate itself from a JSON schema.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Real-time validation&lt;/strong&gt; – errors should appear as soon as a wrong option is selected.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Centralized business logic&lt;/strong&gt; – validation rules live in the backend, not duplicated in the frontend.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Visual previews&lt;/strong&gt; – users should see results immediately, even in 3D where possible.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;The stack:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;React&lt;/strong&gt; for the UI&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;@rjsf/core&lt;/strong&gt; (React JSONSchema Form) for schema-based form generation&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;AJV&lt;/strong&gt; for JSON Schema validation&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Node.js&lt;/strong&gt; for enforcing business rules and integrating with PLM systems&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Three.js&lt;/strong&gt; for interactive 3D previews&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  How It Fits Together
&lt;/h2&gt;

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

&lt;p&gt;The frontend dynamically renders forms and handles simple checks. The backend enforces rules and returns either errors or a valid configuration. The preview then updates instantly.&lt;/p&gt;

&lt;h2&gt;
  
  
  JSON Schema: The Core
&lt;/h2&gt;

&lt;p&gt;At the center is a schema like this:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight json"&gt;&lt;code&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"title"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"Product Configuration"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"type"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"object"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"properties"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"model"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nl"&gt;"type"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"string"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nl"&gt;"enum"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="s2"&gt;"A"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"B"&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;},&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"color"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nl"&gt;"type"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"string"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nl"&gt;"enum"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="s2"&gt;"Red"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"Blue"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"Green"&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;},&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"size"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nl"&gt;"type"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"string"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nl"&gt;"enum"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="s2"&gt;"Small"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"Medium"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"Large"&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="p"&gt;},&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"required"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="s2"&gt;"model"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"color"&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;And the backend enforces rules cleanly:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight jsx"&gt;&lt;code&gt;&lt;span class="nx"&gt;app&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;post&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;/validate&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;req&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;res&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;model&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;color&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;req&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;body&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="k"&gt;if &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;model&lt;/span&gt; &lt;span class="o"&gt;===&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;A&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt; &lt;span class="o"&gt;&amp;amp;&amp;amp;&lt;/span&gt; &lt;span class="nx"&gt;color&lt;/span&gt; &lt;span class="o"&gt;===&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;Green&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nx"&gt;res&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;status&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;400&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nf"&gt;json&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt; &lt;span class="na"&gt;error&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;Model A does not support Green&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt; &lt;span class="p"&gt;});&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;
  &lt;span class="nx"&gt;res&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;json&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt; &lt;span class="na"&gt;success&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kc"&gt;true&lt;/span&gt; &lt;span class="p"&gt;});&lt;/span&gt;
&lt;span class="p"&gt;});&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;No duplication, no guesswork.&lt;/p&gt;

&lt;h2&gt;
  
  
  Frontend Implementation
&lt;/h2&gt;

&lt;p&gt;With RJSF and AJV, the form almost builds itself:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight jsx"&gt;&lt;code&gt;&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="nx"&gt;Form&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;@rjsf/core&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="nx"&gt;validator&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;@rjsf/validator-ajv8&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;schema&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="cm"&gt;/* schema as above */&lt;/span&gt; &lt;span class="p"&gt;};&lt;/span&gt;

&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;App&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;handleSubmit&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;({&lt;/span&gt; &lt;span class="nx"&gt;formData&lt;/span&gt; &lt;span class="p"&gt;})&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="nx"&gt;console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;log&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;Submitted:&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;formData&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="c1"&gt;// Send to backend for validation&lt;/span&gt;
  &lt;span class="p"&gt;};&lt;/span&gt;

  &lt;span class="k"&gt;return &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
    &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nc"&gt;Formschema&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;schema&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;
      &lt;span class="na"&gt;validator&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;validator&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;
      &lt;span class="na"&gt;onSubmit&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;handleSubmit&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;
    &lt;span class="p"&gt;/&amp;gt;&lt;/span&gt;
  &lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="p"&gt;};&lt;/span&gt;

&lt;span class="k"&gt;export&lt;/span&gt; &lt;span class="k"&gt;default&lt;/span&gt; &lt;span class="nx"&gt;App&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Custom UI tweaks and validation messages make it user-friendly while still fully dynamic.&lt;/p&gt;

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

&lt;h2&gt;
  
  
  The User Experience
&lt;/h2&gt;

&lt;p&gt;Here’s what happens when someone configures a product:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;They select: Model A, Color Red, Size Medium.&lt;/li&gt;
&lt;li&gt;Local schema check passes.&lt;/li&gt;
&lt;li&gt;The UI displays the message instantly.&lt;/li&gt;
&lt;li&gt;Once valid, the live preview updates.&lt;/li&gt;
&lt;/ol&gt;

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

&lt;ol&gt;
&lt;li&gt;They select: Model C, Color Red&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;API call flags an error:&lt;br&gt;
&lt;/p&gt;
&lt;pre class="highlight json"&gt;&lt;code&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nl"&gt;"error"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"Model A does not support Green"&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/li&gt;
&lt;/ol&gt;

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

&lt;p&gt;Result: a smooth, guided workflow with minimal frustration.&lt;/p&gt;

&lt;h2&gt;
  
  
  Why This Approach Works
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Scalable&lt;/strong&gt; - handle thousands of options without rewriting the UI.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Maintainable&lt;/strong&gt; - rules live in one place, the backend.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Cross-platform&lt;/strong&gt; - the same schema can drive web, mobile, or desktop.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;User-friendly&lt;/strong&gt; - instant validation and previews reduce trial-and-error.&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Wrapping Up
&lt;/h2&gt;

&lt;p&gt;We went from static, brittle forms to a flexible, schema-driven configurator that’s easier to maintain and far more enjoyable for users.&lt;/p&gt;

&lt;p&gt;If your forms are drowning in hardcoded logic, it might be time to let schemas and centralized rules do the heavy lifting.&lt;/p&gt;

&lt;p&gt;“Curious to try it out? Explore the project on &lt;a href="https://github.com/AbhishekIngle/Dynamic-Form-Generation-for-Configuration" rel="noopener noreferrer"&gt;GitHub &lt;/a&gt;Contributions and feedback welcome!”&lt;/p&gt;

&lt;p&gt;Have you dealt with similar form chaos? How did you approach validation and scaling? Share your thoughts-I’d love to swap ideas.&lt;/p&gt;

</description>
      <category>plm</category>
      <category>digitaltransformation</category>
      <category>opensource</category>
      <category>react</category>
    </item>
  </channel>
</rss>
