<?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: Optimajet Limited</title>
    <description>The latest articles on Forem by Optimajet Limited (@optimajet).</description>
    <link>https://forem.com/optimajet</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%2F1475516%2F326deb07-08af-408b-a5a3-dfa595a8ebb3.png</url>
      <title>Forem: Optimajet Limited</title>
      <link>https://forem.com/optimajet</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://forem.com/feed/optimajet"/>
    <language>en</language>
    <item>
      <title>React JSON Schema Form Alternative: FormEngine vs RJSF Bundle Size Comparison</title>
      <dc:creator>Optimajet Limited</dc:creator>
      <pubDate>Wed, 11 Feb 2026 19:19:23 +0000</pubDate>
      <link>https://forem.com/optimajet/formengine-vs-rjsf-an-honest-bundle-size-comparison-of-two-json-schema-form-libraries-133n</link>
      <guid>https://forem.com/optimajet/formengine-vs-rjsf-an-honest-bundle-size-comparison-of-two-json-schema-form-libraries-133n</guid>
      <description>&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;Disclaimer:&lt;/strong&gt; Hi! We're the team at &lt;a href="https://optimajet.com" rel="noopener noreferrer"&gt;Optimajet&lt;/a&gt;, creators of FormEngine. This is an honest technical comparison of our library with react-jsonschema-form (RJSF). All tests are public, reproducible, and &lt;a href="https://github.com/optimajet/formengine/tree/master/community/examples/bundle-size" rel="noopener noreferrer"&gt;available on GitHub&lt;/a&gt;.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;&lt;strong&gt;TL;DR:&lt;/strong&gt; We compared two direct competitors in the JSON-based React forms space. RJSF is lighter out of the box (175 KB vs 244 KB). But if you already have Material UI &lt;strong&gt;FormEngine becomes 23% lighter&lt;/strong&gt; (188 KB), while RJSF gets 32% heavier (232 KB). &lt;strong&gt;Your choice of UI library determines the winner.&lt;/strong&gt;&lt;/p&gt;




&lt;h2&gt;
  
  
  Why RJSF vs FormEngine? 🤔
&lt;/h2&gt;

&lt;p&gt;When we developed FormEngine, we often heard: "How are you different from react-jsonschema-form?"&lt;/p&gt;

&lt;p&gt;Fair question. Both libraries:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;React-based&lt;/li&gt;
&lt;li&gt;Work with JSON:

&lt;ul&gt;
&lt;li&gt;RJSF uses JSON Schema to describe forms&lt;/li&gt;
&lt;li&gt;FormEngine uses its own JSON format&lt;/li&gt;
&lt;/ul&gt;


&lt;/li&gt;

&lt;li&gt;Support Material UI&lt;/li&gt;

&lt;li&gt;Open to customization&lt;/li&gt;

&lt;/ul&gt;

&lt;p&gt;But there's one fundamental architectural difference that &lt;strong&gt;radically affects bundle size&lt;/strong&gt;:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;RJSF&lt;/strong&gt; — adds UI components on top of the base library&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;FormEngine&lt;/strong&gt; — completely replaces UI components during integration&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Let's see how this works in practice.&lt;/p&gt;




&lt;h2&gt;
  
  
  Testing Methodology
&lt;/h2&gt;

&lt;p&gt;We tested two realistic forms:&lt;/p&gt;

&lt;h3&gt;
  
  
  Login Form (Simple Case)
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;Email + Password fields&lt;/li&gt;
&lt;li&gt;Basic validation&lt;/li&gt;
&lt;li&gt;Submit button&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  Booking Form (Complex Case)
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;Multi-step form&lt;/li&gt;
&lt;li&gt;Conditional logic&lt;/li&gt;
&lt;li&gt;Different field types (text, dates, selects)&lt;/li&gt;
&lt;li&gt;Validation at each step&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;Test Conditions:&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Production build (minified + gzipped)&lt;/li&gt;
&lt;li&gt;Vite as bundler&lt;/li&gt;
&lt;li&gt;Tree-shaking enabled&lt;/li&gt;
&lt;li&gt;Default configurations&lt;/li&gt;
&lt;li&gt;Two variants: with default UI (FormEngine Core has no default UI, React Suite v5 was used) and with Material UI&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Full methodology: &lt;a href="https://formengine.io/documentation/bundle-size-comparison" rel="noopener noreferrer"&gt;formengine.io/documentation/bundle-size-comparison&lt;/a&gt;&lt;/p&gt;




&lt;h2&gt;
  
  
  Results (gzip sizes)
&lt;/h2&gt;

&lt;h3&gt;
  
  
  Login Form - Default UI
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;🥇 RJSF           175.26 KB  (baseline)
🥈 FormEngine + React Suite (v5)   244.19 KB  (+39% heavier)
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;RJSF wins&lt;/strong&gt; in its pure form. Bootstrap CSS is lighter than React Suite.&lt;/p&gt;




&lt;h3&gt;
  
  
  Login Form - With Material UI
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;🥇 FormEngine     188.54 KB  (-23% from default!)  
🥈 RJSF           231.62 KB  (+32% from default)

Difference: 43 KB in favor of FormEngine
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;The picture changes!&lt;/strong&gt; FormEngine becomes lighter when replacing React Suite with MUI.&lt;/p&gt;




&lt;h3&gt;
  
  
  Booking Form - Default UI
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;🥇 RJSF           178.07 KB  (baseline)
🥈 FormEngine + React Suite (v5)    316.69 KB  (+78% heavier)
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;RJSF is ahead again. But the difference has grown — complex forms require more components.&lt;/p&gt;




&lt;h3&gt;
  
  
  Booking Form - With Material UI
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;🥇 FormEngine     199.26 KB  (-37% from default!)  
🥈 RJSF           234.50 KB  (+32% from default)

Difference: 35 KB in favor of FormEngine
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;FormEngine is lighter again&lt;/strong&gt; after MUI integration.&lt;/p&gt;




&lt;h2&gt;
  
  
  Key Insight: How UI Kit Changes Everything
&lt;/h2&gt;

&lt;p&gt;Here's what happens when switching from default UI to Material UI:&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Form&lt;/th&gt;
&lt;th&gt;FormEngine&lt;/th&gt;
&lt;th&gt;RJSF&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Login&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;
&lt;strong&gt;-55.6 KB (-23%)&lt;/strong&gt; ⬇️&lt;/td&gt;
&lt;td&gt;+56.4 KB (+32%) ⬆️&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Booking&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;
&lt;strong&gt;-117.4 KB (-37%)&lt;/strong&gt; ⬇️&lt;/td&gt;
&lt;td&gt;+56.4 KB (+32%) ⬆️&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;h3&gt;
  
  
  Why Does FormEngine Become Lighter?
&lt;/h3&gt;

&lt;p&gt;&lt;strong&gt;Comparison of Different UI Library Usage:&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;FormEngine + React Suite by default:
├── Core engine (~50 KB)
├── React Suite components (~190 KB)
└── React Suite CSS (~52 KB)
= 244 KB total

FormEngine + MUI:
├── Core engine (~50 KB)
├── MUI components (already in project)
└── Minimal CSS (~0.2 KB)
= 188 KB total (-23%)
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Why Does RJSF Become Heavier?
&lt;/h3&gt;

&lt;p&gt;&lt;strong&gt;Additive Architecture:&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;RJSF by default:
├── Core engine (~156 KB)
└── Bootstrap CSS (~19 KB)
= 175 KB total

RJSF + MUI:
├── Core engine (~156 KB)
├── MUI adapter layer (~20 KB)
├── MUI components (already in project)
└── Minimal CSS (~0.2 KB)
= 232 KB total (+32%)
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;MUI is &lt;strong&gt;added on top&lt;/strong&gt;, not replacing the base components.&lt;/p&gt;




&lt;h2&gt;
  
  
  What Does This Mean for Real Users?
&lt;/h2&gt;

&lt;p&gt;A difference of 35-43 KB might seem small, but let's translate it into seconds:&lt;/p&gt;

&lt;h3&gt;
  
  
  On Slow 3G (Emerging Markets):
&lt;/h3&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Metric&lt;/th&gt;
&lt;th&gt;43 KB Difference&lt;/th&gt;
&lt;th&gt;Impact&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Load&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;~1.2 sec&lt;/td&gt;
&lt;td&gt;Slower UI appearance&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;TTI&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;~1.0 sec&lt;/td&gt;
&lt;td&gt;Slower interactivity&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;h3&gt;
  
  
  On 4G (Typical Conditions):
&lt;/h3&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Metric&lt;/th&gt;
&lt;th&gt;43 KB Difference&lt;/th&gt;
&lt;th&gt;Impact&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Load&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;~0.13 sec&lt;/td&gt;
&lt;td&gt;Almost imperceptible&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;TTI&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;~0.15 sec&lt;/td&gt;
&lt;td&gt;Barely noticeable&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;&lt;strong&gt;Conclusion:&lt;/strong&gt; If you have users on slow networks (emerging markets, mobile internet in subways, poor WiFi) — every second is critical.&lt;/p&gt;




&lt;h2&gt;
  
  
  Conclusions (And What We Learned About Our Own Product)
&lt;/h2&gt;

&lt;h3&gt;
  
  
  1. &lt;strong&gt;Context Is Everything&lt;/strong&gt;
&lt;/h3&gt;

&lt;p&gt;You can't say "FormEngine is better than RJSF" or vice versa. The right answer depends on your project:&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Choose RJSF if:&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Need minimal baseline&lt;/li&gt;
&lt;li&gt;JSON Schema is your primary source of truth&lt;/li&gt;
&lt;li&gt;Simple forms with basic validation&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;Choose FormEngine if:&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Already using Material UI or another UI kit&lt;/li&gt;
&lt;li&gt;Need deep component customization&lt;/li&gt;
&lt;li&gt;Complex forms with conditional logic&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  2. &lt;strong&gt;Our Competitive Advantage Is Integration&lt;/strong&gt;
&lt;/h3&gt;

&lt;p&gt;We initially designed FormEngine for &lt;strong&gt;embedding into existing projects&lt;/strong&gt; with already installed UI libraries. This architectural decision paid off:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Minus 23-37% bundle when integrating with MUI compared to React Suite&lt;/li&gt;
&lt;li&gt;Complete UI replacement instead of layering&lt;/li&gt;
&lt;li&gt;Zero overhead for components&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  3. &lt;strong&gt;Different Approach to Describing Forms in JSON&lt;/strong&gt;
&lt;/h3&gt;

&lt;p&gt;This is one of the most important differences that affects not only DX but also bundle size:&lt;/p&gt;

&lt;h4&gt;
  
  
  RJSF: Separate Schemas (Data Schema + UI Schema)
&lt;/h4&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight json"&gt;&lt;code&gt;&lt;span class="err"&gt;//&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="err"&gt;data-schema.json&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="err"&gt;-&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="err"&gt;describes&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="err"&gt;data&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;"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;"email"&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;"format"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"email"&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;"password"&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;"minLength"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;8&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;"email"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"password"&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="err"&gt;//&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="err"&gt;ui-schema.json&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="err"&gt;-&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="err"&gt;describes&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="err"&gt;UI&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;"email"&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;"ui:widget"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"email"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"ui:placeholder"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"Enter your email"&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;"password"&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;"ui:widget"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"password"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"ui:help"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"Min 8 characters"&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;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;Pros of Separation:&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;✅&lt;strong&gt;Standardization&lt;/strong&gt; — JSON Schema is an open standard&lt;/li&gt;
&lt;li&gt;✅ &lt;strong&gt;Reusability&lt;/strong&gt; — one data schema can be used in different UIs&lt;/li&gt;
&lt;li&gt;✅ &lt;strong&gt;Validation independent of UI&lt;/strong&gt; — can validate on backend with the same schema&lt;/li&gt;
&lt;li&gt;✅ &lt;strong&gt;Ecosystem&lt;/strong&gt; — many tools for JSON Schema (generators, validators, documentation)&lt;/li&gt;
&lt;li&gt;✅ &lt;strong&gt;Separation of concerns&lt;/strong&gt; — logic separate from presentation&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;Cons of Separation:&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;❌ &lt;strong&gt;Synchronization&lt;/strong&gt; — need to maintain two files in sync&lt;/li&gt;
&lt;li&gt;❌ &lt;strong&gt;Verbosity&lt;/strong&gt; — more code for simple forms&lt;/li&gt;
&lt;li&gt;❌ &lt;strong&gt;Learning curve&lt;/strong&gt; — need to know both formats&lt;/li&gt;
&lt;/ul&gt;

&lt;h4&gt;
  
  
  FormEngine: Unified JSON (Data + UI in One JSON)
&lt;/h4&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight json"&gt;&lt;code&gt;&lt;span class="err"&gt;//&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="err"&gt;form.json&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="err"&gt;-&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="err"&gt;everything&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="err"&gt;in&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="err"&gt;one&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="err"&gt;place&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;"components"&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;"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;"TextField"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
      &lt;/span&gt;&lt;span class="nl"&gt;"key"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"email"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
      &lt;/span&gt;&lt;span class="nl"&gt;"label"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"Email"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
      &lt;/span&gt;&lt;span class="nl"&gt;"placeholder"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"Enter your email"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
      &lt;/span&gt;&lt;span class="nl"&gt;"validation"&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="kc"&gt;true&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
        &lt;/span&gt;&lt;span class="nl"&gt;"email"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="kc"&gt;true&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="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;"PasswordField"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
      &lt;/span&gt;&lt;span class="nl"&gt;"key"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"password"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
      &lt;/span&gt;&lt;span class="nl"&gt;"label"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"Password"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
      &lt;/span&gt;&lt;span class="nl"&gt;"help"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"Min 8 characters"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
      &lt;/span&gt;&lt;span class="nl"&gt;"validation"&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="kc"&gt;true&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
        &lt;/span&gt;&lt;span class="nl"&gt;"minLength"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;8&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="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;&lt;strong&gt;Pros of Unification:&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;✅ &lt;strong&gt;Simplicity&lt;/strong&gt; — one file, one source of truth&lt;/li&gt;
&lt;li&gt;✅ &lt;strong&gt;Less code&lt;/strong&gt; — no duplication of field names&lt;/li&gt;
&lt;li&gt;✅ &lt;strong&gt;Conditional logic&lt;/strong&gt; — easier to describe dependencies between fields&lt;/li&gt;
&lt;li&gt;✅ &lt;strong&gt;DX&lt;/strong&gt; — faster to write and understand&lt;/li&gt;
&lt;li&gt;✅ &lt;strong&gt;Compactness&lt;/strong&gt; — less boilerplate&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;Cons of Unification:&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;❌ &lt;strong&gt;No standardization&lt;/strong&gt; — proprietary FormEngine format&lt;/li&gt;
&lt;li&gt;❌ &lt;strong&gt;Vendor lock-in&lt;/strong&gt; — harder to migrate to another library&lt;/li&gt;
&lt;li&gt;❌ &lt;strong&gt;Validation only on client&lt;/strong&gt; — can't reuse schema on backend directly&lt;/li&gt;
&lt;li&gt;❌ &lt;strong&gt;Fewer tools&lt;/strong&gt; — no JSON Schema ecosystem&lt;/li&gt;
&lt;li&gt;❌ &lt;strong&gt;UI and data coupling&lt;/strong&gt; — UI changes can affect logic&lt;/li&gt;
&lt;/ul&gt;

&lt;h4&gt;
  
  
  Impact on Bundle Size
&lt;/h4&gt;

&lt;p&gt;&lt;strong&gt;RJSF (separate schemas):&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;✅ JSON Schema validator (~15-20 KB)
✅ Standard ajv (might already be in project)
❌ UI Schema parser (~5 KB)
❌ Mapping layer between schemas (~3-5 KB)

Total: ~23-30 KB overhead
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;FormEngine (unified schema):&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;✅ Custom validator (~8-12 KB)
✅ Less parsing
❌ No ajv reuse
❌ Proprietary format

Total: ~8-12 KB overhead
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;Conclusion:&lt;/strong&gt; FormEngine saves ~10-15 KB on schema parsing, but loses standardization benefits.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Important note:&lt;/strong&gt; Although FormEngine uses a proprietary format, it is fully open and &lt;a href="https://formengine.io/documentation/formengine-core/forms-json" rel="noopener noreferrer"&gt;documented&lt;/a&gt;. This means you can study the specification, write your own parsers or form generators, without depending on closed solutions.&lt;/p&gt;




&lt;h3&gt;
  
  
  Real Example: Complex Conditional Logic
&lt;/h3&gt;

&lt;p&gt;Imagine a form where the "Phone" field is shown only if "Contact by phone" is selected:&lt;/p&gt;

&lt;h4&gt;
  
  
  RJSF Approach:
&lt;/h4&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight json"&gt;&lt;code&gt;&lt;span class="err"&gt;//&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="err"&gt;data-schema.json&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;"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;"contactMethod"&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;"email"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"phone"&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;"phone"&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;"pattern"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"^[0-9]{10}$"&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;"dependencies"&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;"phone"&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;"contactMethod"&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;"if"&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;"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;"contactMethod"&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;"const"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"phone"&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="p"&gt;},&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"then"&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;"phone"&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="err"&gt;//&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="err"&gt;ui-schema.json&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;"phone"&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;"ui:widget"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"phone"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"ui:options"&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;"conditional"&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;"show"&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;"field"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"contactMethod"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
          &lt;/span&gt;&lt;span class="nl"&gt;"is"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"phone"&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="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;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;Problem:&lt;/strong&gt; The condition is described in two places! Data schema says "phone required if...", UI schema says "show phone if...". Need to synchronize.&lt;/p&gt;

&lt;h4&gt;
  
  
  FormEngine Approach:
&lt;/h4&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;"components"&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;"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;"RadioGroup"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
      &lt;/span&gt;&lt;span class="nl"&gt;"key"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"contactMethod"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
      &lt;/span&gt;&lt;span class="nl"&gt;"label"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"Contact method"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
      &lt;/span&gt;&lt;span class="nl"&gt;"options"&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;"value"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"email"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nl"&gt;"label"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"Email"&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;"value"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"phone"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nl"&gt;"label"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"Phone"&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="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;"PhoneField"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
      &lt;/span&gt;&lt;span class="nl"&gt;"key"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"phone"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
      &lt;/span&gt;&lt;span class="nl"&gt;"label"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"Phone number"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
      &lt;/span&gt;&lt;span class="nl"&gt;"conditional"&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;"show"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"{{contactMethod === 'phone'}}"&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;"validation"&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="s2"&gt;"{{contactMethod === 'phone'}}"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
        &lt;/span&gt;&lt;span class="nl"&gt;"pattern"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"^[0-9]{10}$"&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="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;&lt;strong&gt;Advantage:&lt;/strong&gt; Condition described once. UI and validation automatically synchronized.&lt;/p&gt;




