amp-inputmask

Edit on Github
Open in Playground View Demo

Experimental Mode

This example uses the following experimental feature: [amp-inputmask]. Enable the experiment via the button below. Some components require the AMP Dev Channel to be enabled as well. Learn more here.

Enable Dev Channel

Introduction

Input masks automatically add formatting characters to user input, and prevent users from typing input that doesn't match the mask. For example, an input mask on a telephone field automatically adds special characters like (, ) and -, and users can type only the numbers needed while the mask prevents them from typing incorrect characters.

The amp-inputmask component enables input masks for form fields in AMP documents.

Setup

Import the amp-inputmask component in the header

<script async custom-element="amp-inputmask" src="https://cdn.ampproject.org/v0/amp-inputmask-0.1.js"></script>

amp-inputmask depends on the amp-form extension, so the amp-form script also needs to be added to the document.

<script async custom-element="amp-form" src="https://cdn.ampproject.org/v0/amp-form-0.1.js"></script>

amp-mustache isn't required to use amp-inputmask, but here amp-form uses it to render the submit-success message, and amp-list uses it to render templates.

<script async custom-template="amp-mustache" src="https://cdn.ampproject.org/v0/amp-mustache-0.1.js"></script>

amp-list also isn't required to use amp-inputmask, but here the advanced example uses it to render the changing phone values.

<script async custom-element="amp-list" src="https://cdn.ampproject.org/v0/amp-list-0.1.js"></script>

amp-bind also isn't required to use amp-inputmask, but here the advanced example uses it to render the changing phone values.

<script async custom-element="amp-bind" src="https://cdn.ampproject.org/v0/amp-bind-0.1.js"></script>

Basic usage

The mask attribute specifies the characters that users are allowed to input, and any special characters that can be automatically added by the mask. Here, the user may enter a Canadian postal code.

In the mask, L allows the user to enter an alphabetic character. 0 denotes a numeric character. _ is a literal space character. See the full mask specification at the amp-inputmask documentation

Example

<form class="sample-form"
  method="post"
  action-xhr="/components/amp-inputmask/default"
  target="_top">
  <label>Postal code:
    <input name="code"
      mask="L0L_0L0"
      placeholder="A1A 1A1">
  </label>
  <input type="submit">
  <div submit-success>
    <template type="amp-mustache">
      <p>You submitted: {{code}}</p>
    </template>
  </div>
</form>

The mask attribute also accepts special named attributes. These are payment-card, date-dd-mm-yyyy, date-mm-dd-yyyy, date-mm-yy and date-yyyy-mm-dd.

Example

<form class="sample-form"
  method="post"
  action-xhr="/components/amp-inputmask/default"
  target="_top">
  <p>
    <label class="mask-label">Credit card (
      <code>payment-card</code>)
      <input name="payment-card"
        type="tel"
        mask="payment-card"
        placeholder="Card number">
    </label>
  </p>
  <p>
    <label class="mask-label">mm/dd/yyyy (
      <code>date-mm-dd-yyyy</code>)
      <input name="date1"
        mask="date-mm-dd-yyyy"
        placeholder="mm/dd/yyyy"
        type="tel">
    </label>
  </p>
  <p>
    <label class="mask-label">dd/mm/yyyy (
      <code>date-dd-mm-yyyy</code>)
      <input name="date2"
        mask="date-dd-mm-yyyy"
        placeholder="dd/mm/yyyy"
        type="tel">
    </label>
  </p>
  <p>
    <label class="mask-label">yyyy-mm-dd (
      <code>date-yyyy-mm-dd</code>)
      <input name="date3"
        mask="date-yyyy-mm-dd"
        placeholder="yyyy-mm-dd"
        type="tel">
    </label>
  </p>
  <p>
    <label class="mask-label">mm/yy (
      <code>date-mm-yy</code>)
      <input name="date4"
        mask="date-mm-yy"
        placeholder="MM/YY"
        type="tel">
    </label>
  </p>
  <input type="submit">
  <div submit-success>
    <template type="amp-mustache">
      <p>Thanks for submitting the form!</p>
    </template>
  </div>
</form>

Removing nonalphanumeric characters

If the mask-output attribute is set to "alphanumeric", amp-inputmask will add a hidden input with only the alphanumeric characters from the original input. The default value is "raw"

Example

<form class="sample-form"
  method="post"
  action-xhr="/components/amp-inputmask/postal"
  target="_top">
  <label>Postal code:
    <input name="code"
      mask="L0L_0L0"
      placeholder="A1A 1A1"
      mask-output="alphanumeric">
  </label>
  <input type="submit">
  <div submit-success>
    <template type="amp-mustache">
      <p>The raw value: {{code}}</p>
      <p>The unmasked value: {{code-unmasked}}</p>
    </template>
  </div>
