<h1 id="mb_pseudoform">MB_PseudoForm</h1>
<p>Mb_PseudoForm allows you to organize <code>input</code>, <code>select</code> and <code>textarea</code> elements in a container (typically a DIV element) and to send data entered by the user to a server using an &quot;Ajax Request&quot;.</p>
<p>Mb_PseudForm can be useful:</p>
<ul>
<li>in all situations when you want to send the user&#39;s input to the server without unloading the page.</li>
<li>in particular if you want to create entry modules in a WebForm ASP.NET application without using the Asp form (see the example in the demo folder)</li>
</ul>
<p><code>Mb_PseudForm</code> sends data in the form as a list of objects. This allows you to build generic handlers server side, independent of the structure of the input module to elaborate. </p>
<p>The attached demo is a WebForm ASP.NET application where an API Controller transforms any group of data entered by the user into a formatted email that is sent to the site staff.</p>
<h2 id="getting-started">Getting started</h2>
<p><code>MB_PseudoForm</code> can be loaded directly from CDN,</p>
<pre><code>&lt;script src=&quot;https://cdn.jsdelivr.net/npm/@magicbruno/mb_pseudoform@1.0.0/dist/MB_PseudoForm.min.js&quot;&gt;&lt;/script&gt;
</code></pre>
<p>installed via NPM,</p>
<pre><code>npm install @magicbruno/mb_pseudoform@1.0.0
</code></pre>
<p>or you can clone the GitHub repository: </p>
<pre><code>git clone https://github.com/magicbruno/MB_PseudoForm.git
</code></pre>
<h2 id="how-does-it-work">How does it work</h2>
<p>A pseudo form is an HTML element (for example a <code>div</code> element) that contains <code>input</code>, <code>select</code> and <code>textarea</code> elements and at least one clickable element (<code>&lt;Button&gt;</code> or <code>&lt;a&gt;</code>) which will submit the data.</p>
<p>Minimum conditions because an HTML element becomes a pseudo form are:</p>
<ul>
<li>that the handler intended to receive data server-side is defined using the <code>data-mb-action</code> attribute to be applied to the element itself</li>
<li>that the element contains a * Submit Button * defined by assigning to an element <code>&lt;Button&gt;</code> or to an element <code>&lt;a&gt;</code> the attribute <code>data-mb-toggle=&quot;submit </code>.</li>
</ul>
<pre><code>&lt;div id=&quot;sample1-en&quot; data-mb-action=&quot;api/PseudoForm&quot;&gt;
  &lt;!-- Input fields --&gt;
  &lt;button type=&quot;button&quot; data-mb-toggle=&quot;submit&quot;&gt;Invia dati&lt;/button&gt;
&lt;/div&gt;
</code></pre>
<h3 id="initialization">Initialization</h3>
<p>You can activate the pseudo form via javascript (<code>pform</code> can be a CSS selector or an HTML element)</p>
<pre><code>const myPseudoForm = new MB_PseudoForm(pForm) ;
</code></pre>
<p>or simply by assigning the attribute <code>data-mb-ride=&quot;pseudo-form&quot;</code> to the element.</p>
<pre><code>&lt;div id=&quot;sample1-en&quot; data-mb-action=&quot;api/PseudoForm&quot; data-mb-ride=&quot;pseudo-form&quot;&gt;
  &lt;!-- Input fields --&gt;
  &lt;button type=&quot;button&quot; data-mb-toggle=&quot;submit&quot;&gt;Invia dati&lt;/button&gt;