&lt;h3&gt;
  
  
  When Is Each Approach Better?
&lt;/h3&gt;

&lt;h4&gt;
  
  
  Choose RJSF (separate schemas) if:
&lt;/h4&gt;

&lt;ul&gt;
&lt;li&gt;You already have JSON Schema for API validation&lt;/li&gt;
&lt;li&gt;Need one schema for frontend and backend&lt;/li&gt;
&lt;li&gt;Working in a team where backend generates schemas&lt;/li&gt;
&lt;li&gt;Using JSON Schema ecosystem tools&lt;/li&gt;
&lt;li&gt;Need compatibility with third-party systems&lt;/li&gt;
&lt;li&gt;Simple forms without complex conditional logic&lt;/li&gt;
&lt;/ul&gt;

&lt;h4&gt;
  
  
  Choose FormEngine (unified schema) if:
&lt;/h4&gt;

&lt;ul&gt;
&lt;li&gt;Forms are complex with many conditions&lt;/li&gt;
&lt;li&gt;UI logic is more important than data validation&lt;/li&gt;
&lt;li&gt;Want to avoid duplication&lt;/li&gt;
&lt;li&gt;DX and development speed are priorities&lt;/li&gt;
&lt;li&gt;Not planning to migrate to another library&lt;/li&gt;
&lt;/ul&gt;




&lt;h3&gt;
  
  
  4. &lt;strong&gt;Transparency Builds Trust&lt;/strong&gt;
&lt;/h3&gt;

&lt;p&gt;We've published all data, including scenarios where RJSF is faster. This is our principle: &lt;strong&gt;honesty is more important than marketing&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;If you find errors in the tests — &lt;a href="https://github.com/optimajet/formengine/issues" rel="noopener noreferrer"&gt;open an issue&lt;/a&gt;, we'll fix it.&lt;/p&gt;




&lt;h2&gt;
  
  
  Detailed Data
&lt;/h2&gt;

&lt;h3&gt;
  
  
  Comparison Table (All Scenarios)
&lt;/h3&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Scenario&lt;/th&gt;
&lt;th&gt;RJSF (gzip)&lt;/th&gt;
&lt;th&gt;FormEngine (gzip)&lt;/th&gt;
&lt;th&gt;Winner&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;Login default UI&lt;/td&gt;
&lt;td&gt;&lt;strong&gt;175.26 KB&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;244.19 KB&lt;/td&gt;
&lt;td&gt;RJSF (-39%)&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Login MUI&lt;/td&gt;
&lt;td&gt;231.62 KB&lt;/td&gt;
&lt;td&gt;&lt;strong&gt;188.54 KB&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;FormEngine (-19%)&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Booking default UI&lt;/td&gt;
&lt;td&gt;&lt;strong&gt;178.07 KB&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;316.69 KB&lt;/td&gt;
&lt;td&gt;RJSF (-78%)&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Booking MUI&lt;/td&gt;
&lt;td&gt;234.50 KB&lt;/td&gt;
&lt;td&gt;&lt;strong&gt;199.26 KB&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;FormEngine (-15%)&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;h3&gt;
  
  
  Detailed Bundle Breakdown
&lt;/h3&gt;

&lt;h4&gt;
  
  
  RJSF Login (default UI):
&lt;/h4&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Code:     480.72 KB raw / 156.37 KB gzip (80%)
CSS:      117.18 KB raw / 19.27 KB gzip (20%)
Total:    597.91 KB raw / 175.64 KB gzip
Chunks:   2
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h4&gt;
  
  
  FormEngine Login (default UI):
&lt;/h4&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Code:     626.23 KB raw / 192.65 KB gzip (59%)
CSS:      438.18 KB raw / 52.42 KB gzip (41%)
Total:    1.04 MB raw / 245.07 KB gzip
Chunks:   2
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h4&gt;
  
  
  RJSF Login (MUI):
&lt;/h4&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Code:     725.19 KB raw / 232.47 KB gzip (100%)
CSS:      186 B raw / 169 B gzip (0%)
Total:    725.37 KB raw / 232.64 KB gzip
Chunks:   2
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h4&gt;
  
  
  FormEngine Login (MUI):
&lt;/h4&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Code:     622.22 KB raw / 189.27 KB gzip (100%)
CSS:      186 B raw / 169 B gzip (0%)
Total:    622.40 KB raw / 189.44 KB gzip
Chunks:   2
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;Observation:&lt;/strong&gt; After switching to MUI, CSS practically disappears for both libraries (186 bytes). The entire difference is in the JS code.&lt;/p&gt;




&lt;h2&gt;
  
  
  Practical Recommendations
&lt;/h2&gt;

&lt;h3&gt;
  
  
  If You DON'T Have a UI Library in Your Project:
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Recommendation: RJSF

Reason: 
- Lighter out of the box (175 KB vs 244 KB)
- Faster setup
- No need to choose UI kit
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  If You HAVE Material UI:
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Recommendation: FormEngine

Reason:
- Lighter with MUI (188 KB vs 232 KB)
- No duplication of UI code
- Full integration with your Design System
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  If You Have Another UI Kit (Ant Design, Chakra, etc):
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Recommendation: Depends on adapter availability

RJSF: Has adapters for many UI kits
FormEngine: Currently only MUI and React Suite

Check documentation for both libraries
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  If Planning to Change UI Kit in the Future:
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Recommendation: FormEngine

Reason:
- UI replacement architecture
- Easier to migrate between UI kits
- Less technical debt
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;






&lt;h2&gt;
  
  
  Reproducibility
&lt;/h2&gt;

&lt;p&gt;All tests are available and reproducible:&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;GitHub Repository:&lt;/strong&gt;&lt;br&gt;
👉 &lt;a href="https://github.com/optimajet/formengine/tree/master/community/examples/bundle-size" rel="noopener noreferrer"&gt;github.com/optimajet/formengine/tree/master/community/examples/bundle-size&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Full Report:&lt;/strong&gt;&lt;br&gt;
👉 &lt;a href="https://formengine.io/documentation/bundle-size-comparison" rel="noopener noreferrer"&gt;formengine.io/documentation/bundle-size-comparison&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;How to Run Yourself:&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;git clone https://github.com/optimajet/formengine.git
&lt;span class="nb"&gt;cd &lt;/span&gt;formengine/community/examples/bundle-size
npm &lt;span class="nb"&gt;install
&lt;/span&gt;npm run build
npm run analyze
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;What You'll Get:&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Bundle size report&lt;/li&gt;
&lt;li&gt;Chunk visualization&lt;/li&gt;
&lt;li&gt;Duplicate packages detection&lt;/li&gt;
&lt;li&gt;Tree-shaking analysis&lt;/li&gt;
&lt;/ul&gt;




&lt;h2&gt;
  
  
  What's Next?
&lt;/h2&gt;

&lt;h3&gt;
  
  
  Try It Yourself
&lt;/h3&gt;

&lt;p&gt;&lt;strong&gt;RJSF:&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;📚 &lt;a href="https://rjsf-team.github.io/react-jsonschema-form/" rel="noopener noreferrer"&gt;Documentation&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;💻 &lt;a href="https://github.com/rjsf-team/react-jsonschema-form" rel="noopener noreferrer"&gt;GitHub&lt;/a&gt;
&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;FormEngine:&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;📚 &lt;a href="https://formengine.io/documentation" rel="noopener noreferrer"&gt;Documentation&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;💻 &lt;a href="https://github.com/optimajet/formengine" rel="noopener noreferrer"&gt;GitHub&lt;/a&gt;
&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  Give Feedback
&lt;/h3&gt;

&lt;p&gt;If you:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Found errors in tests&lt;/li&gt;
&lt;li&gt;Want to add new scenarios&lt;/li&gt;
&lt;li&gt;Disagree with conclusions&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Write to us:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Let us know what you think in the comments 👇&lt;/li&gt;
&lt;li&gt;&lt;a href="https://github.com/optimajet/formengine/issues" rel="noopener noreferrer"&gt;GitHub Issues&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="mailto:hello@optimajet.com"&gt;hello@optimajet.com&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;




&lt;h2&gt;
  
  
  Final Verdict
&lt;/h2&gt;

&lt;p&gt;&lt;strong&gt;There's no universal winner.&lt;/strong&gt; And that's good! &lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;RJSF&lt;/strong&gt; — excellent choice for quick start and JSON Schema purists&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;FormEngine&lt;/strong&gt; — optimal for integration into existing projects with UI kits&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Choose based on your context, not marketing.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;What's your experience with RJSF or FormEngine? Or are you using something else? Share in the comments! 👇&lt;/strong&gt;&lt;/p&gt;




&lt;p&gt;&lt;em&gt;P.S. We're Optimajet, also making &lt;a href="https://workflowengine.io" rel="noopener noreferrer"&gt;Workflow Engine&lt;/a&gt; for processes and &lt;a href="https://workflowserver.io" rel="noopener noreferrer"&gt;Workflow Server&lt;/a&gt; for business automation.&lt;/em&gt;&lt;/p&gt;

</description>
      <category>javascript</category>
      <category>react</category>
      <category>webdev</category>
      <category>frontend</category>
    </item>
    <item>
      <title>FormEngine Core is Now Open Source</title>
      <dc:creator>Optimajet Limited</dc:creator>
      <pubDate>Tue, 12 Aug 2025 14:22:39 +0000</pubDate>
      <link>https://forem.com/optimajet/formengine-core-is-now-open-source-n31</link>
      <guid>https://forem.com/optimajet/formengine-core-is-now-open-source-n31</guid>
      <description>&lt;p&gt;If you've ever spent hours wrestling with complex forms in React, struggling with validation, localization, or custom components, FormEngine is here to transform your workflow. This powerful tool combines an intuitive visual designer with a flexible, code-first library, enabling you to create any form, from simple to dynamic, data-driven ones, with ease. Born from our team's real-world challenges, FormEngine empowers solo developers and enterprise teams alike to save time and scale projects effortlessly. Curious about how it became a game-changer for developers? Read on to dive into the full story!&lt;/p&gt;

&lt;h2&gt;
  
  
  Your Ultimate Solution for Building Forms in React.
&lt;/h2&gt;

&lt;p&gt;Here’s a little story about how it all became possible. We began developing FormEngine in early 2023 to address our own internal needs, driven by the immaturity of the React form library ecosystem both in terms of backend-driven form generation and visual form designers. Our goal was to replace our outdated FormBuilder.dev, with a more modern and developer-friendly form builder built for React.&lt;/p&gt;

&lt;p&gt;After a thorough investigation, we hoped to find an open-source library we could build on something robust enough to support our team and integrate seamlessly into our commercial products: &lt;strong&gt;Optimajet Workflow Server&lt;/strong&gt; and form-related plugins for &lt;strong&gt;WorkflowEngine&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;We evaluated the most popular MIT-licensed libraries and have great respect for React Hook Form, Formik, React Final Form, and SurveyJS, each of which has made a significant contribution to the React ecosystem.&lt;br&gt;
When tested against the strict internal requirements of the Optimajet development team, none could fully deliver the flexibility, integration depth, and scalability needed for our enterprise-grade use cases.&lt;/p&gt;

&lt;p&gt;One of the key requirements especially for large teams in big tech companies or custom software development firms is the ability to easily and quickly integrate custom components. We recognized that this was a common pain point across the industry, and we had the expertise to solve it.&lt;/p&gt;

&lt;p&gt;That insight led us to a bold decision: to build the best React-based FormBuilder from scratch-first and foremost, for ourselves. We surveyed our enterprise customers and small teams building business applications for workflow automation. Based on their feedback and requirements, we formed the foundation for what we believe to be an ideal form library one that supports code-first form creation in React, and serves as the engine behind a low or no-code visual form designer.&lt;/p&gt;

&lt;h3&gt;
  
  
  Here is the list of requirements and brief explanations that guided the Optimajet team when we started developing FormEngine Core.
&lt;/h3&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;strong&gt;Lower learning curve:&lt;/strong&gt; Easily create forms using typed FormEngine Core functions, without writing components or learning complex React concepts. JSON representation of the form is also supported for configuration-driven use.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Built-in form validation:&lt;/strong&gt; Data validation works out of the box with no extra code. Required fields, error messages, and rules are defined directly in code or JSON. Easily integrates with third-party validation libraries.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Built-in localization:&lt;/strong&gt; Forms are ready for multi-language support out of the box. Third-party localization libraries can be integrated if needed.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Dynamic CSS and responsive layout support:&lt;/strong&gt; Forms automatically adapt to different devices and styles  no additional layout code needed.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Built-in actions:&lt;/strong&gt; Forms support actions like submit, reset, and external calls out of the box. Define only what you need in code or JSON and it’ll just work.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Reusable forms across apps:&lt;/strong&gt; Cross-project compatibility just copy and use forms are easily portable between applications with minimal effort. A single JSON object contains the full structure, logic, styles, validation, and actions.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Programmatic form creation and dynamic generation:&lt;/strong&gt; Build or modify forms in real time using code or external data sources.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Ready-to-use component library:&lt;/strong&gt; Includes built-in components and supports easy integration of custom ones. Get started fast without sacrificing flexibility.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Easy custom component integration&lt;/strong&gt;: Quickly define your own component by specifying its name, type, and props.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Ready to use with popular frameworks:&lt;/strong&gt; Works seamlessly with Next.js, Remix, and other modern React stacks  no special setup needed.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;High performance and lightweight:&lt;/strong&gt; Fast load times, smooth rendering, and minimal impact on app performance.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;On &lt;strong&gt;October 31, 2023&lt;/strong&gt;, we released &lt;strong&gt;FormEngine 0.0.13&lt;/strong&gt;  our new standalone commercial product. &lt;a href="https://formengine.io/documentation/release-notes#0013" rel="noopener noreferrer"&gt;Release notes →&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;This marked the beginning of a journey to bring to life everything our development team had envisioned for the platform. And right from day one, the results confirmed we were on the right track.&lt;/p&gt;

&lt;p&gt;We delivered a complete, time-saving tool for development teams  something that works just as well for solo developers as it does for large projects. Whether you're building a few simple forms or managing hundreds or thousands of dynamically generated ones from a backend  &lt;strong&gt;FormEngine just works.&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;The initial sales were strong, and as demand grew, we even experimented with pricing tiers and product options to better understand what triggered the “Aha!” moment for our users.&lt;/p&gt;

&lt;p&gt;That moment where everything clicks  and the value is obvious.&lt;/p&gt;

&lt;p&gt;We’re still searching for a definitive answer to what exactly made the product such a commercial success, especially among enterprise teams. But one thing is clear: we hit a real need, and we’re excited to keep building on it. &lt;/p&gt;

&lt;p&gt;Thanks to the commercial licenses issued to our partners custom software companies we’ve been improving the &lt;strong&gt;FormEngine&lt;/strong&gt; libraries day by day, with one clear goal:&lt;/p&gt;

&lt;p&gt;To create the best React-based form solution on the market for developers and businesses who want powerful forms without the usual complexity.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;We give developers everything they need to build real, working forms  without the usual mess of extra tools, boilerplate, and setup.&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://www.npmjs.com/package/@react-form-builder/core" rel="noopener noreferrer"&gt;@react-form-builder/core&lt;/a&gt; Community MIT Open Source Form Library for React  &lt;/p&gt;

&lt;p&gt;&lt;a href="https://www.npmjs.com/package/@react-form-builder/components-rsuite" rel="noopener noreferrer"&gt;@react-form-builder/components-rsuite&lt;/a&gt; Form Components Library &lt;/p&gt;

&lt;p&gt;&lt;a href="https://www.npmjs.com/package/@react-form-builder/designer" rel="noopener noreferrer"&gt;@react-form-builder/designer&lt;/a&gt; Premium Drag-and-Drop Form Builder, also known as the Visual Form Designer&lt;/p&gt;

&lt;h2&gt;
  
  
  Why FormEngine Core is Now Open Source?
&lt;/h2&gt;

&lt;p&gt;Many of our partners, who use FormEngine as part of their business process automation and approval workflow applications, asked us to open up the core Formengine  so they could deeply integrate it into their systems and even extend its functionality where needed.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;And now, after nearly two years of development and five major releases, the time has come.&lt;/strong&gt; &lt;/p&gt;

&lt;p&gt;On 26 June 2025, we are proud of the quality, stability, and architecture of our code, and we are ready to share it. By open-sourcing the FormEngine Core library, we make this technology freely available to the global developer community, fostering innovation, transparency, and long-term adoption.&lt;/p&gt;

&lt;p&gt;Your support means the world to us, and we’d love for you to be part of this exciting new chapter for FormEngine.&lt;/p&gt;

&lt;h3&gt;
  
  
  &lt;strong&gt;If you find value in what we’re building, consider giving us a ⭐️ on &lt;a href="https://github.com/optimajet/formengine" rel="noopener noreferrer"&gt;GitHub&lt;/a&gt;  it helps more amazing developers like you discover FormEngine Core.&lt;/strong&gt;
&lt;/h3&gt;

&lt;p&gt;Open source thrives on collaboration, and we warmly welcome contributors who want to join us on this journey. Whether it’s contributing code, sharing ideas, or spreading the word, your involvement will &lt;a href="https://github.com/optimajet/formengine/discussions" rel="noopener noreferrer"&gt;help FormEngine, and our growing community thrive&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;With gratitude and excitement, &lt;strong&gt;The Optimajet Developers Team&lt;/strong&gt;&lt;/p&gt;

</description>
      <category>react</category>
      <category>opensource</category>
      <category>frontend</category>
      <category>webdev</category>
    </item>
    <item>
      <title>A True React Hook Form Alternative – FormEngine Core 4.0 Is Now MIT Licensed and Free! 🚀</title>
      <dc:creator>Optimajet Limited</dc:creator>
      <pubDate>Tue, 27 May 2025 18:06:46 +0000</pubDate>
      <link>https://forem.com/optimajet/a-true-react-hook-form-alternative-formengine-40-is-now-mit-licensed-and-free-1gke</link>
      <guid>https://forem.com/optimajet/a-true-react-hook-form-alternative-formengine-40-is-now-mit-licensed-and-free-1gke</guid>
      <description>&lt;p&gt;React developers, here's big news! On May 15, 2025, Optimajet released FormEngine Core 4.0, making essential libraries available under the permissive MIT license free even for commercial use. FormEngine is now the leading alternative to React Hook Form, especially for teams building complex, interactive forms.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Why switch from React Hook Form to FormEngine?&lt;/strong&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  ⚡️ Rapid and Simple Setup