</form>

Composing a phone number form

To enable input masking for a large number of phone numbers, a selector can be combined with amp-list and amp-bind to allow the user to select their phone number format.

Example

Phone (United States)
<amp-state id="bound">
  <script type="application/json">
    false
  </script>
</amp-state>
<amp-state id="phoneNumber">
  <script type="application/json">
    ""
  </script>
</amp-state>
<amp-state id="doubleBufferPhoneNumber">
  <script type="application/json">
    ""
  </script>
</amp-state>
<amp-state id="countryCode">
  <script type="application/json">
    "US"
  </script>
</amp-state>
<amp-state id="phoneCodes">
  <script type="application/json">
    [{
        "placeholder": "+213-00-000-0000",
        "mask": "+213-00-000-0000",
        "cc": "DZ",
        "cd": "Algeria"
      },
      {
        "placeholder": "+54(000)000-0000",
        "mask": "+54(000)000-0000",
        "cc": "AR",
        "cd": "Argentina"
      },
      {
        "placeholder": "+973-0000-0000",
        "mask": "+\\973-0000-0000",
        "cc": "BH",
        "cd": "Bahrain"
      },
      {
        "placeholder": "+501-000-0000",
        "mask": "+501-000-0000",
        "cc": "BZ",
        "cd": "Belize"
      },
      {
        "placeholder": "+591-0-000-0000",
        "mask": "+5\\91-0-000-0000",
        "cc": "BO",
        "cd": "Bolivia"
      },
      {
        "placeholder": "+55-00-00000-0000",
        "mask": "+55-00-0000-0000 +55-00-00000-0000",
        "cc": "BR",
        "cd": "Brazil"
      },
      {
        "placeholder": "+56-0-0000-0000",
        "mask": "+56-0-0000-0000",
        "cc": "CL",
        "cd": "Chile"
      },
      {
        "placeholder": "+86-00-00000-00000",
        "mask": "+86(000)0000-000 +86(000)0000-0000 +86-00-00000-00000",
        "cc": "CN",
        "cd": "China (PRC)"
      },
      {
        "placeholder": "+57(000)000-0000",
        "mask": "+57(000)000-0000",
        "cc": "CO",
        "cd": "Colombia"
      },
      {
        "placeholder": "+506-0000-0000",
        "mask": "+506-0000-0000",
        "cc": "CR",
        "cd": "Costa Rica"
      },
      {
        "placeholder": "+53-0-000-0000",
        "mask": "+53-0-000-0000",
        "cc": "CU",
        "cd": "Cuba"
      },
      {
        "placeholder": "+593-00-000-0000",
        "mask": "+5\\93-0-000-0000 +5\\93-00-000-0000",
        "cc": "EC",
        "cd": "Ecuador"
      },
      {
        "placeholder": "+20(000)000-0000",
        "mask": "+20(000)000-0000",
        "cc": "EG",
        "cd": "Egypt"
      },
      {
        "placeholder": "+503-00-00-0000",
        "mask": "+503-00-00-0000",
        "cc": "SV",
        "cd": "El Salvador"
      },
      {
        "placeholder": "+33-0-00-00-00-00",
        "mask": "+33-0-00-00-00-00",
        "cc": "FR",
        "cd": "France"
      },
      {
        "placeholder": "+49(0000)000-0000",
        "mask": "+4\\9-000-000 +4\\9(000)00-00 +4\\9(000)00-000 +4\\9(000)00-0000 +4\\9(000)000-0000 +4\\9(0000)000-0000",
        "cc": "DE",
        "cd": "Germany"
      },
      {
        "placeholder": "+502-0-000-0000",
        "mask": "+502-0-000-0000",
        "cc": "GT",
        "cd": "Guatemala"
      },
      {
        "placeholder": "+504-0000-0000",
        "mask": "+504-0000-0000",
        "cc": "HN",
        "cd": "Honduras"
      },
      {
        "placeholder": "+91(0000)000-000",
        "mask": "+\\91(0000)000-000",
        "cc": "IN",
        "cd": "India"
      },
      {
        "placeholder": "+62(800)000-00-000",
        "mask": "+62-00-000-00 +62-00-000-000 +62-00-000-0000 +62(800)000-000 +62(800)000-0000 +62(800)000-00-000",
        "cc": "ID",
        "cd": "Indonesia"
      },
      {
        "placeholder": "+964(000)000-0000",
        "mask": "+\\964(000)000-0000",
        "cc": "IQ",
        "cd": "Iraq"
      },
      {
        "placeholder": "+39(000)0000-00-00",
        "mask": "+3\\9(00)00-00 +3\\9(000)00-00 +3\\9(000)00-000 +3\\9(000)000-000 +3\\9(000)0000-000 +3\\9(300)00-00-00 +3\\9(300)000-00-00 +3\\9(000)0000-00-00",
        "cc": "IT",
        "cd": "Italy"
      },
      {
        "placeholder": "+81-00-0000-0000",
        "mask": "+81(000)000-000 +81-00-0000-0000",
        "cc": "JP",
        "cd": "Japan"
      },
      {
        "placeholder": "+962-0-0000-0000",
        "mask": "+\\962-0-0000-0000",
        "cc": "JO",
        "cd": "Jordan"
      },
      {
        "placeholder": "+82-00-000-0000",
        "mask": "+82-00-000-0000",
        "cc": "KR",
        "cd": "Korea (South)"
      },
      {
        "placeholder": "+965-0000-0000",
        "mask": "+\\965-0000-0000",
        "cc": "KW",
        "cd": "Kuwait"
      },
      {
        "placeholder": "+961-00-000-000",
        "mask": "+\\961-0-000-000 +\\961-00-000-000",
        "cc": "LB",
        "cd": "Lebanon"
      },
      {
        "placeholder": "+218-21-000-0000",
        "mask": "+218-00-000-000 +218-21-000-0000",
        "cc": "LY",
        "cd": "Libya"
      },
      {
        "placeholder": "+52(000)000-0000",
        "mask": "+52-00-00-0000 +52(000)000-0000",
        "cc": "MX",
        "cd": "Mexico"
      },
      {
        "placeholder": "+212-00-0000-000",
        "mask": "+212-00-0000-000",
        "cc": "MA",
        "cd": "Morocco"
      },
      {
        "placeholder": "+31-00-000-0000",
        "mask": "+31-00-000-0000",
        "cc": "NL",
        "cd": "Netherlands"
      },
      {
        "placeholder": "+505-0000-0000",
        "mask": "+505-0000-0000",
        "cc": "NI",
        "cd": "Nicaragua"
      },
      {
        "placeholder": "+47(000)00-000",
        "mask": "+47(000)00-000",
        "cc": "NO",
        "cd": "Norway"
      },
      {
        "placeholder": "+968-00-000-000",
        "mask": "+\\968-00-000-000",
        "cc": "OM",
        "cd": "Oman"
      },
      {
        "placeholder": "+507-000-0000",
        "mask": "+507-000-0000",
        "cc": "PA",
        "cd": "Panama"
      },
      {
        "placeholder": "+595(000)000-000",
        "mask": "+5\\95(000)000-000",
        "cc": "PY",
        "cd": "Paraguay"
      },
      {
        "placeholder": "+51(000)000-000",
        "mask": "+51(000)000-000",
        "cc": "PE",
        "cd": "Peru"
      },
      {
        "placeholder": "+351-00-000-0000",
        "mask": "+351-00-000-0000",
        "cc": "PT",
        "cd": "Portugal"
      },
      {
        "placeholder": "+974-0000-0000",
        "mask": "+\\974-0000-0000",
        "cc": "QA",
        "cd": "Qatar"
      },
      {
        "placeholder": "+7(000)000-00-00",
        "mask": "+7(000)000-00-00",
        "cc": "RU",
        "cd": "Russia"
      },
      {
        "placeholder": "+966-5-0000-0000",
        "mask": "+\\966-0-000-000 +\\966-5-0000-0000",
        "cc": "SA",
        "cd": "Saudi Arabia"
      },
      {
        "placeholder": "+34(000)000-000",
        "mask": "+34(000)000-000",
        "cc": "ES",
        "cd": "Spain"
      },
      {
        "placeholder": "+963-00-0000-000",
        "mask": "+\\963-00-0000-000",
        "cc": "SY",
        "cd": "Syrian Arab Republic"
      },
      {
        "placeholder": "+886-0-0000-0000",
        "mask": "+886-0000-0000 +886-0-0000-0000",
        "cc": "TW",
        "cd": "Taiwan"
      },
      {
        "placeholder": "+216-00-000-000",
        "mask": "+216-00-000-000",
        "cc": "TN",
        "cd": "Tunisia"
      },
      {
        "placeholder": "+90(000)000-0000",
        "mask": "+\\90(000)000-0000",
        "cc": "TR",
        "cd": "Turkey"
      },
      {
        "placeholder": "+971-50-000-0000",
        "mask": "+\\971-0-000-0000 +\\971-50-000-0000",
        "cc": "AE",
        "cd": "United Arab Emirates"
      },
      {
        "placeholder": "+44-00-0000-0000",
        "mask": "+44-00-0000-0000",
        "cc": "UK",
        "cd": "United Kingdom"
      },
      {
        "placeholder": "+598-0-000-00-00",
        "mask": "+5\\98-0-000-00-00",
        "cc": "UY",
        "cd": "Uruguay"
      },
      {
        "placeholder": "+1(000)000-0000",
        "mask": "+1(000)000-0000",
        "cc": "US",
        "cd": "USA and Canada"
      },
      {
        "placeholder": "+58(000)000-0000",
        "mask": "+58(000)000-0000",
        "cc": "VE",
        "cd": "Venezuela"
      },
      {
        "placeholder": "+84(000)0000-000",
        "mask": "+84-00-0000-000 +84(000)0000-000",
        "cc": "VN",
        "cd": "Vietnam"
      },
      {
        "placeholder": "+967-000-000-000",
        "mask": "+\\967-0-000-000 +\\967-00-000-000 +\\967-000-000-000",
        "cc": "YE",
        "cd": "Yemen"
      }
    ]
  </script>