&lt;/div&gt;
</code></pre>
<h2 id="properties-and-methods">Properties and methods</h2>
<p>It could be useful to illustrate how the pseudo form works. For more details, we recommend examining the code directly. It&#39;s clear and fully commented.</p>
<p>MB_PseudoForm is based on three Javascript classes:</p>
<ul>
<li><code>MB_PseudoForm</code>, the main class</li>
<li><code>MB_PseudoFormValue</code> which defines the object in which the user&#39;s entered fields are transformed for sending the server</li>
<li><code>ValuesList</code> which provides some methods to manage a list of <code>MB_PseudoFormValue</code> </li>
</ul>
<h3 id="mb_pseudoformvalue">MB_PseudoFormValue</h3>
<p>MB_PseudoFormValue provides 5 properties that reflect the characteristics and value of the fields compiled by the user.</p>
<table>
<thead>
<tr>
<th>Property</th>
<th>Type</th>
<th>Description</th>
</tr>
</thead>
<tbody><tr>
<td><code>Name</code></td>
<td><code>string</code></td>
<td>Reflects the content of the attribute <code>name</code> of the element. If the <code>name</code> attribute is not present, the <code>id</code> attribute will be used.</td>
</tr>
<tr>
<td><code>Type</code></td>
<td><code>string</code></td>
<td>Reflects the content of the property <code>type</code>  of the element.</td>
</tr>
<tr>
<td><code>Value</code></td>
<td><code>any</code></td>
<td>If the element is a <code>checkbox</code>, it&#39;s&#39; <code>true</code> if selected, otherwise <code>false</code>. If the element is an input of type <code>file</code>, <code>Value</code> is the content of the file coded as DataUrlBase64. In other cases it reflects the content of the property <code>value</code> of the element.</td>
</tr>
<tr>
<td><code>Label</code></td>
<td><code>string</code></td>
<td>Reflects the content of the attribute <code>aria-label</code> of the element. If the attribute is not present it returns the same value that <code>Name</code></td>
</tr>
<tr>
<td><code>Detail</code></td>
<td><code>string</code></td>
<td>If the element is an input of type <code>file</code>, it returns  the original file name. In other cases it can be used to transfer to the server additional information on that field (see demo)</td>
</tr>
</tbody></table>
<p>The the pseudo form fields are transformed into MB_PseudoFormValue objects using the asynchronous static method <code>MB_Pseudoformvalue.CreateAsync</code> which returns a <code>Promise</code> that resolves with the created object. </p>
<h3 id="valueslist">ValuesList</h3>
<p>The value returned by the <code>MB_PseudoForm.collectData</code> method (see below), which collects the fields compiled by the user as a list of <code>MB_PseudoFormValue</code> objects is an instance of the <code>ValueList</code> class.</p>
<p>The <code>ValueList</code> class exposes only one property, <code>length</code> (which returns the length of the list) and offers some methods that help to manage it.</p>
<table>
<thead>
<tr>
<th>Method</th>
<th>Type returned</th>
<th>Description</th>
</tr>
</thead>
<tbody><tr>
<td><code>item(i)</code></td>
<td><code>MB_PseudoFormValue</code></td>
<td><strong>Parameter</strong>: <em>i</em> <code>number</code>. Returns the  <code>MB_PseudoFormValue</code> object with index <em>i</em></td>
</tr>
<tr>
<td><code>push(obj)</code></td>
<td><code>number</code></td>
<td><strong>Parameter</strong>: <em>obj</em> <code>MB_PseudoFormValue</code>. Add a <code>MB_PseudoFormValue</code> object to the list. If there is already an object with the same <code>Name</code>, the present object is replaced by the one inserted. Returns the new length of the list.</td>
</tr>
<tr>
<td><code>remove(name)</code></td>
<td><code>boolean</code></td>
<td><strong>Parameter</strong>: <em>name</em> <code>string</code>. Removes the object with <code>Name</code> = <em>name</em> from the list. It returns <code>true</code> if the object has been removed <code>false</code> if it has not been found on the list.</td>
</tr>
<tr>
<td><code>indexOf(name)</code></td>
<td><code>number</code></td>
<td><strong>Parameter</strong>: <em>name</em> <code>string</code>. Search the list with the object with <code>Name</code> = <em>name</em>. If object is found, it returns its index otherwise <code>-1</code>.</td>
</tr>
<tr>
<td><code>getValue(name)</code></td>
<td><code>any</code></td>
<td><strong>Parameter</strong>: <em>name</em> <code>string</code>. Search the list with the object with <code>Name</code> = <em>name</em>. If found, returns it&#39;s <code>Value</code>, otherwise <code>null</code>.</td>
</tr>
<tr>
<td><code>clear()</code></td>
<td><code>none</code></td>
<td>Clear the list</td>
</tr>
</tbody></table>
<h3 id="mb_pseudoform-1">MB_PseudoForm</h3>
<blockquote>
<p>In general, it should not be necessary to directly access the properties and methods of <code>MB_PseudoForm</code>. The interface with the pseudo form is guaranteed by the events (<code>change.mb.pseudoform</code>, <code>validate.mb.pseudoform</code> e <code>submitted.mb.pseudoform</code>) which are dispatched in the key moments of the process.  </p>
</blockquote>
<h4 id="properties"><strong>Properties</strong></h4>
<table>
<thead>
<tr>
<th>Property</th>
<th>Type</th>
<th>Description</th>
</tr>
</thead>
<tbody><tr>
<td><code>pseudoForm</code></td>
<td><code>HTML element</code></td>
<td>Readonly property. Returns the HTML element on which the pseudo form was built.</td>
</tr>
<tr>
<td><code>submit</code></td>
<td><code>HTML element</code></td>
<td>Readonly property. Returns the HTML element that is used as <em>Submit Button</em></td>
</tr>
<tr>
<td><code>inputs</code></td>
<td><code>static NodeList</code></td>
<td>Readonly property. Returns the list of elements (<code>input</code>, <code>select</code> e <code>textarea</code>) which are part of the pseudo form as a <a href="https://developer.mozilla.org/en-US/docs/Web/API/NodeList">static NodeList</a>.</td>
</tr>
<tr>
<td><code>pendingChanges</code></td>
<td><code>boolean</code></td>
<td>It returns <code>true</code> if at least one input element has been changed. It is automatically reset when the data is sent to the server. It can be reset (set to <code>false</code>) also programmatically.</td>
</tr>
</tbody></table>
<h4 id="methods"><strong>Methods</strong></h4>
<table>
<thead>
<tr>
<th>Method</th>
<th>Type returned</th>
<th>Description</th>
</tr>
</thead>
<tbody><tr>
<td><code>collectData</code></td>
<td><code>Promise</code></td>
<td>Asynchronous method. The Promise returned resolves the list of values entered by the user as a <code>ValueList</code>.</td>
</tr>
<tr>
<td><code>submitData</code></td>
<td>none</td>
<td>It allows you to programmatically send the pseudo form to the server. It dispatches a  <code>validate.mb.pseudoform</code> event (cancelable) immediately before sending data and a <code>submitted.mb.pseudoform</code> event immediately after receiving the response from the server.</td>
</tr>
</tbody></table>
<h4 id="events"><strong>Events</strong></h4>
<p>All events are sent to the HTML element on which the pseudo form is built. To manage them, therefore, just add an event listener to the element itself:</p>
<pre><code>&lt;div id=&quot;sample1-en&quot; data-mb-action=&quot;api/PseudoForm&quot; data-mb-ride=&quot;pseudo-form&quot;&gt;
  &lt;!-- Input fields --&gt;
  &lt;button type=&quot;button&quot; data-mb-toggle=&quot;submit&quot;&gt;Invia dati&lt;/button&gt;