&lt;/h2&gt;

&lt;p&gt;React Hook Form requires extensive manual setup of controllers, hooks, and validation logic. FormEngine simplifies this by leveraging intuitive, schema-based definitions.&lt;/p&gt;

&lt;h2&gt;
  
  
  🎨 Powerful Drag-and-Drop FormEngine Visual Designer
&lt;/h2&gt;

&lt;p&gt;Unlike React Hook Form’s code-only approach, FormEngine includes an intuitive visual editor, allowing instant form creation and modification, significantly speeding up development. &lt;em&gt;(Note: FormEngine Visual Designer is a paid component for commercial use; however, its full functionality is available for unlimited testing.)&lt;/em&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  🔌 Easy Custom Components Integration
&lt;/h2&gt;

&lt;p&gt;React Hook Form’s custom component integration can be cumbersome. FormEngine makes this seamless, simplifying component binding and custom logic implementation.&lt;/p&gt;

&lt;h2&gt;
  
  
  📱 Real-Time Form Previews
&lt;/h2&gt;

&lt;p&gt;Get instant visual feedback as you build forms. React Hook Form needs extra setup or third-party tools for similar functionality.&lt;/p&gt;

&lt;h2&gt;
  
  
  Built-In Component Library
&lt;/h2&gt;

&lt;p&gt;Unlike React Hook Form, FormEngine comes with a built-in library of ready-to-use components (@react-form-builder/components-rsuite), further accelerating development and reducing the need to create components from scratch.&lt;/p&gt;

&lt;h2&gt;
  
  
  Completely Free and MIT Licensed
&lt;/h2&gt;

&lt;p&gt;FormEngine’s core libraries are now MIT-licensed and fully free, even for commercial use:&lt;/p&gt;

&lt;p&gt;📦 &lt;a href="https://www.npmjs.com/package/@react-form-builder/core" rel="noopener noreferrer"&gt;@react-form-builder/core&lt;/a&gt;&lt;br&gt;
📦 &lt;a href="https://www.npmjs.com/package/@react-form-builder/components-rsuite" rel="noopener noreferrer"&gt;@react-form-builder/components-rsuite&lt;/a&gt;&lt;br&gt;
📦 &lt;a href="https://www.npmjs.com/package/@react-form-builder/viewer-bundle" rel="noopener noreferrer"&gt;@react-form-builder/viewer-bundle&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  💡 Highlights of FormEngine Core 4.0:
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;UI-Agnostic: Integrate effortlessly with UI libraries like MUI, Ant Design, shadcn/ui, and more.&lt;/li&gt;
&lt;li&gt;Framework-Friendly: Built-in support for Next.js, Remix, and framework-agnostic CDN deployment.&lt;/li&gt;
&lt;li&gt;Multi-Database Compatibility: Seamlessly use MySQL, PostgreSQL, MongoDB, SQLite, and more.&lt;/li&gt;
&lt;li&gt;Robust Validation: Powered by Zod, with extensible support for Yup, AJV, Superstruct, and Joi.&lt;/li&gt;
&lt;li&gt;Dynamic &amp;amp; Responsive: Create reactive, adaptive layouts with MobX-powered dynamic properties.&lt;/li&gt;
&lt;li&gt;Flexible Storage: Store forms as JSON or generate them programmatically.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;🎬 Watch the video to see FormEngine in action—start building your forms faster, smarter, and with greater ease than ever before!&lt;/p&gt;

&lt;p&gt;In this step-by-step tutorial, I'll walk you through building a simple React demo app using FormEngine. You'll see how quickly you can design, render, and manage forms — without writing endless custom code.&lt;/p&gt;

&lt;h2&gt;
  
  
  Install
&lt;/h2&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;npm install @react-form-builder/core
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Quickstart
&lt;/h2&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;viewWithCss&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;@react-form-builder/components-rsuite&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;
&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;buildForm&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;FormViewer&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;@react-form-builder/core&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;

