UNPKG

@epa-wg/custom-element

Version:

Declarative Custom Element as W3C proposal PoC with native(XSLT) based templating

282 lines (261 loc) 12.6 kB
<!DOCTYPE html> <html lang="en" xmlns:xsl="http://www.w3.org/1999/XSL/Transform" xmlns:xhtml="http://www.w3.org/1999/xhtml"> <head> <meta http-equiv="Content-Type" content="text/html; charset=utf-8"/> <title>Forms - Declarative Custom Element implementation demo</title> <link rel="icon" href="./wc-square.svg"/> <script type="module" src="../local-storage.js"></script> <script type="module" src="../custom-element.js"></script> <style> @import "./demo.css"; label { display: flex; } label:has(input[type="text"],input[type="password"],input:not([type]) ) { flex-direction: column; } nav { max-width: 32em; } </style> <!-- https://github.com/mdn/learning-area/blob/main/html/forms/form-validation/custom-error-message.html todo: apply setCustomValidity( warningStr ) --> </head> <body> <nav> <a href="../index.html"><h3><code>custom-element</code> demo</h3></a> <p> <b>formData</b><br/> The values of named form fields are populated into the <b>slice</b> as <b>form-data</b> on <var>change</var> or <var>submit</var> event. The field values can be used in form validation via <var>custom-validity</var> attribute and in condition to enabling the form parts <a href="https://developer.mozilla.org/en-US/docs/Web/API/FormData">formData MDN</a> </p> <details> <summary>slice to form-data mapping</summary> <html-demo-element> <template> <datadom hidden> <slice> <signin-form> <form-data> <username>QWE</username> <password>ASD</password> </form-data> </signin-form> </slice> </datadom> </template> </html-demo-element> </details> <p> <b> custom-validity attribute </b><br/> applied on the form itself or on the form field.<br/> The value is an XPath over DCE <var>datadom</var>. When evaluated as <u>boolean</u>, it would enable(true) or disable(false) the form submission, acting as form validation mechanism.<br> Alternatively, the value can be evaluated as a <u>string</u> which would be treated as an error and can be used as validation error message set as <var>@validation-message</var> attribute on the form slice. Look for <var>email-form/@validation-message</var> example on the page.<br/> </p> <p> When <var>custom-validity</var> attribute is set on the field, its XPath evaluated value is propagated to <a href="https://developer.mozilla.org/en-US/docs/Web/API/HTMLObjectElement/validationMessage"> validationMessage property</a>. Which would be shown via browser system popup as the field validation error. </p> <p> <var>@validation-message</var> is set either by <var>custom-validity</var> attribute or by browser as system message. By default, it is shown as popup on the field validation. But also is available for template as a string via form field attribute. Like in <var>email-form/@validation-message</var>. </p> <a href="https://developer.mozilla.org/en-US/docs/Learn/Forms/Form_validation">Form Validation MDN</a> </nav> <html-demo-element legend="1. Simple validation" description="custom-validity boolean value prevents submission, username length switches Next to 'Sign In' button "> <ol> <li> Click Next, observe the warning</li> <li> Fill input with 10+ characters</li> <li> Click Next, the password and "Sign In" button should appear</li> </ol> <template> <custom-element> <template> <form slice="signin-form" custom-validity=" string-length(/datadom/slice/signin-form/form-data/username) &gt; 10 and string-length(//form-data/password) &gt; 3 " > <label> Email <input name="username" autocomplete="username" placeholder="Email, phone, or username" required=""> </label> <variable name="showpassword" select="string-length(//form-data/username) &gt; 10 "></variable> <if test="not($showpassword)"> <button slice="confirm" slice-event="click" slice-value="'password'">Next</button> </if> <if test="$showpassword"> <label>Enter password: <input name="password" type="password" required> </label> <button>Sign In</button> </if> username {//username} </form> </template> </custom-element> </template> </html-demo-element> <html-demo-element legend="2. Form life cycle demo" description="form-data in the form slice is the source of truth"> <template> <custom-element> <template> <form slice="signin-form" custom-validity=" string-length(/datadom/slice/signin-form/form-data/username) &gt; 9 and ( ( //confirm-by = 'sms' ) or ( //confirm-by = 'email' ) or ( //confirm-by = 'password' and string-length(//form-data/password) &gt; 3 ) ) " > <!-- form validity should be based on form-data --> <variable name="warn"> <if test="string-length(//username-slice) &lt; 9 "> Should be 10 or more symbols. &nbsp; <!-- updated by slice on input event --> </if> <if test="//form-data/confirm-by = 'sms'"> Message and Data Rates may apply. <!-- updated by form change by radio select --> </if> </variable> <label> Enter your email, phone, or user name <input name="username" autocomplete="username" placeholder="Email, phone, or username" custom-validity="( string-length(//username-slice) &gt; 9 ) ?? 'should be 10+ symbols'" slice-event="input" slice="username-slice" required /> </label> <var> {$warn} </var> <fieldset> <legend>Confirm by</legend> <label><input type="radio" name="confirm-by" value="email"/> email </label> <label><input type="radio" name="confirm-by" value="sms"/> text to phone </label> <label><input type="radio" name="confirm-by" value="password"/> password </label> <if test="/datadom/slice/signin-form/form-data/confirm-by = 'password'"> <label>Enter password: <input type="password" NAME="password" custom-validity="( string-length(//form-data/password) &gt; 3 ) ?? 'password is too short'" /></label> </if> <if test="not(//confirm-by)"> Please select the auth method </if> </fieldset> <section> <button>Sign In</button> </section> </form> //username-slice {//username-slice}<br/> //username {//username}<br/> //confirm-by {//confirm-by}<br/> //password {//password} </template> </custom-element> </template> </html-demo-element> <html-demo-element legend="3. read system validity message" description="validationMessage propagated into slice as 'validation-message' attribute "> <ol> <li> type in input field</li> <li> delete input field content</li> <li> observe the warning in string after input</li> <li> Click Next observe the system warning in dropdown over input</li> </ol> <template> <custom-element> <template> <form slice="email-form"> <label> Email <input slice="username" slice-event="input" placeholder="non-empty" required> </label> <if test="//username/@validation-message"> <var>{//username/@validation-message}</var> </if> <button>Next</button> </form> </template> </custom-element> </template> </html-demo-element> <html-demo-element legend="4. form validity message" description="@validation-message propagated into form slice and "> <ol> <li> type up to 3 chars in input field</li> <li> observe the slice value change</li> <li> click next</li> <li> observe the warning bellow the button</li> </ol> <template> <custom-element> <template> <form slice="email-form" custom-validity=" string-length(//slice/username) &gt; 3 ?? concat('should be more than 3 characters, now is ',string-length(//slice/username) ) " > <label> Email <input name="email" slice="username" slice-event="input" placeholder="non-empty" required/> </label> <if test="//username/@validation-message"> <var>{//username/@validation-message}</var> </if> <button>Next</button> <p>//email-form/@validation-message: {//email-form/@validation-message} </p> <p>//slice/username: {//slice/username} </p> </form> </template> </custom-element> </template> </html-demo-element> <html-demo-element legend="5. using custom-element as form input" description="bypass value to container form " id="sample-5" > <ol> <li> select radio in top group</li> <li> observe the fruit selected on the left</li> <li> observe the warning message bellow button</li> <li> next button does not submit the form</li> <li> select radio in bottom group</li> <li> observe the fruit selected on the right</li> <li> same fruit selection would eliminate the warning and allow the form submission</li> <li> after submit, observe the URL parameters 'inp-1=🍏&inp-2=🍏' </li> </ol> <template> <custom-element tag="sample-input"> <template> <attribute name="name" ></attribute> <attribute name="value" select="//val"></attribute> {$name} <label><input type="radio" name="{$name}" slice="val" value="🍏">Apple</label> <label><input type="radio" name="{$name}" slice="val" value="🍌">Banana</label> </template> </custom-element> <custom-element> <template> <form slice="cart-form" action="#sample-5" custom-validity="(//inp1 = //inp2) ?? 'pick same fruit'" > <sample-input slice="inp1" name="inp-1"></sample-input> <sample-input slice="inp2" name="inp-2"></sample-input> <button>Next</button> Picked :{//inp1} and {//inp2} <p>{//cart-form/@validation-message}</p> </form> </template> </custom-element> </template> </html-demo-element> <script type="module" src="https://unpkg.com/html-demo-element@1/html-demo-element.js"></script> </body> </html>