</amp-state>
<select on="change: AMP.setState({countryCode: event.value, bound: true, doubleBufferPhoneNumber: phoneNumber})">
  <option value="DZ">Algeria</option>
  <option value="AR">Argentina</option>
  <option value="BH">Bahrain</option>
  <option value="BZ">Belize</option>
  <option value="BO">Bolivia</option>
  <option value="BR">Brazil</option>
  <option value="US">Canada</option>
  <option value="CL">Chile</option>
  <option value="CN">China (PRC)</option>
  <option value="CO">Colombia</option>
  <option value="CR">Costa Rica</option>
  <option value="CU">Cuba</option>
  <option value="EC">Ecuador</option>
  <option value="EG">Egypt</option>
  <option value="SV">El Salvador</option>
  <option value="FR">France</option>
  <option value="DE">Germany</option>
  <option value="GT">Guatemala</option>
  <option value="HN">Honduras</option>
  <option value="IN">India</option>
  <option value="ID">Indonesia</option>
  <option value="IQ">Iraq</option>
  <option value="IT">Italy</option>
  <option value="JP">Japan</option>
  <option value="JO">Jordan</option>
  <option value="KR">Korea (South)</option>
  <option value="KW">Kuwait</option>
  <option value="LB">Lebanon</option>
  <option value="LY">Libya</option>
  <option value="MX">Mexico</option>
  <option value="MA">Morocco</option>
  <option value="NL">Netherlands</option>
  <option value="NI">Nicaragua</option>
  <option value="NO">Norway</option>
  <option value="OM">Oman</option>
  <option value="PA">Panama</option>
  <option value="PY">Paraguay</option>
  <option value="PE">Peru</option>
  <option value="PT">Portugal</option>
  <option value="QA">Qatar</option>
  <option value="RU">Russia</option>
  <option value="SA">Saudi Arabia</option>
  <option value="ES">Spain</option>
  <option value="SY">Syrian Arab Republic</option>
  <option value="TW">Taiwan</option>
  <option value="TN">Tunisia</option>
  <option value="TR">Turkey</option>
  <option value="AE">United Arab Emirates</option>
  <option value="UK">United Kingdom</option>
  <option value="UY">Uruguay</option>
  <option value="US"
    selected>USA</option>
  <option value="VE">Venezuela</option>
  <option value="VN">Vietnam</option>
  <option value="YE">Yemen</option>