&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;simpleForm&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;buildForm&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt;&lt;span class="na"&gt;errorType&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;RsErrorMessage&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="nf"&gt;component&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;container&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="s1"&gt;RsContainer&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="nf"&gt;style&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt;&lt;span class="na"&gt;flexDirection&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;row&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="nf"&gt;children&lt;/span&gt;&lt;span class="p"&gt;((&lt;/span&gt;&lt;span class="nx"&gt;builder&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt;
    &lt;span class="nx"&gt;builder&lt;/span&gt;
      &lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;component&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;firstName&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="s1"&gt;RsInput&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="nf"&gt;prop&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;placeholder&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="s1"&gt;Enter your first name&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="nf"&gt;prop&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;label&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="s1"&gt;First Name&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="nf"&gt;validation&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;required&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="nf"&gt;component&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;lastName&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="s1"&gt;RsInput&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="nf"&gt;prop&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;placeholder&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="s1"&gt;Enter your last name&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="nf"&gt;prop&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;label&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="s1"&gt;Last Name&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="nf"&gt;validation&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;required&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
  &lt;span class="p"&gt;)&lt;/span&gt;

  &lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;component&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;birthDate&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="s1"&gt;RsDatePicker&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="nf"&gt;prop&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;label&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="s1"&gt;Birth Date&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="nf"&gt;prop&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;oneTap&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="kc"&gt;true&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
  &lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;validation&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;min&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nf"&gt;args&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt;&lt;span class="na"&gt;value&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;1900-01-07T12:25:37.000Z&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="nf"&gt;component&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;submit&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="s1"&gt;RsButton&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="nf"&gt;prop&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;children&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="s1"&gt;Submit&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="nf"&gt;prop&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;color&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="s1"&gt;blue&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="nf"&gt;prop&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;appearance&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="s1"&gt;primary&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="nf"&gt;event&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;onClick&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="nf"&gt;commonAction&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;validate&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nf"&gt;args&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt;&lt;span class="na"&gt;failOnError&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kc"&gt;true&lt;/span&gt;&lt;span class="p"&gt;})&lt;/span&gt;
  &lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;customAction&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;onSubmit&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="nf"&gt;json&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;

&lt;span class="k"&gt;export&lt;/span&gt; &lt;span class="kd"&gt;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="k"&gt;return&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;FormViewer&lt;/span&gt;
    &lt;span class="nx"&gt;view&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;viewWithCss&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;
    &lt;span class="nx"&gt;getForm&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="p"&gt;{()&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="nx"&gt;simpleForm&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;
    &lt;span class="nx"&gt;actions&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="p"&gt;{{&lt;/span&gt;
      &lt;span class="na"&gt;onSubmit&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;e&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="c1"&gt;// submit the form to the backend&lt;/span&gt;
        &lt;span class="nf"&gt;alert&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;Form data: &lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="nx"&gt;JSON&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;stringify&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;e&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;data&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt;
      &lt;span class="p"&gt;},&lt;/span&gt;
    &lt;span class="p"&gt;}}&lt;/span&gt;
  &lt;span class="sr"&gt;/&lt;/span&gt;&lt;span class="err"&gt;&amp;gt;
&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  What you'll learn:
&lt;/h2&gt;

&lt;ol&gt;
&lt;li&gt;How to install and set up the FormEngine Core Library&lt;/li&gt;
&lt;li&gt;Creating and editing forms using JSON&lt;/li&gt;
&lt;li&gt;Running your app and previewing form behavior&lt;/li&gt;
&lt;li&gt;Using the FormEngine Visual Designer to create forms&lt;/li&gt;
&lt;/ol&gt;

&lt;h2&gt;
  
  
  🌍 Help us grow the ecosystem, if you like the project:
&lt;/h2&gt;

&lt;p&gt;⭐ Star us on &lt;a href="https://github.com/optimajet/formengine" rel="noopener noreferrer"&gt;GitHub&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;💬 Share feedback! Have feature requests or thoughts on the docs? Share them in the comments below!&lt;/p&gt;

&lt;p&gt;🔗 Mention &lt;a class="mentioned-user" href="https://dev.to/optimajet"&gt;@optimajet&lt;/a&gt; Formengine &lt;a href="https://x.com/" rel="noopener noreferrer"&gt;X / Twitter&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  🚀 This is just the beginning — part two is on the way!
&lt;/h2&gt;

&lt;p&gt;We'll provide a detailed comparison between React Hook Form and FormEngine Core.&lt;/p&gt;

&lt;p&gt;📘 Docs, Live Demo &amp;amp; Examples: &lt;a href="https://formengine.io/documentation" rel="noopener noreferrer"&gt;formengine.io/documentation&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;We’d love to address your specific questions, so please leave your questions in the comments, and we'll include the answers in our upcoming comparison!&lt;/strong&gt;&lt;/p&gt;

</description>
      <category>react</category>
      <category>webdev</category>
      <category>frontend</category>
      <category>javascript</category>
    </item>
    <item>
      <title>Key differences between BPMN diagrams and Optimajet .NET Workflow Engine process schemes</title>
      <dc:creator>Optimajet Limited</dc:creator>
      <pubDate>Mon, 04 Nov 2024 16:06:28 +0000</pubDate>
      <link>https://forem.com/optimajet/key-differences-between-bpmn-diagrams-and-optimajet-net-workflow-engine-process-schemes-21ka</link>
      <guid>https://forem.com/optimajet/key-differences-between-bpmn-diagrams-and-optimajet-net-workflow-engine-process-schemes-21ka</guid>
      <description>&lt;p&gt;&lt;strong&gt;Element specialization&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;In BPMN, there are a lot of elements that often have narrow specializations and are categorized into Tasks, Gateways, and Events, although other distinct elements exist as well. The Sequence flow is particularly significant and stands out.&lt;br&gt;
In Workflow Engine, there are only two types of elements in the scheme — Activities and Transitions. By combining the configurations of these two elements, you can create Workflow Engine schemes that function similarly to the corresponding BPMN elements.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Activity is not a Task&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;At first glance, an Activity appears as a rectangle, similar to a Task, and it may seem like these elements are alike. However, they're actually quite different. An Activity can represent a Service Task, a Gateway, or even an Event. The main function of an Activity is to execute your code, but the overall behavior of the scheme (i.e., the direction and manner in which the process flows next) depends on the settings of the outgoing Transitions from the Activity.&lt;/p&gt;

&lt;p&gt;For example, if an Activity has Transitions triggered by Commands, it acts similarly to an Event-based Gateway; however, unlike a Gateway, the Activity can execute some code. If the Transitions from an Activity are configured to start parallel processes, then that Activity will behave like a Parallel Gateway. And so on.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Transition is not a Sequence Flow&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;At first glance, Transition and Sequence Flow may seem like similar elements, as both represent arrows between elements on a diagram. However, they're actually quite different.&lt;/p&gt;

&lt;p&gt;In Workflow Engine, a Transition defines how and where the process execution will transition. For example, a process can move to the next state based on a Timer or a Command. What is set by events in BPMN is managed through transitions in Workflow Engine. Additionally, Transitions can be conditional, and access to them can be restricted to specific users or roles. Transitions also determine parallelism, which in BPMN is either set through Gateways or implicitly defined.&lt;/p&gt;

&lt;p&gt;In BPMN, however, a Sequence Flow only defines the direction of the transition. This element has almost no settings, except for flows coming out of exclusive gateways.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Parallelism difference&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Parallelism in BPMN and Workflow Engine operates on different, yet non-contradictory principles.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;In BPMN, parallel execution is defined either explicitly, using a Parallel Gateway, or implicitly, for example, when multiple Sequence Flows emerge from a single Service Task or Event. In this case, it is considered that the process remains singular, but several tokens are introduced. This can lead to a situation where, if you don't introduce a merging element or remove these tokens, multiple tokens will continue during sequential process execution.&lt;/li&gt;
&lt;li&gt;In Workflow Engine, you can assume that there is always only one token within a single process, and parallelism is achieved by creating dependent processes (called subprocesses in Workflow Engine). These subprocesses depend on the process that spawned them, and you can retrieve a list of Activities where the parent process and all its child subprocesses are located, as well as manage the parent process and its subprocesses collectively. The creation and merging of processes are handled by transition settings. However, if this approach is unfamiliar, you can use the Parallel Gateway, which replicates the behavior of its BPMN counterpart.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;Subprocesses in BPMN and Workflow Engine are completely different&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;In BPMN, a Subprocess is merely a nested part of the main diagram that can be collapsed. It can't be reused and is primarily for aesthetic purposes. Workflow Engine has a similar feature called Inline Activity. This is a special activity that embeds another scheme into the current one. The embedded scheme can be used in multiple other schemes, allowing for reusability.&lt;/li&gt;
&lt;li&gt;In Workflow Engine, a subprocess is a dependent process, as mentioned earlier.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;Workflow Engine provides real access control to Commands&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;In Workflow Engine, Actors are part of the process, and you can set restrictions on command execution (similar to a Message Catch Event) by specific users directly within the scheme. BPMN doesn't offer such functionality explicitly.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Execution ready approach&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;A valid Workflow Engine scheme is always ready for execution and can be run on the Workflow Engine. In contrast, a valid BPMN diagram might just be an illustration, and no engine will necessarily be able to execute it.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Ability to set the Process to any state&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;In Workflow Engine, a running process can always be forcibly set to any of its states. BPMN doesn't offer such a capability.&lt;/p&gt;

&lt;p&gt;Armed with this knowledge, let's move on to exploring which BPMN elements are supported in Workflow Engine and how they’re implemented.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Configuring and using BPMN plugin&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;You can read about how to install, configure, and start using the BPMN Diagram Import Plugin in the .NET Workflow Engine in the &lt;a href="https://workflowengine.io/documentation/bpmn-plugin" rel="noopener noreferrer"&gt;official documentation.&lt;/a&gt;&lt;/p&gt;

</description>
      <category>bpmn</category>
      <category>dotnet</category>
      <category>csharp</category>
    </item>
    <item>
      <title>Introducing BPMN support in .NET Workflow Engine library</title>
      <dc:creator>Optimajet Limited</dc:creator>
      <pubDate>Mon, 04 Nov 2024 15:55:44 +0000</pubDate>
      <link>https://forem.com/optimajet/introducing-bpmn-support-in-net-workflow-engine-library-4o71</link>
      <guid>https://forem.com/optimajet/introducing-bpmn-support-in-net-workflow-engine-library-4o71</guid>
      <description>&lt;p&gt;Many .NET developers, during the POC process, requested that we add the ability to import BPMN schemas into our WorkflowEngine. In an new &lt;a href="https://workflowengine.io/documentation/release-notes/workflow-engine/#breaking-changes" rel="noopener noreferrer"&gt;update&lt;/a&gt;, Optimajet's Workflow Engine now introduces foundational BPMN support, making it easier for .net developers to work with familiar process elements and streamline workflow designs. While Workflow Engine is not a dedicated BPMN engine, this new capability bridges some gaps by enabling users to work with BPMN elements, enhancing compatibility and efficiency for process modeling.&lt;/p&gt;

&lt;p&gt;Workflow Engine is not a BPMN engine, so full compliance with the BPMN standard isn't achievable. However, the process execution principles in Workflow Engine align with those of BPMN. Consequently, BPMN support in Workflow Engine is grounded in two key aspects:&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;BPMN Elements in Workflow Engine Scheme:&lt;/strong&gt; We have added basic BPMN elements to Workflow Engine so that when a BPMN diagram is imported, familiar elements remain, making it clear where attention should be focused. Some of these elements are useful on their own, such as the Parallel Gateway, which can be beneficial for creating and merging subprocesses in Workflow Engine in a simpler and more understandable way.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;BPMN Import:&lt;/strong&gt; You can import a BPMN diagram, and it will be converted into a Workflow Engine scheme. A detailed log and comments will indicate what is unsupported or only partially supported in the current implementation.&lt;br&gt;
The structure of this section will be as follows. First, we will describe the differences between BPMN diagrams and Workflow Engine process schemes. Then, we will review which BPMN diagram elements are supported in Workflow Engine and how they are implemented. Finally, we will explain how to integrate BPMN import into an application running Workflow Engine and how to customize this import process.&lt;/p&gt;

&lt;h2&gt;
  
  
  BPMN elements support in Workflow Engine
&lt;/h2&gt;

&lt;p&gt;The BPMN plugin for Workflow Engine currently supports only the most essential BPMN elements, with new functionalities being progressively added. Here’s an overview of the supported and partially supported elements:&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Tasks&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Generic Task - Converted into a standard Activity.&lt;/li&gt;
&lt;li&gt;Service Task - Transformed into a specialized Activity based on the values of attributes like &lt;code&gt;camunda:topic&lt;/code&gt; and &lt;code&gt;camunda:delegateExpression&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;Receive Task - Supported, with an outgoing transition triggered by a Command.&lt;/li&gt;
&lt;li&gt;User Task. Not supported yet; support will be added after the release of the plugin integrating Workflow Engine with forms.&lt;/li&gt;
&lt;li&gt;Business Rule Task. Not supported; will be converted into a standard Activity.&lt;/li&gt;
&lt;li&gt;Manual Task. Not supported; will be converted into a standard Activity.&lt;/li&gt;
&lt;li&gt;Script Task. Not supported; will be converted into a standard Activity.&lt;/li&gt;
&lt;li&gt;Send Task. Not supported; will be converted into a standard Activity.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;Gateways&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Exclusive Gateway and Parallel Gateway - Supported.&lt;/li&gt;
&lt;li&gt;Event-Based Gateway - Supported and converted into an Activity with transitions triggered by corresponding events.&lt;/li&gt;
&lt;li&gt;Inclusive and Complex Gateways - Not supported and are currently converted into standard Activities.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;Events&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Start Events - Generic Start Event is supported, with partial support for Message and Timer types.&lt;/li&gt;
&lt;li&gt;End Events - Generic and Terminate End Events are supported.&lt;/li&gt;
&lt;li&gt;Boundary Events - Partially supported; Message and Timer Boundary Events are converted into transitions with Command and Timer triggers.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;Other Elements&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Subprocesses and Pools - Converted to Inline Activities or separate workflow schemes.&lt;/li&gt;
&lt;li&gt;Call Activities and Lanes - Not supported; Lanes are ignored due to no equivalent grouping method in Workflow Engine.&lt;/li&gt;
&lt;li&gt;Parallelism&lt;/li&gt;
&lt;li&gt;In BPMN diagrams, implicit parallelism is converted to explicit parallelism in Workflow Engine, using dashed lines to mark the start of subprocesses and dash-dotted lines for their completion.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;Feedback&lt;/strong&gt;&lt;br&gt;
Since BPMN support is an evolving feature, your feedback on the BPMN elements you need is invaluable to us. Please let us know in the comments below which elements are critical to your workflows, so we can prioritize their implementation in future releases. We will gradually add new BPMN elements based on requests from .NET developers who have chosen Workflow Engine as the workflow library for their business applications.&lt;/p&gt;

</description>
      <category>bpmn</category>
      <category>dotnet</category>
      <category>csharp</category>
    </item>
    <item>
      <title>Maximizing Hardware Utilization with Parallelism in Workflow Subprocesses Using Optimajet Workflow Engine</title>
      <dc:creator>Optimajet Limited</dc:creator>
      <pubDate>Wed, 11 Sep 2024 10:31:13 +0000</pubDate>
      <link>https://forem.com/optimajet/maximizing-hardware-utilization-with-parallelism-in-workflow-subprocesses-using-optimajet-workflow-engine-4adb</link>
      <guid>https://forem.com/optimajet/maximizing-hardware-utilization-with-parallelism-in-workflow-subprocesses-using-optimajet-workflow-engine-4adb</guid>
      <description>&lt;h2&gt;
  
  
  Introduction
&lt;/h2&gt;

&lt;p&gt;In today's fast-paced digital landscape, businesses demand agility, scalability, and high performance from their software solutions. Workflow engines play a pivotal role in orchestrating tasks and automating processes, ensuring that everything runs smoothly. But when these processes become more complex and resource-intensive, how can workflow engines scale efficiently and stay responsive? The answer lies in &lt;strong&gt;threads&lt;/strong&gt;. Examples of schemas using &lt;strong&gt;subprocesses&lt;/strong&gt; in different workflows are described in detail in the &lt;a href="https://workflowengine.io/documentation/execution/subprocesses" rel="noopener noreferrer"&gt;official documentation of the Workflow Engine&lt;/a&gt;. &lt;/p&gt;

&lt;p&gt;However, in this article, we will try to explain complex things in simple terms. We'll explore what threads are in the context of the Optimajet Workflow Engine and how they can dramatically enhance efficiency, enabling smoother execution and more responsive workflows.&lt;/p&gt;

&lt;h2&gt;
  
  
  What is Parallelism in Workflow Subprocesses?
&lt;/h2&gt;

&lt;p&gt;In modern software systems, the need to optimize for both performance and resource efficiency has become a critical challenge. One of the most powerful techniques for achieving this is leveraging parallelism within subprocesses when building workflow schemas. By running multiple subprocesses concurrently, you can unlock higher performance and make full use of your hardware’s processing power. Optimizing workflows in this way can dramatically improve system efficiency, especially when dealing with complex workflows that involve multiple independent tasks. Parallelism refers to the ability to execute multiple independent or semi-independent subprocesses simultaneously. &lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fh7wbe7q1ls5zjxmh777j.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fh7wbe7q1ls5zjxmh777j.png" alt="Image description" width="591" height="322"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;In the context of workflow automation with Optimajet Workflow Engine, this means that different stages of a workflow can be run in parallel as Subprocesses, rather than waiting for each one to finish before starting the next. This improves efficiency, reduces execution time, and allows your workflows to handle more tasks concurrently.&lt;/p&gt;

&lt;h2&gt;
  
  
  What Are Threads in a Workflow Engine?
&lt;/h2&gt;

&lt;p&gt;In simple terms, threads are independent sequences of execution within a larger process. In a multi-threaded environment, multiple tasks or operations can run simultaneously, each in its own thread. This allows for parallel processing, where multiple parts of a workflow can be executed at the same time rather than sequentially.&lt;/p&gt;

&lt;p&gt;Within the Optimajet Workflow Engine, threads enable you to break down a workflow into parallel paths of execution. These paths can run independently or concurrently, meaning that tasks that don’t depend on each other can proceed without waiting for others to complete. This parallelism can significantly boost performance and efficiency, especially in complex workflows where multiple independent tasks need to be handled simultaneously.&lt;/p&gt;

&lt;h2&gt;
  
  
  Threads and Their Role in Parallelism
&lt;/h2&gt;

&lt;p&gt;At the core of parallelism is the concept of threads. A thread is a lightweight unit of execution that can run code independently of other threads. In modern multi-core processors, threads allow you to take full advantage of the hardware by distributing work across different cores.&lt;/p&gt;

&lt;p&gt;In the Optimajet Workflow Engine, subprocesses within a workflow can be split into multiple threads. However, unlike some systems that automatically handle thread allocation, Optimajet requires developers to configure thread distribution manually when designing the workflow schema. This gives developers full control over how tasks are distributed across threads, ensuring that workflows are tailored to specific use cases and hardware environments.&lt;/p&gt;

&lt;p&gt;By using threads, developers gain several important benefits for efficiency, performance, and flexibility, which make thread-based parallelism an essential tool for optimizing workflows.&lt;/p&gt;

&lt;h2&gt;
  
  
  Benefits of Using Threads in Workflow Schemes
&lt;/h2&gt;

&lt;h3&gt;
  
  
  1. Parallelism and Efficiency
&lt;/h3&gt;

&lt;p&gt;&lt;strong&gt;Benefit:&lt;/strong&gt; Threads allow for the parallel execution of tasks that can be performed simultaneously, meaning that workflows can handle multiple operations at once.&lt;br&gt;
&lt;strong&gt;Why Use It:&lt;/strong&gt; If you have tasks that don’t depend on each other—like sending notifications while processing data—threads can significantly speed up the workflow by reducing idle or waiting time.&lt;/p&gt;

&lt;h3&gt;
  
  
  2. Better Resource Utilization
&lt;/h3&gt;

&lt;p&gt;&lt;strong&gt;Benefit:&lt;/strong&gt; Threads make better use of system resources, particularly in multi-core processors. Instead of running tasks sequentially on a single CPU core, threads can distribute tasks across multiple cores for more efficient processing.&lt;br&gt;
&lt;strong&gt;Why Use It:&lt;/strong&gt; For workflows handling large datasets, high-volume tasks, or I/O operations (like API calls or database queries), threads maximize throughput by fully utilizing your system’s computing power.&lt;/p&gt;

&lt;h3&gt;
  
  
  3. Concurrency and Responsiveness
&lt;/h3&gt;

&lt;p&gt;&lt;strong&gt;Benefit:&lt;/strong&gt; Threads allow workflows to continue processing while waiting for external events (e.g., user input, network responses). This keeps the workflow responsive instead of stalling.&lt;br&gt;
&lt;strong&gt;Why Use It:&lt;/strong&gt; In complex workflows involving long-running tasks, threads prevent bottlenecks by keeping the rest of the workflow active.&lt;/p&gt;

&lt;h3&gt;
  
  
  4. Asynchronous Processing
&lt;/h3&gt;

&lt;p&gt;&lt;strong&gt;Benefit:&lt;/strong&gt; Threads enable asynchronous execution, meaning tasks can be initiated and the workflow can move forward without waiting for them to complete, revisiting them once results are ready.&lt;br&gt;
&lt;strong&gt;Why Use It:&lt;/strong&gt; This is particularly useful when interacting with external services or databases. Instead of halting the workflow, other operations can proceed, making the entire process more efficient.&lt;/p&gt;

&lt;h3&gt;
  
  
  5. Scalability
&lt;/h3&gt;

&lt;p&gt;&lt;strong&gt;Benefit:&lt;/strong&gt; Threads help workflow engines scale by handling large numbers of simultaneous operations. This ensures that as workflows grow in complexity, they can split the workload across multiple threads and execute them concurrently.&lt;br&gt;
&lt;strong&gt;Why Use It:&lt;/strong&gt; For businesses with growing demands, thread-based parallelism ensures that workflows can handle larger volumes of tasks or users without degrading performance.&lt;/p&gt;

&lt;h3&gt;
  
  
  6. Load Balancing
&lt;/h3&gt;

&lt;p&gt;&lt;strong&gt;Benefit:&lt;/strong&gt; In distributed systems, threads can help balance the load by distributing tasks across multiple systems or servers, preventing any one system from being overloaded.&lt;br&gt;
&lt;strong&gt;Why Use It:&lt;/strong&gt; When scaling workflows to handle multiple users or requests, thread-based processing distributes tasks evenly, avoiding overloads in certain parts of the system.&lt;/p&gt;

&lt;h3&gt;
  
  
  7. Improved User Experience
&lt;/h3&gt;

&lt;p&gt;&lt;strong&gt;Benefit:&lt;/strong&gt; By performing background operations on separate threads, workflows can maintain a smoother, more responsive interface for users.&lt;br&gt;
&lt;strong&gt;Why Use It:&lt;/strong&gt; For workflows that involve user interaction (e.g., form submissions, approvals), threads allow background processing to occur without affecting the front-end experience.&lt;/p&gt;

&lt;h3&gt;
  
  
  8. Concurrency Control
&lt;/h3&gt;

&lt;p&gt;&lt;strong&gt;Benefit:&lt;/strong&gt; Workflow engines utilizing threads provide mechanisms to manage concurrent processes, ensuring that shared resources aren’t corrupted due to conflicting operations.&lt;br&gt;
&lt;strong&gt;Why Use It:&lt;/strong&gt; When multiple threads need to access or modify shared data, thread-based concurrency control ensures safe access, avoiding race conditions and data corruption.&lt;/p&gt;

&lt;h2&gt;
  
  
  How Optimajet Workflow Engine Manages Threads
&lt;/h2&gt;

&lt;p&gt;Unlike some workflow engines that automatically distribute tasks across threads, the Optimajet Workflow Engine requires developers to manually configure thread assignment within the workflow schema for subprocesses.&lt;br&gt;
Here’s how it works:&lt;/p&gt;

&lt;h3&gt;
  
  
  Manual Thread Assignment
&lt;/h3&gt;

&lt;p&gt;In the Optimajet designer, developers define which subprocesses should run in parallel and manually specify how they will be distributed across threads. This allows for more control over the threading model, making it possible to tailor workflows based on specific system requirements and workloads.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Foijrq8mvo7we3772p7pb.jpg" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Foijrq8mvo7we3772p7pb.jpg" alt="Image description" width="800" height="503"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  Task Scheduling by Design
&lt;/h3&gt;

&lt;p&gt;The manual assignment of threads ensures that developers have full control over the scheduling of parallel subprocesses. While this requires some upfront design, it allows for more optimized performance as each task can be carefully scheduled based on the system’s capabilities.&lt;/p&gt;

&lt;h2&gt;
  
  
  Practical Example
&lt;/h2&gt;

&lt;p&gt;Imagine a workflow designed to process a customer order. This workflow may include subprocesses like validating the payment, checking inventory, generating shipping labels, and sending notifications to the customer. In a sequential workflow, each subprocess would run one after the other, increasing the time it takes to complete the order.&lt;/p&gt;

&lt;p&gt;By using &lt;strong&gt;Optimajet’s parallelism&lt;/strong&gt; and manually assigning threads:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Payment validation runs on one thread.&lt;/li&gt;
&lt;li&gt;Simultaneously, inventory checking runs on another thread.&lt;/li&gt;
&lt;li&gt;While these are happening, shipping label generation and notification sending can run on other threads.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;The result is a much faster order processing time, as independent tasks are executed in parallel, fully utilizing the CPU cores. In this scenario, the system is able to handle more orders per minute, improving throughput and customer satisfaction.&lt;/p&gt;

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

&lt;p&gt;Parallelism in workflow subprocesses, combined with manual thread assignment in Optimajet Workflow Engine, unlocks the full potential of your hardware. By distributing tasks across multiple threads, you can maximize CPU utilization, reduce latency, and increase throughput. Optimajet’s support for manual threading ensures that developers have the flexibility to optimize workflows for specific use cases and hardware environments.&lt;/p&gt;

&lt;p&gt;If your workflows are still running sequentially, it’s time to explore the power of parallelism. With Optimajet, you can build faster, more efficient workflows that scale effortlessly with your system’s needs.&lt;/p&gt;

</description>
      <category>parallelism</category>
      <category>dotnet</category>
      <category>workflow</category>
      <category>csharp</category>
    </item>
    <item>
      <title>Understanding Workflow Schemes and Instances in Optimajet Workflow Engine</title>
      <dc:creator>Optimajet Limited</dc:creator>
      <pubDate>Tue, 03 Sep 2024 11:14:24 +0000</pubDate>
      <link>https://forem.com/optimajet/understanding-workflow-schemes-and-instances-in-optimajet-workflow-engine-55lm</link>
      <guid>https://forem.com/optimajet/understanding-workflow-schemes-and-instances-in-optimajet-workflow-engine-55lm</guid>
      <description>&lt;p&gt;Our team conducts daily demonstrations of the &lt;a href="https://demo.workflowengine.io/Designer" rel="noopener noreferrer"&gt;Workflow Engine&lt;/a&gt; and &lt;a href="https://demo.workflowserver.io/?apanel=workflow&amp;amp;aid=InboxDemo" rel="noopener noreferrer"&gt;Workflow Server&lt;/a&gt;. Quite often, through interviews with those who are just beginning to develop their integration architecture, we discover that very simple concepts are not always immediately understood. One such concept is the difference between a workflow scheme and workflow instances. This understanding can be critically important for product licensing, as the Optimajet license allows for the creation of an unlimited number of instances. The limitations of the &lt;a href="https://optimajet.com/products/workflowengine/price/" rel="noopener noreferrer"&gt;free community version&lt;/a&gt; apply only to the capabilities of the scheme itself.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Free limits:&lt;/strong&gt;&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Activity: 15&lt;/li&gt;
&lt;li&gt;Transition: 25&lt;/li&gt;
&lt;li&gt;Command: 5&lt;/li&gt;
&lt;li&gt;Schema: 1&lt;/li&gt;
&lt;li&gt;Thread: 1&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;This means that you can create and manage an unlimited number of instances for relatively simple schemes, effectively meeting basic needs when choosing a workflow engine.&lt;/p&gt;

&lt;h2&gt;
  
  
  Let’s dive deeper into this topic.
&lt;/h2&gt;

&lt;p&gt;In the context of the Optimajet Workflow Engine, a workflow scheme and a workflow instance are two key concepts that are important to understand.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Workflow Scheme&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;A workflow scheme is an abstract description of the sequence of actions, conditions, and transitions between them. Simply put, it is a plan or model of a workflow that defines how work should be carried out. The scheme specifies the steps, possible transitions between them, the conditions that must be met for a transition, as well as various other parameters and settings.&lt;/p&gt;

&lt;p&gt;An example of a workflow scheme might include stages such as:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Request creation&lt;/li&gt;
&lt;li&gt;Request review&lt;/li&gt;
&lt;li&gt;Decision making&lt;/li&gt;
&lt;li&gt;Process completion&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fr69h3fx1s53ihc9ll3zd.jpg" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fr69h3fx1s53ihc9ll3zd.jpg" alt="Image description" width="800" height="421"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;A workflow scheme is a static structure that describes the process without being tied to specific data or instances of the process.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Workflow Instance&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;A workflow instance is a specific execution of a workflow scheme. When a process is launched based on a given scheme, an instance of that process is created. The instance includes the current state of the process, the data that has been passed through the stages, and the history of actions performed.&lt;/p&gt;

&lt;p&gt;If you imagine the scheme as a building blueprint, the instance is the actual building constructed according to that blueprint. Therefore, there may be multiple instances of the same workflow, each corresponding to the same scheme but containing unique data and having its own current state.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Differences&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Workflow Scheme&lt;/strong&gt; – This is the general model that describes how the process should proceed.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Workflow Instance&lt;/strong&gt; – This is the specific execution of the process according to this model, with certain data and the current state.&lt;br&gt;
Thus, the workflow scheme is a concept, while the instance is its practical implementation.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Very important&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Please write in the comments about the challenges you face when choosing a workflow engine in the .NET stack. What is the most critical deal-breaker when deciding which library to use? We will try to create a guide that benefits the entire community and helps you.&lt;/p&gt;

</description>
      <category>dotnet</category>
      <category>csharp</category>
      <category>softwaredevelopment</category>
      <category>beginners</category>
    </item>
    <item>
      <title>BPMN Diagram Import Feature in the .NET Workflow Engine Library by Optimajet</title>
      <dc:creator>Optimajet Limited</dc:creator>
      <pubDate>Tue, 03 Sep 2024 09:52:41 +0000</pubDate>
      <link>https://forem.com/optimajet/bpmn-diagram-import-feature-in-the-net-workflow-engine-library-by-optimajet-254i</link>
      <guid>https://forem.com/optimajet/bpmn-diagram-import-feature-in-the-net-workflow-engine-library-by-optimajet-254i</guid>
      <description>&lt;h2&gt;
  
  
  Introduction
&lt;/h2&gt;

&lt;p&gt;We are excited to announce a new feature that will be available in one of the upcoming releases of Optimajet Workflow Engine — BPMN diagram import. This feature is designed to significantly simplify and accelerate the process of creating and configuring business processes for .NET Developers. What’s even more important, it is a unique offering in the market of on-premise .NET libraries.&lt;/p&gt;

&lt;p&gt;We are starting extensive testing of BPMN diagram import among Optimajet Workflow Engine users. If you need this feature and are willing to provide feedback, &lt;a href="https://optimajet.com/contact-us/" rel="noopener noreferrer"&gt;please contact us&lt;/a&gt;, and we will grant you access.&lt;/p&gt;

&lt;h2&gt;
  
  
  What is BPMN?
&lt;/h2&gt;

&lt;p&gt;BPMN (Business Process Model and Notation) is an international standard for describing and modeling business processes. BPMN provides a visual language that is equally understandable to both business analysts and technical specialists. It is a universal tool for creating clear and comprehensive process documentation.&lt;/p&gt;

&lt;h2&gt;
  
  
  Key Advantages of the BPMN Diagram Import
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Unique Market Offering:&lt;/strong&gt; Optimajet Workflow Engine now offers a unique capability for on-premise .NET solutions — BPMN diagram import for Dot Net developers, it's rare to find a library that offers this functionality, making our product a trailblazer in the field&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Accelerated Process Creation:&lt;/strong&gt; With BPMN diagram import, users can instantly transfer their existing process models into Optimajet Workflow Engine, significantly reducing the time required to set up new workflows.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Support for International Standards:&lt;/strong&gt; The new tool supports the BPMN standard, making your processes compatible with other systems and enabling easy exchange of diagrams across various platforms and teams.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Ease of Use:&lt;/strong&gt; Importing BPMN diagrams is straightforward and involves just a few simple steps. The user uploads the diagram file, and Optimajet Workflow Engine automatically converts it into a workflow that is ready for further configuration and execution.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Handling Complex Processes:&lt;/strong&gt; The new feature allows for easy import and management of processes of any complexity, including parallel flows, loops, and branches, expanding the scope of your automation capabilities.&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;In the image below, you can see an example of a pizza order BPMN diagram. &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%2F6zlyew4jb1ahnagmpk58.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%2F6zlyew4jb1ahnagmpk58.png" alt="Image description" width="800" height="524"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  How Does It Work? Just Three Simple Steps
&lt;/h2&gt;

&lt;p&gt;&lt;strong&gt;1. BPMN File Upload:&lt;/strong&gt; The user selects and uploads a BPMN file (.bpmn) through the Optimajet Workflow Engine interface.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;2. Automatic Conversion BPMN to Workflow Engine Schema:&lt;/strong&gt; Workflow Engine analyzes the structure of the uploaded diagram and automatically converts it into a one or several workflow schemas that can be further configured or executed. &lt;/p&gt;

&lt;p&gt;For example, the import of the pizza order BPMN diagram was transformed into two separate workflows: the Customer Workflow Schema and the Vendor Workflow Schema.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;&lt;em&gt;Customer Workflow Schema&lt;/em&gt;&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%2F3zt81pbtbcuzno9qyoee.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%2F3zt81pbtbcuzno9qyoee.png" alt="Image description" width="800" height="185"&gt;&lt;/a&gt; &lt;/p&gt;

&lt;p&gt;&lt;strong&gt;&lt;em&gt;Vendor Workflow Schema&lt;/em&gt;&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%2Fi7ekjt4byap896b7nber.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%2Fi7ekjt4byap896b7nber.png" alt="Image description" width="800" height="394"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;3. Flexible Configuration:&lt;/strong&gt; After import, users can make any necessary adjustments to the process, adapting it to specific business requirements, and start using it right away.&lt;/p&gt;

&lt;h2&gt;
  
  
  Practical Application
&lt;/h2&gt;

&lt;p&gt;The BPMN diagram import feature will be especially valuable for companies that are already actively using BPMN in their work and want to migrate their processes to the Optimajet Workflow Engine platform with minimal effort. It is also an excellent tool for quickly launching automation when ready-made solutions need to be implemented promptly.&lt;/p&gt;

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

&lt;p&gt;BPMN diagram import is an important enhancement that will be introduced in the upcoming versions of Optimajet Workflow Engine. We are confident that this feature, unique for on-premise .NET libraries, will help our users achieve better results in business process automation, making it faster, simpler, and more efficient.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;If you need this feature and are willing to provide feedback, &lt;a href="https://optimajet.com/contact-us/" rel="noopener noreferrer"&gt;please contact us&lt;/a&gt; Or Stay tuned for updates and be ready for new possibilities in the &lt;a href="https://workflowengine.io/documentation/roadmap" rel="noopener noreferrer"&gt;upcoming release!&lt;/a&gt;&lt;/strong&gt; &lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Very important&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Please write in the comments about the challenges you face when choosing a workflow engine in the .NET stack. What is the most critical deal-breaker when deciding which library to use? We will try to create a guide that benefits the entire community and helps you. &lt;/p&gt;

&lt;h2&gt;
  
  
  Workflow Engine: Release Notes Updates - BPMN Plugin is Ready to use!
&lt;/h2&gt;

&lt;p&gt;&lt;strong&gt;&lt;a href="https://workflowengine.io/documentation/bpmn-differences" rel="noopener noreferrer"&gt;October 24, Workflow Engine: 2024 16.0.0&lt;/a&gt;&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Breaking Changes&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;BPMN import functionality has been released! Be sure to switch to the new BPMN plugin. For more details, please refer to the &lt;a href="https://workflowengine.io/documentation/bpmn-differences" rel="noopener noreferrer"&gt;BPMN documentation.&lt;/a&gt;&lt;/p&gt;

</description>
      <category>bpmn</category>
      <category>dotnet</category>
      <category>tooling</category>
      <category>csharp</category>
    </item>
    <item>
      <title>Become a .NET Workflow Engine Pro: Follow This Step-by-Step Learning Roadmap!</title>
      <dc:creator>Optimajet Limited</dc:creator>
      <pubDate>Thu, 15 Aug 2024 14:52:19 +0000</pubDate>
      <link>https://forem.com/optimajet/become-a-net-workflow-engine-pro-follow-this-step-by-step-learning-roadmap-561d</link>
      <guid>https://forem.com/optimajet/become-a-net-workflow-engine-pro-follow-this-step-by-step-learning-roadmap-561d</guid>
      <description>&lt;p&gt;The Optimajet team supports developers of their products during the Proof of Concept stage. In most cases, when .NET developers tackle their own tasks or their clients' business challenges, they have to start from scratch in understanding the architecture of various .NET engines. Initially, they study the market and need to grasp the capabilities of all products, along with their pros and cons. &lt;/p&gt;

&lt;p&gt;Unfortunately, all products are different, and it is nearly impossible to compare them, because they are structured very differently. However, there are some fundamental principles.&lt;/p&gt;

&lt;p&gt;In this article, we have tried to compile a learning roadmap using our documentation as an example, to make it easier for you to understand the principles of the Optimajet Workflow Engine. This engine is very easy to learn and won't require more than two weeks of your time. After this, you'll be able to understand any engine, professionally compare the solutions available on the market, and make the right choice.&lt;/p&gt;

&lt;p&gt;To reinforce the materials through practice, we recommend installing and run &lt;a href="https://workflowserver.io/documentation/" rel="noopener noreferrer"&gt;WorkflowServer&lt;/a&gt; in a &lt;a href="https://workflowserver.io/documentation/how-to-launch#docker" rel="noopener noreferrer"&gt;Docker&lt;/a&gt; container and creating working schemes to test how everything works in practice.&lt;/p&gt;

&lt;p&gt;Starting from the &lt;strong&gt;Functionality&lt;/strong&gt; stage, a basic understanding of C# and .Net may be required since Optimajet Workflow Engine is a .Net library for developers, and most tasks require extending the engine’s capabilities using C# code.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Basics&lt;/strong&gt; &lt;/p&gt;

&lt;p&gt;Start by reading the articles in the &lt;a href="https://workflowengine.io/documentation/scheme" rel="noopener noreferrer"&gt;Workflow Scheme&lt;/a&gt; section. As a foundation, it's important to understand how the basic building blocks of a scheme work: &lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;a href="https://workflowengine.io/documentation/scheme/activities" rel="noopener noreferrer"&gt;Activities&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://workflowengine.io/documentation/scheme/transitions" rel="noopener noreferrer"&gt;Transitions&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;
&lt;a href="https://workflowengine.io/documentation/scheme/commands" rel="noopener noreferrer"&gt;Commands&lt;/a&gt; &lt;/li&gt;
&lt;li&gt;&lt;a href="https://workflowengine.io/documentation/scheme/parameters" rel="noopener noreferrer"&gt;Parameters&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://workflowengine.io/documentation/scheme/rules" rel="noopener noreferrer"&gt;Actors&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://workflowengine.io/documentation/scheme/timers" rel="noopener noreferrer"&gt;Timers&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;You should have a good understanding of how they are interconnected and what they are used for.&lt;/p&gt;

&lt;p&gt;&lt;iframe width="710" height="399" src="https://www.youtube.com/embed/w_EHopQHTs4"&gt;
&lt;/iframe&gt;
&lt;/p&gt;

&lt;p&gt;At this stage, there's no need to look for real-world applications for the schemes; just practice creating them for different scenarios without focusing on implementation. It’s also important to understand how to create scheme instances—processes—and the &lt;a href="https://workflowengine.io/documentation/execution/regular-process" rel="noopener noreferrer"&gt;lifecycle of these instances&lt;/a&gt;. You don’t need to delve too deeply at the start, simply creating a few processes and experimenting with their states will suffice.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Functionality&lt;/strong&gt; &lt;/p&gt;

&lt;p&gt;At this stage, you'll need to figure out how to turn empty schemes into the workhorses of business, and here, unfortunately, C# .Net knowledge is essential. The Optimajet Workflow Engine is designed for developers. The engine’s functionality is implemented through three main components: &lt;a href="https://workflowengine.io/documentation/scheme/actions" rel="noopener noreferrer"&gt;Actions&lt;/a&gt;, &lt;a href="https://workflowengine.io/documentation/scheme/conditions" rel="noopener noreferrer"&gt;Conditions&lt;/a&gt;, and &lt;a href="https://workflowengine.io/documentation/scheme/rules" rel="noopener noreferrer"&gt;Rules&lt;/a&gt;, which developers see as &lt;strong&gt;IWorkflowActionProvider&lt;/strong&gt; and &lt;strong&gt;IWorkflowRuleProvider&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;Practice implementing these interfaces and create a scheme that performs some useful work—saving data to a database, sending notification emails, or requesting user approval.&lt;/p&gt;

&lt;p&gt;You should also learn how to programmatically trigger transitions using &lt;a href="https://workflowengine.io/documentation/execution/setting-state-activity" rel="noopener noreferrer"&gt;SetState, SetActivity, and Resume&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Complex Schemes&lt;/strong&gt; &lt;/p&gt;

&lt;p&gt;The ability to create “simple” schemes consisting of branches with conditions and action implementations is sufficient for 80% of scenarios. However, for the remaining cases, you’ll need some advanced techniques: &lt;a href="https://workflowengine.io/documentation/execution/subprocesses" rel="noopener noreferrer"&gt;subprocesses and parallel task execution&lt;/a&gt;, &lt;a href="https://workflowengine.io/documentation/execution/scheme-inlining" rel="noopener noreferrer"&gt;embedding one scheme into another&lt;/a&gt;, and &lt;a href="https://workflowengine.io/documentation/plugins/loopsplugin" rel="noopener noreferrer"&gt;creating loops in the scheme&lt;/a&gt; (this feature is implemented via plugins).&lt;/p&gt;

&lt;p&gt;These features allow you to create very advanced schemes. At this stage, it’s important to understand how &lt;a href="https://workflowengine.io/documentation/execution/scheme-update" rel="noopener noreferrer"&gt;scheme migrations&lt;/a&gt; occur when they are changed. Also, explore the important mechanism of &lt;a href="https://workflowengine.io/documentation/execution/pre-execution" rel="noopener noreferrer"&gt;Pre-execution&lt;/a&gt;, which allows you to predict the movement of the scheme without changing its state. By the end of this stage, you should be confident in developing complex business processes using WFE.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Customization&lt;/strong&gt; &lt;/p&gt;

&lt;p&gt;Quite often, users of Optimajet Workflow Engine want to customize the product and extend its functionality. There are two components here: visual and logical. Both can be combined into a &lt;a href="https://workflowengine.io/documentation/plugins" rel="noopener noreferrer"&gt;plugin&lt;/a&gt; and installed as a single package.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Visual customization&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.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%2Femv4wu4evwu8flil6plz.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.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%2Femv4wu4evwu8flil6plz.png" alt="Image description"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://workflowengine.io/documentation/designer-customization/appearance-customization" rel="noopener noreferrer"&gt;Visual customization&lt;/a&gt; is based on the fact that any element of the designer is a template written in Vue.js, which the client can change without access to the source code. There are also some specific features like &lt;a href="https://workflowengine.io/documentation/designer-customization/autocomplete-provider" rel="noopener noreferrer"&gt;autocomplete&lt;/a&gt; or providing &lt;a href="https://workflowengine.io/documentation/designer-customization/parameter-appearance" rel="noopener noreferrer"&gt;forms for parameters&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;The logical part allows you to create your own &lt;a href="https://workflowengine.io/documentation/designer-customization/custom-activity" rel="noopener noreferrer"&gt;custom activities&lt;/a&gt; that perform some specific work. They work thanks to &lt;a href="https://workflowengine.io/documentation/scheme/annotations" rel="noopener noreferrer"&gt;metadata (annotations)&lt;/a&gt; that can be attached to any activity, and a form for editing these annotations is automatically generated, using the parameter form mechanism from the visual part.&lt;/p&gt;

&lt;p&gt;As part of this learning stage, you should study how &lt;a href="https://workflowengine.io/documentation/scheme/localization" rel="noopener noreferrer"&gt;localization&lt;/a&gt; works, which can also be configured in the designer itself. Here, you can learn how to &lt;a href="https://workflowengine.io/documentation/designer-customization/languages" rel="noopener noreferrer"&gt;add languages for localization&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Plugins&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;This stage is not as difficult as the previous one but is quite extensive and requires an understanding of how customization and plugins work. A lot of work has been done, and most of the standard scenarios of logical customization have already been written by Optimajet and included in the package.&lt;/p&gt;

&lt;p&gt;These are various plugins: A &lt;a href="https://workflowengine.io/documentation/plugins/basicplugin" rel="noopener noreferrer"&gt;Basic plugin&lt;/a&gt; one with a set of different tools, an &lt;a href="https://workflowengine.io/documentation/plugins/approvalplugin" rel="noopener noreferrer"&gt;Approval plugin&lt;/a&gt; that implements an inbox system for tracking and notifying actors moving the process state, and an &lt;a href="https://workflowengine.io/documentation/plugins/assignmentplugin" rel="noopener noreferrer"&gt;Assignment plugin&lt;/a&gt; for task assignment. There are also other minor plugins, which you can find on the documentation website and review on your own; they are mostly integrations with various services and technologies.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Advanced Features&lt;/strong&gt; &lt;/p&gt;

&lt;p&gt;This stage of learning covers very large and complex concepts, specific tasks may arise, and it’s important to know how they work. The difference between a &lt;a href="https://workflowengine.io/documentation/scalability/singleserver" rel="noopener noreferrer"&gt;single-server&lt;/a&gt; and &lt;a href="https://workflowengine.io/documentation/scalability/multiserver" rel="noopener noreferrer"&gt;multi-server setup&lt;/a&gt;, understanding the concept of &lt;a href="https://workflowengine.io/documentation/main-terms/runtime" rel="noopener noreferrer"&gt;Runtime&lt;/a&gt;, &lt;a href="https://workflowengine.io/documentation/main-terms/runtime-settings" rel="noopener noreferrer"&gt;Runtime configuration options&lt;/a&gt;, and &lt;a href="https://workflowengine.io/documentation/scalability/restore" rel="noopener noreferrer"&gt;recovery after a failure&lt;/a&gt;. The specifics of &lt;a href="https://workflowengine.io/documentation/main-terms/persistence" rel="noopener noreferrer"&gt;data storage&lt;/a&gt; by the Optimajet provider and the &lt;a href="https://workflowengine.io/documentation/scalability/multitenancy" rel="noopener noreferrer"&gt;configuration of multi-tenancy mode&lt;/a&gt; should also be reviewed. Additionally, familiarize yourself with &lt;a href="https://workflowengine.io/documentation/execution/scheme-generation" rel="noopener noreferrer"&gt;scheme generation&lt;/a&gt; and the process of &lt;a href="https://workflowengine.io/documentation/execution/build-steps" rel="noopener noreferrer"&gt;building a scheme&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Various Useful Features&lt;/strong&gt; &lt;/p&gt;

&lt;p&gt;It’s difficult to categorize these features, but they are worth mentioning as they are not the most complex features and additions, but also guides. They will also be useful for understanding the Optimajet Workflow Engine at an advanced level.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;a href="https://workflowengine.io/documentation/parallel-approval-without-branches" rel="noopener noreferrer"&gt;How to make approvals by multiple users without creating branches in the scheme&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://workflowengine.io/documentation/scheme/process-logs" rel="noopener noreferrer"&gt;How logs work in the designer&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://workflowengine.io/documentation/scheme/working-calendars" rel="noopener noreferrer"&gt;Work calendars&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://workflowengine.io/documentation/sample-error-handling" rel="noopener noreferrer"&gt;Error handling&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://workflowengine.io/documentation/sample-dependency-injection" rel="noopener noreferrer"&gt;Dependency injection&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;We will continue to supplement and update this article based on your questions and feedback, so that the Learning Roadmap becomes the best version of itself. Please be active in the comments and feel free to ask your questions.&lt;/p&gt;

</description>
      <category>csharp</category>
      <category>learning</category>
      <category>dotnet</category>
      <category>docker</category>
    </item>
    <item>
      <title>Formengine Release notes 1.3.0</title>
      <dc:creator>Optimajet Limited</dc:creator>
      <pubDate>Fri, 14 Jun 2024 09:24:29 +0000</pubDate>
      <link>https://forem.com/optimajetlimited/formengine-release-notes130-3hgo</link>
      <guid>https://forem.com/optimajetlimited/formengine-release-notes130-3hgo</guid>
      <description>&lt;ul&gt;
&lt;li&gt;Added the RsSignature component for drawing signatures.&lt;/li&gt;
&lt;li&gt;The text of the form data and errors in the left panel on the designer preview is now scrollable.&lt;/li&gt;
&lt;li&gt;Fixed minor style breakdowns in the designer scrollbars.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;a href="https://formengine.io/documentation/release-notes"&gt;Formengine Release notes &lt;/a&gt;&lt;/p&gt;

</description>
    </item>
    <item>
      <title>Comprehensive Guide: Integrating a Drag-and-Drop Form Builder for Camunda.</title>
      <dc:creator>Optimajet Limited</dc:creator>
      <pubDate>Mon, 10 Jun 2024 09:16:49 +0000</pubDate>
      <link>https://forem.com/optimajet/comprehensive-guide-integrating-a-drag-and-drop-form-builder-for-camunda-284b</link>
      <guid>https://forem.com/optimajet/comprehensive-guide-integrating-a-drag-and-drop-form-builder-for-camunda-284b</guid>
      <description>&lt;h3&gt;
  
  
  Introduction:
&lt;/h3&gt;

&lt;p&gt;Camunda is a Open Source powerful business process management (BPM) solution that provides a flexible and scalable platform for process automation. It supports BPMN for process modeling, CMMN for case management, and DMN for decision modeling.&lt;/p&gt;

&lt;p&gt;Optimajet team receives a large number of questions regarding the integration of the form builder for Camunda. We have written a detailed guide so that all developers can connect [Optimajet Formengine to &lt;a href="https://github.com/camunda" rel="noopener noreferrer"&gt;Camunda&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://formengine.io" rel="noopener noreferrer"&gt;Formengine&lt;/a&gt; is a Drag &amp;amp; Drop Form Builder Library for React. OptimaJet FormBuilder is a lightweight front-end tool that offers an easy and flexible approach to adding drag-and-drop form functionality to your React applications.&lt;/p&gt;

&lt;p&gt;In this guide, we will use an example from the Camunda&lt;br&gt;
repository, &lt;a href="https://github.com/camunda/camunda-bpm-examples/tree/master/usertask/task-form-embedded-react" rel="noopener noreferrer"&gt;Using React Forms with Tasklist&lt;/a&gt;, and modify it so that the forms are displayed using Optimajet FormEngine.&lt;/p&gt;
&lt;h3&gt;
  
  
  Requirements
&lt;/h3&gt;

&lt;p&gt;To follow along, you will need the following:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;&lt;a href="https://www.oracle.com/java/technologies/javase/jdk17-archive-downloads.html" rel="noopener noreferrer"&gt;Java Development Kit (JDK) 17&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://downloads.camunda.cloud/release/camunda-bpm/tomcat/7.21/camunda-bpm-tomcat-7.21.0.zip" rel="noopener noreferrer"&gt;Camunda 7 Community Edition&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://camunda.com/download/modeler/" rel="noopener noreferrer"&gt;Camunda Modeler&lt;/a&gt;&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;Ensure that both Camunda 7 Community Edition and Camunda Modeler are installed on your system if they are not already.&lt;/p&gt;
&lt;h2&gt;
  
  
  Starting with the React Example
&lt;/h2&gt;

&lt;p&gt;The Camunda repository on GitHub provides a simple and&lt;br&gt;
clear &lt;a href="https://github.com/camunda/camunda-bpm-examples/blob/master/usertask/task-form-embedded-react/README.md" rel="noopener noreferrer"&gt;instruction&lt;/a&gt; for using React&lt;br&gt;
in Tasklist. Let's walk through it together.&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;&lt;strong&gt;Add &lt;code&gt;loadReact.js&lt;/code&gt; to Camunda Tasklist:&lt;/strong&gt;&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;Download &lt;a href="https://github.com/camunda/camunda-bpm-examples/blob/master/usertask/task-form-embedded-react/config/react/loadReact.js" rel="noopener noreferrer"&gt;loadReact.js&lt;/a&gt;&lt;br&gt;
   and place it in the &lt;code&gt;app/tasklist/scripts/react&lt;/code&gt; directory of the Camunda Tasklist webapp. For example, if you are using Tomcat, the path&lt;br&gt;
   will be &lt;code&gt;/webapps/camunda/app/tasklist/scripts/react&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;This script will load React and ReactDOM from a CDN and add them to the global scope. If you prefer to use different versions of React,&lt;br&gt;
   adjust the import paths in the script accordingly.&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;&lt;strong&gt;Add the loader as a custom script:&lt;/strong&gt;&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;Modify the &lt;code&gt;app/tasklist/scripts/config.js&lt;/code&gt; file of the Camunda Tasklist webapp to include the loader script. For Tomcat, this file is&lt;br&gt;
   located at &lt;code&gt;/webapps/camunda/app/tasklist/scripts/config.js&lt;/code&gt;. Update the file as shown in&lt;br&gt;
   the &lt;a href="https://github.com/camunda/camunda-bpm-examples/blob/master/usertask/task-form-embedded-react/config/config.js" rel="noopener noreferrer"&gt;example&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;config.js&lt;/strong&gt;&lt;/p&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;

   &lt;span class="nx"&gt;customScripts&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;
     &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;scripts/react/loadReact.js&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;
   &lt;span class="p"&gt;]&lt;/span&gt;


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

&lt;/div&gt;
&lt;p&gt;Launch Camunda if it is not already running. Next, we need to upload the process definition and forms from GitHub, then upload them to&lt;br&gt;
Camunda using Camunda Modeler and start the process. Let's do it step by step:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;&lt;strong&gt;Download the following files:&lt;/strong&gt;&lt;/li&gt;
&lt;/ol&gt;

&lt;ul&gt;
&lt;li&gt;&lt;a href="https://raw.githubusercontent.com/camunda/camunda-bpm-examples/master/usertask/task-form-embedded-react/src/main/resources/react-example.bpmn" rel="noopener noreferrer"&gt;react-example.bpmn&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://raw.githubusercontent.com/camunda/camunda-bpm-examples/master/usertask/task-form-embedded-react/src/main/webapp/start-form.html" rel="noopener noreferrer"&gt;start-form.html&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://raw.githubusercontent.com/camunda/camunda-bpm-examples/master/usertask/task-form-embedded-react/src/main/webapp/task-form.html" rel="noopener noreferrer"&gt;task-form.html&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;ol&gt;
&lt;li&gt;&lt;strong&gt;Open Camunda Modeler and load the &lt;code&gt;react-example.bpmn&lt;/code&gt; file:&lt;/strong&gt;&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;&lt;a href="https://media.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%2F284mny861p0fni6vo3s9.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.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%2F284mny861p0fni6vo3s9.png" alt="Camunda Modeler"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;&lt;strong&gt;Update the form keys:&lt;/strong&gt;&lt;/li&gt;
&lt;/ol&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;Click the "Invoice Received" element and change the Form key from &lt;code&gt;embedded:app:start-form.html&lt;/code&gt;&lt;br&gt;
to &lt;code&gt;embedded:deployment:start-form.html&lt;/code&gt;:&lt;br&gt;
&lt;a href="https://media.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%2Ffhiu8ngocg7vvh296bsk.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.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%2Ffhiu8ngocg7vvh296bsk.png" alt="Camunda Modeler"&gt;&lt;/a&gt;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Click the "Approve Invoice" element and change the Form key from &lt;code&gt;embedded:app:task-form.html&lt;/code&gt; to &lt;code&gt;embedded:deployment:task-form.html&lt;/code&gt;:&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;a href="https://media.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%2F0tgg9vjesre3wnl322l5.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.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%2F0tgg9vjesre3wnl322l5.png" alt="Camunda Modeler"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;&lt;strong&gt;Deploy the process:&lt;/strong&gt;&lt;/li&gt;
&lt;/ol&gt;

&lt;ul&gt;
&lt;li&gt;Click the Rocket button at the bottom of the screen, then click the plus button next to "Include additional files" and add the
previously downloaded &lt;code&gt;start-form.html&lt;/code&gt; and &lt;code&gt;task-form.html&lt;/code&gt; files:&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;a href="https://media.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%2Fc1woccjwji8owbxqi3r7.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.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%2Fc1woccjwji8owbxqi3r7.png" alt="Camunda Modeler"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Click the "Deploy" button. You should see a message indicating that the Process Definition has been successfully deployed:&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;a href="https://media.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%2Fgd4jbq9bwwibujla52p8.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.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%2Fgd4jbq9bwwibujla52p8.png" alt="Camunda Modeler"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;To ensure everything works correctly, follow these steps to test the setup in the Camunda web interface. If Camunda is running locally, the&lt;br&gt;
address will be something like &lt;a href="http://localhost:8080/camunda-welcome/index.html" rel="noopener noreferrer"&gt;http://localhost:8080/camunda-welcome/index.html&lt;/a&gt;:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;&lt;strong&gt;Open the Camunda web interface:&lt;/strong&gt;&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;&lt;a href="https://media.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%2Fbfe0huixkbbru5jb65ma.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.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%2Fbfe0huixkbbru5jb65ma.png" alt="Camunda admin"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;&lt;strong&gt;Access the Tasklist:&lt;/strong&gt;&lt;/li&gt;
&lt;/ol&gt;

&lt;ul&gt;
&lt;li&gt;Click on the Tasklist image.&lt;/li&gt;
&lt;li&gt;Log in using the credentials &lt;strong&gt;demo&lt;/strong&gt;/&lt;strong&gt;demo&lt;/strong&gt;:&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;a href="https://media.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%2Fgh2ooy9m6wblr57mtauf.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.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%2Fgh2ooy9m6wblr57mtauf.png" alt="Camunda login"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;&lt;strong&gt;Start the process:&lt;/strong&gt;&lt;/li&gt;
&lt;/ol&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;Click on the "Start Process" button on the top panel:&lt;br&gt;
&lt;a href="https://media.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%2Fo9hofiy5dmb0io69cj52.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.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%2Fo9hofiy5dmb0io69cj52.png" alt="Camunda Task"&gt;&lt;/a&gt;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Select "React example" in the "Start process" window:&lt;br&gt;
&lt;a href="https://media.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%2Fzwn2giw8ltlaszenu0yl.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.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%2Fzwn2giw8ltlaszenu0yl.png" alt="Camunda"&gt;&lt;/a&gt;&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;ol&gt;
&lt;li&gt;&lt;strong&gt;Fill in the start form:&lt;/strong&gt;&lt;/li&gt;
&lt;/ol&gt;

&lt;ul&gt;
&lt;li&gt;The form for starting the process, uploaded from &lt;code&gt;start-form.html&lt;/code&gt;, should now be displayed.&lt;/li&gt;
&lt;li&gt;Fill in the form with the necessary data and click the "Start" button:&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;a href="https://media.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%2F98cc4btrodylw9mafosc.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.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%2F98cc4btrodylw9mafosc.png" alt="Camunda start form"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;&lt;strong&gt;View the task list:&lt;/strong&gt;&lt;/li&gt;
&lt;/ol&gt;

&lt;ul&gt;
&lt;li&gt;The process has started. Now click on "All Tasks" on the left panel.&lt;/li&gt;
&lt;li&gt;You should see your task in the task list:&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;a href="https://media.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%2Fpwse55kgzumuw6prdczw.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.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%2Fpwse55kgzumuw6prdczw.png" alt="Camunda Tasklist"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;&lt;strong&gt;Claim the task:&lt;/strong&gt;&lt;/li&gt;
&lt;/ol&gt;

&lt;ul&gt;
&lt;li&gt;Click on the task:&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;a href="https://media.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%2F4yfd6u5ppyn71xsjwscz.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.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%2F4yfd6u5ppyn71xsjwscz.png" alt="Camunda Tasklist"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Claim the task by clicking on the "Claim" link, which will change to "Demo Demo":&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;a href="https://media.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%2Fuc7f6l66ddd1aljyfbn4.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.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%2Fuc7f6l66ddd1aljyfbn4.png" alt="Camunda Tasklist"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;&lt;strong&gt;Complete the task:&lt;/strong&gt;&lt;/li&gt;
&lt;/ol&gt;

&lt;ul&gt;
&lt;li&gt;The form you see is uploaded from the &lt;code&gt;task-form.html&lt;/code&gt; file.&lt;/li&gt;
&lt;li&gt;Fill out the form by clicking on the "I approve this Invoice" checkbox, then click the "Complete" button:&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;a href="https://media.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%2Fpf9r6v1sljuzt6zy76ca.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.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%2Fpf9r6v1sljuzt6zy76ca.png" alt="Camunda Tasklist"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;&lt;strong&gt;Verify completion:&lt;/strong&gt;&lt;/li&gt;
&lt;/ol&gt;

&lt;ul&gt;
&lt;li&gt;The task will be completed:&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;a href="https://media.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%2F35kyxn5m564vx7bdrwst.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.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%2F35kyxn5m564vx7bdrwst.png" alt="Image description"&gt;&lt;/a&gt;&lt;/p&gt;
&lt;h2&gt;
  
  
  Creating forms
&lt;/h2&gt;

&lt;p&gt;To connect FormEngine to Camunda, we will use a package that includes a set of components based on React Suite. These components are&lt;br&gt;
utilized in our &lt;a href="https://demo.formengine.io/" rel="noopener noreferrer"&gt;demo&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;First, we need two forms to replace the React forms from the Camunda example. We will omit the process of creating these forms, as it is&lt;br&gt;
straightforward to accomplish. For instance, you can use our &lt;a href="https://demo.formengine.io/" rel="noopener noreferrer"&gt;demo&lt;/a&gt;. Simply drag and drop the necessary&lt;br&gt;
components onto the form and configure their properties as required. Below are the JSON files containing the forms themselves.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;start-form.json&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;
  Click to view start-form.json
  &lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight json"&gt;&lt;code&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;"version"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"1"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"actions"&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;"onChange"&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;"body"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"    const setInvoiceDocument = document =&amp;gt; e.store.formData.state['invoiceDocument'] = document;&lt;/span&gt;&lt;span class="se"&gt;\n\n&lt;/span&gt;&lt;span class="s2"&gt;    const blobFile = e.args[0]?.[0]?.blobFile;&lt;/span&gt;&lt;span class="se"&gt;\n&lt;/span&gt;&lt;span class="s2"&gt;    if (blobFile) {&lt;/span&gt;&lt;span class="se"&gt;\n&lt;/span&gt;&lt;span class="s2"&gt;        const reader = new FileReader();&lt;/span&gt;&lt;span class="se"&gt;\n&lt;/span&gt;&lt;span class="s2"&gt;        reader.readAsDataURL(blobFile);&lt;/span&gt;&lt;span class="se"&gt;\n&lt;/span&gt;&lt;span class="s2"&gt;        reader.onload = () =&amp;gt; {&lt;/span&gt;&lt;span class="se"&gt;\n&lt;/span&gt;&lt;span class="s2"&gt;            setInvoiceDocument(reader.result.replace(/^data:(.*;base64,)?/, ''));&lt;/span&gt;&lt;span class="se"&gt;\n&lt;/span&gt;&lt;span class="s2"&gt;        };&lt;/span&gt;&lt;span class="se"&gt;\n&lt;/span&gt;&lt;span class="s2"&gt;        reader.onerror = () =&amp;gt; {&lt;/span&gt;&lt;span class="se"&gt;\n&lt;/span&gt;&lt;span class="s2"&gt;            setInvoiceDocument(undefined);&lt;/span&gt;&lt;span class="se"&gt;\n&lt;/span&gt;&lt;span class="s2"&gt;        }&lt;/span&gt;&lt;span class="se"&gt;\n&lt;/span&gt;&lt;span class="s2"&gt;    } else {&lt;/span&gt;&lt;span class="se"&gt;\n&lt;/span&gt;&lt;span class="s2"&gt;        setInvoiceDocument(undefined);&lt;/span&gt;&lt;span class="se"&gt;\n&lt;/span&gt;&lt;span class="s2"&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;"params"&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="p"&gt;},&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"form"&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;"key"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"Screen"&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;"Screen"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"props"&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;"children"&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;"key"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"RsContainer 1"&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;"RsContainer"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
        &lt;/span&gt;&lt;span class="nl"&gt;"props"&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;"children"&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;"key"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"RsLabel 1"&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;"RsLabel"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
            &lt;/span&gt;&lt;span class="nl"&gt;"props"&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;"text"&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;"value"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"Invoice Document:"&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="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;"key"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"invoiceDocument"&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;"RsUploader"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
            &lt;/span&gt;&lt;span class="nl"&gt;"props"&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;"autoUpload"&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;"value"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="kc"&gt;false&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;"events"&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;"onChange"&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;"name"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"onChange"&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;"code"&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="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="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;"key"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"creditor"&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;"RsInput"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
        &lt;/span&gt;&lt;span class="nl"&gt;"props"&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;"label"&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;"value"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"Creditor:"&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;"placeholder"&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;"value"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"e.g. &lt;/span&gt;&lt;span class="se"&gt;\"&lt;/span&gt;&lt;span class="s2"&gt;Super Awesome Pizza&lt;/span&gt;&lt;span class="se"&gt;\"&lt;/span&gt;&lt;span class="s2"&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;"value"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"md"&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="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;"key"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"amount"&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;"RsNumberFormat"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
        &lt;/span&gt;&lt;span class="nl"&gt;"props"&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;"label"&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;"value"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"Amount:"&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;"placeholder"&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;"value"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"e.g. &lt;/span&gt;&lt;span class="se"&gt;\"&lt;/span&gt;&lt;span class="s2"&gt;30.00&lt;/span&gt;&lt;span class="se"&gt;\"&lt;/span&gt;&lt;span class="s2"&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;"allowNegative"&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;"value"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="kc"&gt;false&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="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;"key"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"invoiceCategory"&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;"RsDropdown"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
        &lt;/span&gt;&lt;span class="nl"&gt;"props"&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;"label"&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;"value"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"Invoice Category:"&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;"data"&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;"value"&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;"value"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"Travel Expenses"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
                &lt;/span&gt;&lt;span class="nl"&gt;"label"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"Travel Expenses"&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;"value"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"Business Meals"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
                &lt;/span&gt;&lt;span class="nl"&gt;"label"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"Business Meals"&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;"value"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"Other"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
                &lt;/span&gt;&lt;span class="nl"&gt;"label"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"Other"&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="p"&gt;},&lt;/span&gt;&lt;span class="w"&gt;
          &lt;/span&gt;&lt;span class="nl"&gt;"value"&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;"value"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&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="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;"key"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"invoiceNumber"&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;"RsInput"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
        &lt;/span&gt;&lt;span class="nl"&gt;"props"&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;"placeholder"&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;"value"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"e.g. &lt;/span&gt;&lt;span class="se"&gt;\"&lt;/span&gt;&lt;span class="s2"&gt;I-12345&lt;/span&gt;&lt;span class="se"&gt;\"&lt;/span&gt;&lt;span class="s2"&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;"label"&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;"value"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"Invoice Number:"&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="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;"localization"&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;"languages"&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;"code"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"en"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
      &lt;/span&gt;&lt;span class="nl"&gt;"dialect"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"US"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
      &lt;/span&gt;&lt;span class="nl"&gt;"name"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"English"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
      &lt;/span&gt;&lt;span class="nl"&gt;"description"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"American English"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
      &lt;/span&gt;&lt;span class="nl"&gt;"bidi"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"ltr"&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;"defaultLanguage"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"en-US"&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;

