Form with a Dialog

Build a form that relies on HTML dialogs for parts of its input.

In this example we wil build a form that uses an HTML dialog to enter or edit data. We will build an expense report application.

The form consists of general input fields: description, cost center, manager and payment method. These are regular input fields and select controls which are rendered in the table lines 5 to 39 of the following code.

Besides these fields, the form contains an empty DIALOG element (line 49) with id linedialog and classes dialog-modal and onclose-restore. The dialog-modal class tells Sircl to open the dialog in modal way (blocking access to the underlying page). The onclose-restore class tells Sircl to restore the content of the DIALOG element when the dialog is closed, which in this case basically means to clear the dialog when it is closed. We'll see later why.

Furthermore, the initial form contains two buttons: an Add new line button (line 42) and a Submit button (line 46). Both are regular form submit buttons where the Add new line button has a formaction attribute to perform a LineNew action.

The whole form lays inside a DIV element with target class: when the form is submitted, the surrounding DIV element is the inline target and the server is expected to return new content for that DIV element. The target also contains an overlay (line 2) that will show up whenever the form is submitted:

<div class="target">
  <div class="overlay" hidden></div>
  <form action="/Expense/Submit" method="post" class="onsubmit-disable">

    <table>
      <tbody>
        <tr>
          <td>Description:</td>
          <td>
            <input type="text" name="Item.Description" />
          </td>
        </tr>
        <tr>
          <td>Cost center:</td>
          <td>
            <select name="Item.CostCenter">
              <option value=""></option>
              <option value="...">...</option>
            </select>
          </td>
        </tr>
        <tr>
          <td>Manager:</td>
          <td>
            <select name="Item.Manager">
              <option value=""></option>
              <option value="...">...</option>
            </select>
          </td>
        </tr>
        <tr>
        <td>Payment method:</td>
        <td>
          <label><input type="radio" name="Item.PaymentMethod" value="0" checked="chekced" /> By crediting credit card</label><br />
          <label><input type="radio" name="Item.PaymentMethod" value="1" /> By bank transfer</label>
        </td>
        </tr>
      </tbody>
    </table>

    <div>
      <button type="submit" formaction="/Expense/LineNew">+ Add new line</button>
    </div>

    <div>
      <button type="submit">Submit</button>
    </div>

    <dialog id="linedialog" class="dialog-modal onclose-restore"></dialog>

  </form>
</div>

Clicking the Submit button will submit the form and, unless valid data was entered, result in the form being returned with information about validation errors: a new version of the form (including validation information) is returned by the server and replaces the content of the inline target. This is normal behaviour with Sircl.

Clicking the Add new line button is also expected to return new content for the inline target. And that is why clicking this button will trigger the overlay of the target.

But the invoked LineNew action will only return content of the DIALOG element. And to tell the client it does provide content for the dialog only, it sets the following response header:

X-Sircl-Target: #linedialog

In other words, the server decides it will provide content for the dialog only, not for the whole form. This is the same as having a target="#linedialog" attribute on the Add new line button element (except the overlay would not be triggered).

The following HTML code is then returned by the LineNew action:

<h3>New line</h3>

<div>
  <label>Description</label><br />
  <input type="text" name="CurrentLine.Description" />
</div>
<div>
  <label>Date</label><br />
  <input type="date" name="CurrentLine.Date" />
</div>
<div>
  <label>Cateogry:</label><br />
  <select name="CurrentLine.Category">
    <option value=""></option>
    <option value="...">...</option>
  </select>
</div>
<div>
  <label>Amount:</label><br />
  <input type="text" name="CurrentLine.Amount" />
</div>

<div>
  <button type="button" class="onclick-closedialog">Cancel</button>
  <button type="submit" formaction="/Expense/LineSubmit">Add</button>
</div>

Since the NewLine action returns content to be embedded in a DIALOG element, Sircl will make sure the dialog is opened. And since the DIALOG element has the dialog-modal class, the HTML dialog will be opened in modal mode.

The DIALOG element is part of the surrounding form. As a consequence, the input elements and submit buttons inside the dialog are part of the surrounding form. 

Pressing the Add button in the dialog will therefore submit the whole form to the LineSubmit action. If entered data is valid, new content will be provided for the regular inline target (the DIV element surrounding the form): a new version of the form with information of the added expense report line (with hidden fields to include the content in subsequent submits).

If the LineSubmit action estimates the submitted content is not valid, it will return a new version of the dialog content (including validation information) as well as the following response header to instruct Sircl to display the returned content inside the DIALOG element instead of inside the target surrounding the form:

X-Sircl-Target: #linedialog

The dialog content also includes a Cancel button to close the dialog. This button does not submit the form, it simply closes the dialog by means of the onclick-closedialog event-action attribute. When closing the dialog this way, it would still contain its fields which may interfer with the (validation of the) main form. Therefore, the onclose-restore class on the dialog was added: it removes all content of the dialog when it is closed using the Cancel button.

 

Working demo
Loading demo...

 

Requirements

This example requires following Sircl library files to be loaded:

or:

Or their non-minified counterparts.

See the Get Started section about how to set up your project to use the Sircl library.