</select>
<form class="sample-form"
  method="post"
  action-xhr="/components/amp-inputmask/phone"
  target="_top"
  id="form-g">
  <amp-layout [hidden]="bound"
    layout="fixed-height"
    height="60">
    <table>
      <tbody>
        <tr>
          <td>Phone (United States)</td>
          <td>
            <input on="input-throttled: AMP.setState({phoneNumber: event.value})"
              id="g-phone-nobind"
              name="phone"
              mask="+1(000)000-0000"
              mask-output="alphanumeric"
              placeholder="+1(000)000-0000"
              [disabled]="bound"
              type="tel">
          </td>
        </tr>
      </tbody>
    </table>
    <input type="submit">
  </amp-layout>
  <amp-list hidden
    [hidden]="!bound"
    layout="fixed-height"
    height="60"
    items="."
    [src]="phoneCodes.filter(x => x.cc == countryCode)[0]">
    <template type="amp-mustache">
      <table>
        <tbody>
          <tr>
            <td>Phone ({{cd}})</td>
            <td>
              <input on="input-throttled: AMP.setState({phoneNumber: event.value})"
                id="g-phone"
                name="phone"
                mask="{{mask}}"
                mask-output="alphanumeric"
                placeholder="{{placeholder}}"
                disabled
                [disabled]="!bound"
                [value]="doubleBufferPhoneNumber"
                type="tel">
            </td>
          </tr>
        </tbody>
      </table>
      <input type="submit">
    </template>
  </amp-list>
  <div submit-success>
    <template type="amp-mustache">
      <p>You submitted: {{phone}}</p>
      <p>The unmasked value: {{phone-unmasked}}</p>
    </template>
  </div>
</form>