&lt;p&gt;You can see the "start-form" in the screenshot below:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.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%2Feyil4g75xsxsvew0yjky.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.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%2Feyil4g75xsxsvew0yjky.png" alt="Optimajet Form Engine"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;The second form is similar to the first.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;task-form.json&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;
  Click to view task-form
  &lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight json"&gt;&lt;code&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;"version"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"1"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"actions"&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;"onChange"&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;"body"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"    const setInvoiceDocument = document =&amp;gt; e.store.formData.state['invoiceDocument'] = document;&lt;/span&gt;&lt;span class="se"&gt;\n\n&lt;/span&gt;&lt;span class="s2"&gt;    const blobFile = e.args[0]?.[0]?.blobFile;&lt;/span&gt;&lt;span class="se"&gt;\n&lt;/span&gt;&lt;span class="s2"&gt;    if (blobFile) {&lt;/span&gt;&lt;span class="se"&gt;\n&lt;/span&gt;&lt;span class="s2"&gt;        const reader = new FileReader();&lt;/span&gt;&lt;span class="se"&gt;\n&lt;/span&gt;&lt;span class="s2"&gt;        reader.readAsDataURL(blobFile);&lt;/span&gt;&lt;span class="se"&gt;\n&lt;/span&gt;&lt;span class="s2"&gt;        reader.onload = () =&amp;gt; {&lt;/span&gt;&lt;span class="se"&gt;\n&lt;/span&gt;&lt;span class="s2"&gt;            setInvoiceDocument(reader.result.replace(/^data:(.*;base64,)?/, ''));&lt;/span&gt;&lt;span class="se"&gt;\n&lt;/span&gt;&lt;span class="s2"&gt;        };&lt;/span&gt;&lt;span class="se"&gt;\n&lt;/span&gt;&lt;span class="s2"&gt;        reader.onerror = () =&amp;gt; {&lt;/span&gt;&lt;span class="se"&gt;\n&lt;/span&gt;&lt;span class="s2"&gt;            setInvoiceDocument(undefined);&lt;/span&gt;&lt;span class="se"&gt;\n&lt;/span&gt;&lt;span class="s2"&gt;        }&lt;/span&gt;&lt;span class="se"&gt;\n&lt;/span&gt;&lt;span class="s2"&gt;    } else {&lt;/span&gt;&lt;span class="se"&gt;\n&lt;/span&gt;&lt;span class="s2"&gt;        setInvoiceDocument(undefined);&lt;/span&gt;&lt;span class="se"&gt;\n&lt;/span&gt;&lt;span class="s2"&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;"params"&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="p"&gt;},&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"form"&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;"key"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"Screen"&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;"Screen"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"props"&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;"children"&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;"key"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"RsContainer 1"&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;"RsContainer"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
        &lt;/span&gt;&lt;span class="nl"&gt;"props"&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;"children"&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;"key"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"RsLabel 1"&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;"RsLabel"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
            &lt;/span&gt;&lt;span class="nl"&gt;"props"&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;"text"&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;"value"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"Invoice Document:"&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="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;"key"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"invoiceDocument"&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;"RsUploader"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
            &lt;/span&gt;&lt;span class="nl"&gt;"props"&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;"autoUpload"&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;"value"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="kc"&gt;false&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;"events"&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;"onChange"&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;"name"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"onChange"&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;"code"&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="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="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;"key"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"creditor"&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;"RsInput"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
        &lt;/span&gt;&lt;span class="nl"&gt;"props"&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;"label"&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;"value"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"Creditor:"&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;"placeholder"&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;"value"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"e.g. &lt;/span&gt;&lt;span class="se"&gt;\"&lt;/span&gt;&lt;span class="s2"&gt;Super Awesome Pizza&lt;/span&gt;&lt;span class="se"&gt;\"&lt;/span&gt;&lt;span class="s2"&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;"value"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"md"&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="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;"key"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"amount"&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;"RsNumberFormat"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
        &lt;/span&gt;&lt;span class="nl"&gt;"props"&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;"label"&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;"value"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"Amount:"&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;"placeholder"&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;"value"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"e.g. &lt;/span&gt;&lt;span class="se"&gt;\"&lt;/span&gt;&lt;span class="s2"&gt;30.00&lt;/span&gt;&lt;span class="se"&gt;\"&lt;/span&gt;&lt;span class="s2"&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;"allowNegative"&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;"value"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="kc"&gt;false&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="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;"key"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"invoiceCategory"&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;"RsDropdown"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
        &lt;/span&gt;&lt;span class="nl"&gt;"props"&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;"label"&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;"value"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"Invoice Category:"&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;"data"&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;"value"&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;"value"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"Travel Expenses"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
                &lt;/span&gt;&lt;span class="nl"&gt;"label"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"Travel Expenses"&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;"value"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"Business Meals"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
                &lt;/span&gt;&lt;span class="nl"&gt;"label"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"Business Meals"&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;"value"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"Other"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
                &lt;/span&gt;&lt;span class="nl"&gt;"label"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"Other"&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="p"&gt;},&lt;/span&gt;&lt;span class="w"&gt;
          &lt;/span&gt;&lt;span class="nl"&gt;"value"&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;"value"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&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="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;"key"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"invoiceNumber"&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;"RsInput"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
        &lt;/span&gt;&lt;span class="nl"&gt;"props"&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;"placeholder"&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;"value"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"e.g. &lt;/span&gt;&lt;span class="se"&gt;\"&lt;/span&gt;&lt;span class="s2"&gt;I-12345&lt;/span&gt;&lt;span class="se"&gt;\"&lt;/span&gt;&lt;span class="s2"&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;"label"&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;"value"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"Invoice Number:"&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="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;"localization"&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;"languages"&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;"code"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"en"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
      &lt;/span&gt;&lt;span class="nl"&gt;"dialect"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"US"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
      &lt;/span&gt;&lt;span class="nl"&gt;"name"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"English"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
      &lt;/span&gt;&lt;span class="nl"&gt;"description"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"American English"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
      &lt;/span&gt;&lt;span class="nl"&gt;"bidi"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"ltr"&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;"defaultLanguage"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"en-US"&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;