&lt;/div&gt;
....
&lt;script&gt;
  const myForm = document.getElementById(&quot;sample1-en&quot;);
  myForm.addEventListener(&#39;validate.mb.pseudoform&#39;, event =&gt; {
    const values = event.detail;
    // .......
  })
&lt;/script&gt;
</code></pre>
<table>
<thead>
<tr>
<th>Event</th>
<th>Description</th>
</tr>
</thead>
<tbody><tr>
<td><code>change.mb.pseudoform</code></td>
<td>It is dispatched every time a pseudo form field is modified. The <code>detail</code> property of the event contains the HTML element whose <code>value</code> has been modified.</td>
</tr>
<tr>
<td><code>validate.mb.pseudoform</code></td>
<td>It is dispatched immediately before the data is sent to the server.The detail property of the event contains the <code>ValueList</code> which is about to be sent. It allows you to validate the data before sending. To extract information on specific fields, the <code>ValueList</code> class methods can be applied to the list. To cancel sending process, apply the <code>preventDefault</code> method to the event</td>
</tr>
<tr>
<td><code>submitted.mb.pseudoform</code></td>
<td>It is issued after the data is sent and either you have received the response from the server, or an error occurs. In the case of response from the server, the <code>detail</code> event property contains the response, in case of error contains an object with four properties: <code>Success</code> (<code>Boolean</code>, set to <code>false</code>), <code>Message</code> (<code>string</code>, contains the error message), <code>Exitcode</code> and <code>Data</code> currently not used (see demo for live example).</td>
</tr>
</tbody></table>
<h2 id="demo">Demo</h2>
<p>In the demo folder of the project you will find a simple ASP.NET Web Application that shows how to use <code>MB_PseudoForm</code> together with an API controller to generate, starting from a <code>MB_PseudoForm</code>, a formatted email with the information inserted by the user to send to the site staff and a thanksgiving email sent to the user himself.</p>
<h3 id="using-the-demo">Using the demo</h3>
<p>Clone the GIT repository on your computer</p>
<pre><code>git clone https://github.com/magicbruno/MB_PseudoForm.git
</code></pre>
<p>or <a href="https://github.com/magicbruno/MB_pseudo_form/archive/refs/heads/main.zip">download it</a>.</p>
<p>Open <code>/demo/demo.sln</code> in Visual Studio.</p>
<p>Before running the application you must configure the SMTP server that the controller will use to send the generated email messages.</p>
<p>Open <code>Web.config</code> in <strong>Visual Studio</strong> editor and in the <code>appSettings</code> section enter the data:</p>
<pre><code>    &lt;appSettings&gt;
    &lt;!-- Enter URL of the smtp server --&gt;
        &lt;add key=&quot;SmtpServer&quot; value=&quot;...&quot;/&gt;
    &lt;!-- Insert smtp credentials --&gt;
        &lt;add key=&quot;SmtpUsername&quot; value=&quot;...&quot;/&gt;
        &lt;add key=&quot;SmtpPassword&quot; value=&quot;...&quot;/&gt;
    &lt;!-- Change the SSL settings if necessary --&gt;
        &lt;add key=&quot;SmtpPort&quot; value=&quot;25&quot;/&gt;
        &lt;add key=&quot;SmtpUseSSL&quot; value=&quot;false&quot;/&gt;
    &lt;!-- Sender of the messages sent by the server --&gt;
        &lt;add key=&quot;DefaultSmtpFromMail&quot; value=&quot;...&quot;/&gt;
    &lt;!-- Staff mailbox --&gt;
        &lt;add key=&quot;MailTo&quot; value=&quot;...&quot;/&gt;
    &lt;/appSettings&gt;
</code></pre>
<p>Then launch the application in Iis Express by pressing <kbd>f5</kbd> o <kbd>ctrl</kbd> + <kbd>f5</kbd>.</p>
<blockquote>
<h2 id="note">Note</h2>
<p>To use the API controller <code>/ApiControllers/PseudoFormController.cs</code> in your project you could have to install the package <a href="https://www.nuget.org/packages/Microsoft.AspNet.WebApi">Microsoft.AspNet.WebApi</a>. You must also add the classes <code>/ApiControllers/ApiControllerResponse.cs</code> and <code>/ApiControllers/PseudoFormModel.cs</code> to the project. More information about ASP.NET Web Api <a href="https://docs.microsoft.com/it-it/aspnet/web-api/">here</a>.</p>
</blockquote>