&lt;p&gt;This is what the second form looks like:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.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%2Fsx2sc5kw448jfl3bvx84.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.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%2Fsx2sc5kw448jfl3bvx84.png" alt="Optimajet Form Engine"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Connecting FormEngine to Camunda
&lt;/h2&gt;

&lt;p&gt;When connecting FormEngine to Camunda, we decided to use a &lt;a href="https://dev.to/installation#cdn"&gt;bundle&lt;/a&gt; designed for use on any web page. This method does&lt;br&gt;
not require a separate React connection.&lt;/p&gt;

&lt;p&gt;During the connection process, we discovered that Camunda uses a strict Content Security Policy, which prohibits some inline CSS used in the&lt;br&gt;
bundle. Therefore, we will connect the component styles separately.&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;&lt;strong&gt;Add &lt;code&gt;loadFormEngine.js&lt;/code&gt;:&lt;/strong&gt;&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;Place &lt;code&gt;loadFormEngine.js&lt;/code&gt; in &lt;code&gt;app/tasklist/scripts/formEngine&lt;/code&gt; of the Camunda Tasklist webapp (e.g., for Tomcat, it will&lt;br&gt;
   be &lt;code&gt;/webapps/camunda/app/tasklist/scripts/formEngine&lt;/code&gt;).&lt;/p&gt;

&lt;p&gt;loadFormEngine.js&lt;/p&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;

   &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;formEngine&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nb"&gt;document&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;createElement&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;script&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
   &lt;span class="nx"&gt;formEngine&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;crossOrigin&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="kc"&gt;true&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
   &lt;span class="nx"&gt;formEngine&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;src&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;https://unpkg.com/@react-form-builder/viewer-bundle@1.2.0/dist/index.umd.js&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
   &lt;span class="nb"&gt;document&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="nf"&gt;append&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;formEngine&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;


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

&lt;/div&gt;
&lt;ol&gt;
&lt;li&gt;&lt;strong&gt;Add the loader to &lt;code&gt;config.js&lt;/code&gt;:&lt;/strong&gt;&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;Modify &lt;code&gt;app/tasklist/scripts/config.js&lt;/code&gt; of the Camunda Tasklist webapp to include the loader script. For Tomcat, the path will&lt;br&gt;
   be &lt;code&gt;/webapps/camunda/app/tasklist/scripts/config.js&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;config.js&lt;/p&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;

   &lt;span class="nx"&gt;customScripts&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;
     &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;scripts/react/loadReact.js&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
      &lt;span class="c1"&gt;// highlight-next-line&lt;/span&gt;
     &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;scripts/formEngine/loadFormEngine.js&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;
   &lt;span class="p"&gt;]&lt;/span&gt;


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

&lt;/div&gt;
&lt;ol&gt;
&lt;li&gt;&lt;strong&gt;Download and add the CSS files:&lt;/strong&gt;&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;Download the &lt;a href="https://unpkg.com/@react-form-builder/viewer-bundle@1.2.0/dist/rsuite-no-reset.min.css" rel="noopener noreferrer"&gt;rsuite-no-reset.min.css&lt;/a&gt; file and&lt;br&gt;
   the &lt;a href="https://unpkg.com/@react-form-builder/viewer-bundle@1.2.0/dist/formengine-rsuite.css" rel="noopener noreferrer"&gt;formengine-rsuite.css&lt;/a&gt; file. Place them in&lt;br&gt;
   the &lt;code&gt;app/tasklist/styles&lt;/code&gt; folder. To avoid configuring the CSP policy, download the styles locally.&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;strong&gt;Modify &lt;code&gt;user-styles.css&lt;/code&gt;:&lt;/strong&gt;
&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;Add the following highlighted lines to &lt;code&gt;app/tasklist/styles/user-styles.css&lt;/code&gt;:&lt;/p&gt;

&lt;p&gt;user-styles.css&lt;/p&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight css"&gt;&lt;code&gt;

   &lt;span class="c"&gt;/*
   .navbar-brand {
     text-indent: -999em;
     background-image: url(./path/to/the/logo.png);
     width: 80px;
   }

   [cam-widget-header] {
     border-bottom-color: blue;
   }
   */&lt;/span&gt;

   &lt;span class="k"&gt;@import&lt;/span&gt; &lt;span class="sx"&gt;url('./rsuite-no-reset.min.css')&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
   &lt;span class="k"&gt;@import&lt;/span&gt; &lt;span class="sx"&gt;url('./formengine-rsuite.css')&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

   &lt;span class="nc"&gt;.rs-picker-select-menu.rs-picker-popup&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
     &lt;span class="nl"&gt;z-index&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="m"&gt;2000&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;h2&gt;
  
  
  Modifying Forms
&lt;/h2&gt;

&lt;p&gt;In the code of both forms, we will use a simple &lt;code&gt;renderFormEngineForm&lt;/code&gt; function that will render the form into an HTML element.&lt;/p&gt;

&lt;p&gt;The function accepts the following parameters:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;code&gt;form&lt;/code&gt; is the JSON of the form.&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;container&lt;/code&gt; is the HTML element where the form will be rendered.&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;additionalProps&lt;/code&gt; are the additional &lt;a href="///api-reference/interfaces/react_form_builder_core.FormViewerProps"&gt;properties&lt;/a&gt; of
the &lt;a href="https://dev.to/api-reference/modules/react_form_builder_core#formviewer"&gt;FormViewer&lt;/a&gt; component.&lt;/li&gt;
&lt;/ol&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;

&lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nf"&gt;renderFormEngineForm&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;form&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;container&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;additionalProps&lt;/span&gt;&lt;span class="p"&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;viewerRef&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="na"&gt;current&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kc"&gt;null&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;viewerBundle&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nb"&gt;window&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;FormEngineViewerBundle&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;components&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;viewerBundle&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;rSuiteComponents&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;view&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;components&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;view&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;withViewerWrapper&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;components&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;RsLocalizationWrapper&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;props&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="na"&gt;getForm&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="nx"&gt;form&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="nx"&gt;view&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="nx"&gt;viewerRef&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="p"&gt;...&lt;/span&gt;&lt;span class="nx"&gt;additionalProps&lt;/span&gt;
  &lt;span class="p"&gt;};&lt;/span&gt;
  &lt;span class="nx"&gt;viewerBundle&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;renderFormViewerTo&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;container&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;props&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;viewerRef&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;Each form's code will have its own &lt;code&gt;renderCamundaForm&lt;/code&gt; function that will link the FormEngine form and the Camunda form, which is stored in&lt;br&gt;
the &lt;code&gt;camForm&lt;/code&gt; object. In general, the form code is similar to the forms from the React example. See the form code below for reference.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;start-form.html&lt;/strong&gt;&lt;br&gt;

  Click to view start-form
  &lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight html"&gt;&lt;code&gt;

&lt;span class="nt"&gt;&amp;lt;script&amp;gt;&lt;/span&gt;
  &lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nf"&gt;renderFormEngineForm&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;form&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;container&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;additionalProps&lt;/span&gt;&lt;span class="p"&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;viewerRef&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="na"&gt;current&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kc"&gt;null&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;viewerBundle&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nb"&gt;window&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;FormEngineViewerBundle&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;components&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;viewerBundle&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;rSuiteComponents&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;view&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;components&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;view&lt;/span&gt;
      &lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;withViewerWrapper&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;components&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;RsLocalizationWrapper&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;props&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
      &lt;span class="na"&gt;getForm&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="nx"&gt;form&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
      &lt;span class="nx"&gt;view&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
      &lt;span class="nx"&gt;viewerRef&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
      &lt;span class="p"&gt;...&lt;/span&gt;&lt;span class="nx"&gt;additionalProps&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;
    &lt;span class="nx"&gt;viewerBundle&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;renderFormViewerTo&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;container&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;props&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;viewerRef&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;

  &lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nf"&gt;onSubmit&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;camForm&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;formRef&lt;/span&gt;&lt;span class="p"&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;formData&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;formRef&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;current&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="nx"&gt;data&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="c1"&gt;// the file data was saved via a user action to a user state&lt;/span&gt;
    &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;userState&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;formRef&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;current&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="nx"&gt;state&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

    &lt;span class="nx"&gt;camForm&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;variableManager&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;createVariable&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt;
        &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;name&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="s1"&gt;invoiceDocument&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="s1"&gt;type&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;File&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="s1"&gt;value&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;userState&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;invoiceDocument&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;valueInfo&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="na"&gt;filename&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;invoice.pdf&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;},&lt;/span&gt;
        &lt;span class="na"&gt;isDirty&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kc"&gt;true&lt;/span&gt;
      &lt;span class="p"&gt;}&lt;/span&gt;
    &lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="nx"&gt;camForm&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;variableManager&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;createVariable&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt;
        &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;name&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="s1"&gt;creditor&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="s1"&gt;type&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;String&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="s1"&gt;value&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="nx"&gt;creditor&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="na"&gt;isDirty&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kc"&gt;true&lt;/span&gt;
      &lt;span class="p"&gt;}&lt;/span&gt;
    &lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="nx"&gt;camForm&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;variableManager&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;createVariable&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt;
        &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;name&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="s1"&gt;amount&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="s1"&gt;type&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;Double&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="s1"&gt;value&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="nx"&gt;amount&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="na"&gt;isDirty&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kc"&gt;true&lt;/span&gt;
      &lt;span class="p"&gt;}&lt;/span&gt;
    &lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="nx"&gt;camForm&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;variableManager&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;createVariable&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt;
        &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;name&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="s1"&gt;category&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="s1"&gt;type&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;String&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="s1"&gt;value&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="nx"&gt;invoiceCategory&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="na"&gt;isDirty&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kc"&gt;true&lt;/span&gt;
      &lt;span class="p"&gt;}&lt;/span&gt;
    &lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="nx"&gt;camForm&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;variableManager&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;createVariable&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt;
        &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;name&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="s1"&gt;invoiceID&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="s1"&gt;type&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;String&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="s1"&gt;value&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="nx"&gt;invoiceNumber&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="na"&gt;isDirty&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kc"&gt;true&lt;/span&gt;
      &lt;span class="p"&gt;}&lt;/span&gt;
    &lt;span class="p"&gt;);&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;

  &lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nf"&gt;renderCamundaForm&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;elementId&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;camForm&lt;/span&gt;&lt;span class="p"&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;form&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s2"&gt;`
{
  "version": "1",
  "actions": {
    "onChange": {
      "body": "    const setInvoiceDocument = document =&amp;gt; e.store.formData.state['invoiceDocument'] = document;&lt;/span&gt;&lt;span class="se"&gt;\\&lt;/span&gt;&lt;span class="s2"&gt;n&lt;/span&gt;&lt;span class="se"&gt;\\&lt;/span&gt;&lt;span class="s2"&gt;n    const blobFile = e.args[0]?.[0]?.blobFile;&lt;/span&gt;&lt;span class="se"&gt;\\&lt;/span&gt;&lt;span class="s2"&gt;n    if (blobFile) {&lt;/span&gt;&lt;span class="se"&gt;\\&lt;/span&gt;&lt;span class="s2"&gt;n        const reader = new FileReader();&lt;/span&gt;&lt;span class="se"&gt;\\&lt;/span&gt;&lt;span class="s2"&gt;n        reader.readAsDataURL(blobFile);&lt;/span&gt;&lt;span class="se"&gt;\\&lt;/span&gt;&lt;span class="s2"&gt;n        reader.onload = () =&amp;gt; {&lt;/span&gt;&lt;span class="se"&gt;\\&lt;/span&gt;&lt;span class="s2"&gt;n            setInvoiceDocument(reader.result.replace(/^data:(.*;base64,)?/, ''));&lt;/span&gt;&lt;span class="se"&gt;\\&lt;/span&gt;&lt;span class="s2"&gt;n        };&lt;/span&gt;&lt;span class="se"&gt;\\&lt;/span&gt;&lt;span class="s2"&gt;n        reader.onerror = () =&amp;gt; {&lt;/span&gt;&lt;span class="se"&gt;\\&lt;/span&gt;&lt;span class="s2"&gt;n            setInvoiceDocument(undefined);&lt;/span&gt;&lt;span class="se"&gt;\\&lt;/span&gt;&lt;span class="s2"&gt;n        }&lt;/span&gt;&lt;span class="se"&gt;\\&lt;/span&gt;&lt;span class="s2"&gt;n    } else {&lt;/span&gt;&lt;span class="se"&gt;\\&lt;/span&gt;&lt;span class="s2"&gt;n        setInvoiceDocument(undefined);&lt;/span&gt;&lt;span class="se"&gt;\\&lt;/span&gt;&lt;span class="s2"&gt;n    }",
      "params": {}
    }
  },
  "form": {
    "key": "Screen",
    "type": "Screen",
    "props": {},
    "children": [
      {
        "key": "RsContainer 1",
        "type": "RsContainer",
        "props": {},
        "children": [
          {
            "key": "RsLabel 1",
            "type": "RsLabel",
            "props": {
              "text": {
                "value": "Invoice Document:"
              }
            }
          },
          {
            "key": "invoiceDocument",
            "type": "RsUploader",
            "props": {
              "autoUpload": {
                "value": false
              }
            },
            "events": {
              "onChange": [
                {
                  "name": "onChange",
                  "type": "code"
                }
              ]
            }
          }
        ]
      },
      {
        "key": "creditor",
        "type": "RsInput",
        "props": {
          "label": {
            "value": "Creditor:"
          },
          "placeholder": {
            "value": "e.g. &lt;/span&gt;&lt;span class="se"&gt;\\&lt;/span&gt;&lt;span class="s2"&gt;"Super Awesome Pizza&lt;/span&gt;&lt;span class="se"&gt;\\&lt;/span&gt;&lt;span class="s2"&gt;""
          },
          "size": {
            "value": "md"
          }
        }
      },
      {
        "key": "amount",
        "type": "RsNumberFormat",
        "props": {
          "label": {
            "value": "Amount:"
          },
          "placeholder": {
            "value": "e.g. &lt;/span&gt;&lt;span class="se"&gt;\\&lt;/span&gt;&lt;span class="s2"&gt;"30.00&lt;/span&gt;&lt;span class="se"&gt;\\&lt;/span&gt;&lt;span class="s2"&gt;""
          },
          "allowNegative": {
            "value": false
          }
        }
      },
      {
        "key": "invoiceCategory",
        "type": "RsDropdown",
        "props": {
          "label": {
            "value": "Invoice Category:"
          },
          "data": {
            "value": [
              {
                "value": "Travel Expenses",
                "label": "Travel Expenses"
              },
              {
                "value": "Business Meals",
                "label": "Business Meals"
              },
              {
                "value": "Other",
                "label": "Other"
              }
            ]
          },
          "value": {
            "value": ""
          }
        }
      },
      {
        "key": "invoiceNumber",
        "type": "RsInput",
        "props": {
          "placeholder": {
            "value": "e.g. &lt;/span&gt;&lt;span class="se"&gt;\\&lt;/span&gt;&lt;span class="s2"&gt;"I-12345&lt;/span&gt;&lt;span class="se"&gt;\\&lt;/span&gt;&lt;span class="s2"&gt;""
          },
          "label": {
            "value": "Invoice Number:"
          }
        }
      }
    ]
  },
  "localization": {},
  "languages": [
    {
      "code": "en",
      "dialect": "US",
      "name": "English",
      "description": "American English",
      "bidi": "ltr"
    }
  ],
  "defaultLanguage": "en-US"
}`&lt;/span&gt;

    &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;viewerContainer&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nb"&gt;document&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;getElementById&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;elementId&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;formRef&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;renderFormEngineForm&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;form&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;viewerContainer&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

    &lt;span class="nx"&gt;camForm&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;on&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;submit&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
      &lt;span class="nf"&gt;onSubmit&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;camForm&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;formRef&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="p"&gt;});&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="nt"&gt;&amp;lt;/script&amp;gt;&lt;/span&gt;

&lt;span class="nt"&gt;&amp;lt;form&lt;/span&gt; &lt;span class="na"&gt;class=&lt;/span&gt;&lt;span class="s"&gt;'form-horizontal'&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
  &lt;span class="nt"&gt;&amp;lt;div&lt;/span&gt; &lt;span class="na"&gt;id=&lt;/span&gt;&lt;span class="s"&gt;"formViewerContainer"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&amp;lt;/div&amp;gt;&lt;/span&gt;

  &lt;span class="nt"&gt;&amp;lt;script &lt;/span&gt;&lt;span class="na"&gt;cam-script&lt;/span&gt; &lt;span class="na"&gt;type=&lt;/span&gt;&lt;span class="s"&gt;'text/form-script'&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
    &lt;span class="nf"&gt;renderCamundaForm&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;formViewerContainer&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;camForm&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
  &lt;span class="nt"&gt;&amp;lt;/script&amp;gt;&lt;/span&gt;
&lt;span class="nt"&gt;&amp;lt;/form&amp;gt;&lt;/span&gt;


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

&lt;/div&gt;


&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;task-form.html&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;
  Click to view task-form
  &lt;p&gt;title="task-form.html" {2,18,20,51,150-168,173,194}&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;script&amp;gt;&lt;/span&gt;
  &lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nf"&gt;renderFormEngineForm&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;form&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;container&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;additionalProps&lt;/span&gt;&lt;span class="p"&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;viewerRef&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="na"&gt;current&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kc"&gt;null&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;viewerBundle&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nb"&gt;window&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;FormEngineViewerBundle&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;components&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;viewerBundle&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;rSuiteComponents&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;view&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;components&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;view&lt;/span&gt;
      &lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;withViewerWrapper&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;components&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;RsLocalizationWrapper&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;props&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
      &lt;span class="na"&gt;getForm&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="nx"&gt;form&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
      &lt;span class="nx"&gt;view&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
      &lt;span class="nx"&gt;viewerRef&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
      &lt;span class="p"&gt;...&lt;/span&gt;&lt;span class="nx"&gt;additionalProps&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;
    &lt;span class="nx"&gt;viewerBundle&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;renderFormViewerTo&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;container&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;props&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;viewerRef&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;

  &lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nf"&gt;renderCamundaForm&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;elementId&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;camForm&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;scope&lt;/span&gt;&lt;span class="p"&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;camVars&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;camForm&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;variableManager&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;variables&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;invoiceUrl&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;camVars&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;invoiceDocument&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;contentUrl&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;form&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s2"&gt;`{
  "version": "1",
  "form": {
    "key": "Screen",
    "type": "Screen",
    "props": {},
    "children": [
      {
        "key": "RsContainer 1",
        "type": "RsContainer",
        "props": {},
        "children": [
          {
            "key": "RsLabel 1",
            "type": "RsLabel",
            "props": {
              "text": {
                "value": "Download Invoice:"
              }
            }
          },
          {
            "key": "invoiceDocument",
            "type": "RsLink",
            "props": {
              "text": {
                "value": "invoice.pdf"
              },
              "href": {
                "value": "&lt;/span&gt;&lt;span class="p"&gt;${&lt;/span&gt;&lt;span class="nx"&gt;invoiceUrl&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;"
              }
            }
          }
        ]
      },
      {
        "key": "amount",
        "type": "RsNumberFormat",
        "props": {
          "label": {
            "value": "Amount:"
          },
          "placeholder": {
            "value": ""
          },
          "allowNegative": {
            "value": false
          },
          "readOnly": {
            "value": false
          },
          "disabled": {
            "value": true
          }
        }
      },
      {
        "key": "creditor",
        "type": "RsInput",
        "props": {
          "label": {
            "value": "Creditor:"
          },
          "placeholder": {
            "value": ""
          },
          "size": {
            "value": "md"
          },
          "disabled": {
            "value": true
          }
        }
      },
      {
        "key": "category",
        "type": "RsInput",
        "props": {
          "label": {
            "value": "Invoice Category:"
          },
          "disabled": {
            "value": true
          }
        }
      },
      {
        "key": "invoiceID",
        "type": "RsInput",
        "props": {
          "placeholder": {
            "value": ""
          },
          "label": {
            "value": "Invoice Number:"
          },
          "disabled": {
            "value": true
          }
        }
      },
      {
        "key": "approve",
        "type": "RsCheckbox",
        "props": {
          "children": {
            "value": "I approve this Invoice"
          },
          "checked": {
            "value": false
          }
        }
      }
    ]
  },
  "localization": {},
  "languages": [
    {
      "code": "en",
      "dialect": "US",
      "name": "English",
      "description": "American English",
      "bidi": "ltr"
    }
  ],
  "defaultLanguage": "en-US"
}`&lt;/span&gt;

    &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;additionalProps&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
      &lt;span class="na"&gt;initialData&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="na"&gt;amount&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;camVars&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;amount&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;value&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="na"&gt;creditor&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;camVars&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;creditor&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;value&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="na"&gt;invoiceID&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;camVars&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;invoiceID&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;value&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="na"&gt;approved&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;camVars&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;approved&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;value&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="na"&gt;category&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;camVars&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;category&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;value&lt;/span&gt;
      &lt;span class="p"&gt;},&lt;/span&gt;
      &lt;span class="na"&gt;onFormDataChange&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;({&lt;/span&gt;&lt;span class="nx"&gt;data&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;errors&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;camForm&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;variableManager&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;variableValue&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;approved&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;data&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;approve&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;data&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;approve&lt;/span&gt; &lt;span class="o"&gt;!==&lt;/span&gt; &lt;span class="nx"&gt;camVars&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;approved&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;value&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
          &lt;span class="c1"&gt;// Activate 'save' button&lt;/span&gt;
          &lt;span class="nx"&gt;scope&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;$$camForm&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;$dirty&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="kc"&gt;true&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
        &lt;span class="p"&gt;}&lt;/span&gt;
      &lt;span class="p"&gt;}&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;

    &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;viewerContainer&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nb"&gt;document&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;getElementById&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;elementId&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="nf"&gt;renderFormEngineForm&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;form&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;viewerContainer&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;additionalProps&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="nt"&gt;&amp;lt;/script&amp;gt;&lt;/span&gt;

&lt;span class="nt"&gt;&amp;lt;form&lt;/span&gt; &lt;span class="na"&gt;class=&lt;/span&gt;&lt;span class="s"&gt;'form-horizontal'&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
  &lt;span class="nt"&gt;&amp;lt;div&lt;/span&gt; &lt;span class="na"&gt;id=&lt;/span&gt;&lt;span class="s"&gt;'formViewerContainer'&lt;/span&gt;&lt;span class="nt"&gt;/&amp;gt;&lt;/span&gt;

  &lt;span class="nt"&gt;&amp;lt;script &lt;/span&gt;&lt;span class="na"&gt;cam-script&lt;/span&gt; &lt;span class="na"&gt;type=&lt;/span&gt;&lt;span class="s"&gt;'text/form-script'&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;

    &lt;span class="c1"&gt;// Fetch Variables and create new ones&lt;/span&gt;
    &lt;span class="nx"&gt;camForm&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;on&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;form-loaded&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nf"&gt;function &lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
      &lt;span class="nx"&gt;camForm&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;variableManager&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;createVariable&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt;
        &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;name&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="s1"&gt;approved&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="s1"&gt;type&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;Boolean&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="s1"&gt;value&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kc"&gt;false&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="na"&gt;isDirty&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="nx"&gt;camForm&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;variableManager&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;fetchVariable&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;amount&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
      &lt;span class="nx"&gt;camForm&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;variableManager&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;fetchVariable&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;creditor&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
      &lt;span class="nx"&gt;camForm&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;variableManager&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;fetchVariable&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;invoiceID&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
      &lt;span class="nx"&gt;camForm&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;variableManager&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;fetchVariable&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;invoiceDocument&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
      &lt;span class="nx"&gt;camForm&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;variableManager&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;fetchVariable&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;category&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;camForm&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;on&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;variables-applied&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nf"&gt;function &lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
      &lt;span class="nf"&gt;renderCamundaForm&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;formViewerContainer&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;camForm&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;$scope&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="p"&gt;});&lt;/span&gt;
  &lt;span class="nt"&gt;&amp;lt;/script&amp;gt;&lt;/span&gt;
&lt;span class="nt"&gt;&amp;lt;/form&amp;gt;&lt;/span&gt;


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

&lt;/div&gt;


&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;The JSON for the form and the basic code for rendering the form are included in HTML files for this example. In practice, it's likely&lt;br&gt;
better to use a separate JavaScript module.&lt;/strong&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Running FormEngine Forms in Camunda
&lt;/h2&gt;

&lt;ol&gt;
&lt;li&gt;&lt;strong&gt;Deploy the FormEngine Forms:&lt;/strong&gt;&lt;/li&gt;
&lt;/ol&gt;

&lt;ul&gt;
&lt;li&gt;Open Camunda Modeler and click the rocket icon button.&lt;/li&gt;
&lt;li&gt;Delete the selected forms &lt;code&gt;start-form.html&lt;/code&gt; and &lt;code&gt;task-form.html&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;Add the forms created for FormEngine.&lt;/li&gt;
&lt;li&gt;Click the Deploy button.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;a href="https://media.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%2Ffm93yogju28unuccdchj.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.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%2Ffm93yogju28unuccdchj.png" alt="Camunda Modeler"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;&lt;strong&gt;Open the Camunda Tasklist Web Interface:&lt;/strong&gt;&lt;/li&gt;
&lt;/ol&gt;

&lt;ul&gt;
&lt;li&gt;Navigate to &lt;a href="http://localhost:8080/camunda/app/tasklist/" rel="noopener noreferrer"&gt;http://localhost:8080/camunda/app/tasklist/&lt;/a&gt; and refresh the page.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;a href="https://media.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%2Fkws9kro60x8d1yjbz1im.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.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%2Fkws9kro60x8d1yjbz1im.png" alt="Camunda Tasklist"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;&lt;strong&gt;Start the Process:&lt;/strong&gt;&lt;/li&gt;
&lt;/ol&gt;

&lt;ul&gt;
&lt;li&gt;Click on the “Start Process” button on the top panel.&lt;/li&gt;
&lt;li&gt;Select "React example" in the "Start process" window. You should see the form made with FormEngine.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;a href="https://media.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%2F7y0bu06yl8h7wx9wk5gz.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.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%2F7y0bu06yl8h7wx9wk5gz.png" alt="Camunda Tasklist"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;&lt;strong&gt;Fill Out the Form and Start the Process:&lt;/strong&gt;&lt;/li&gt;
&lt;/ol&gt;

&lt;ul&gt;
&lt;li&gt;Fill out the form and click the Start button.&lt;/li&gt;
&lt;li&gt;The process has started. Now click on "All Tasks" on the left panel.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;a href="https://media.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%2F3goomzjf49v6ce2qfdav.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.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%2F3goomzjf49v6ce2qfdav.png" alt="Camunda Tasklist"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;&lt;strong&gt;Select and Claim the Task:&lt;/strong&gt;&lt;/li&gt;
&lt;/ol&gt;

&lt;ul&gt;
&lt;li&gt;Select the created task from the top.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;a href="https://media.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%2F2ffwtunim5mkuz5rva5b.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.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%2F2ffwtunim5mkuz5rva5b.png" alt="Camunda Tasklist"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Claim the task by clicking on the "Claim" link. The link text will change to "Demo Demo".&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;a href="https://media.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%2F1gh6jsaud0vdmjhbq9r5.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.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%2F1gh6jsaud0vdmjhbq9r5.png" alt="Camunda Tasklist"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;&lt;strong&gt;Verify Task Variables and Fill Out the Form:&lt;/strong&gt;&lt;/li&gt;
&lt;/ol&gt;

&lt;ul&gt;
&lt;li&gt;You should see that the variables have been populated. Click on the link next to the highlighted text "React Example".&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;a href="https://media.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%2F1dufqngl97otfv6z70hb.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.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%2F1dufqngl97otfv6z70hb.png" alt="Camunda Tasklist"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;The form should be correctly filled out.
&lt;img src="https://media.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%2Fiu7k7rn2a0eu8hayazb2.png" alt="Camunda Tasklist"&gt;
&lt;/li&gt;
&lt;li&gt;Fill out the form and click Complete.
&lt;img src="https://media.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%2Fidoatt7hku21vn4i6s2v.png" alt="Camunda Tasklist"&gt;
&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;That's it! Your FormEngine forms are now running in Camunda.&lt;/p&gt;

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

&lt;p&gt;In this article, we have successfully connected FormEngine as a form rendering engine for Camunda. This allows you to use your custom&lt;br&gt;
components to render forms by passing a set of your components through properties.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Your feedback is very important to us&lt;/strong&gt;&lt;br&gt;
It helps us understand whether this guide was useful to you, how clearly it was written, and what else you would like to learn about. Please ask your questions in the comments or start discussions on &lt;a href="https://github.com/optimajet/formengine/discussions" rel="noopener noreferrer"&gt;GitHub&lt;/a&gt;.&lt;/p&gt;

</description>
      <category>camunda</category>
      <category>opensource</category>
      <category>react</category>
      <category>frontend</category>
    </item>
    <item>
      <title>Optimajet Data Engine 1.0.0: Open Source Workflow Engine Component alpha release</title>
      <dc:creator>Optimajet Limited</dc:creator>
      <pubDate>Tue, 28 May 2024 15:48:11 +0000</pubDate>
      <link>https://forem.com/optimajetlimited/optimajet-data-engine-100-open-source-workflow-engine-component-4o10</link>
      <guid>https://forem.com/optimajetlimited/optimajet-data-engine-100-open-source-workflow-engine-component-4o10</guid>
      <description>&lt;p&gt;Optimajet Data Engine 1.0.0: Open Source Workflow Engine Component is a .NET ORM framework developed for implementing providers in the Workflow Engine. This project is currently in the alpha release stage.&lt;/p&gt;

&lt;p&gt;The primary goal of DataEngine is to generate queries to various databases through a unified interface and automatically map this data to entities.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Contains Breaking Changes&lt;/strong&gt;&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Reworked the process of passing settings to providers' implementations. &lt;/li&gt;
&lt;li&gt;Added the method IProvider.UseOptions to create a local context with settings.&lt;/li&gt;
&lt;li&gt;Added the ability to specify the database schema. Note that this is not supported by all databases.&lt;/li&gt;
&lt;li&gt;Introduced splitting large queries in InsertAll and SelectByKeys into subqueries to avoid parameter overflow errors.&lt;/li&gt;
&lt;li&gt;Reworked the addition of TypeHandlers in SQL providers. This mechanism is now more reliable and understandable, and it also supports detecting vanilla Dapper in the project.&lt;/li&gt;
&lt;li&gt;Updated SqlKata to version 1.0.0.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;GitHub &lt;a href="https://github.com/optimajet/DataEngine.NET"&gt;Open Source code &lt;/a&gt;&lt;/p&gt;

</description>
      <category>dotnet</category>
      <category>opensource</category>
      <category>workflow</category>
      <category>workflowengine</category>
    </item>
  </channel>
</rss>
