Add frontend validation for TextInput()s

- Add input validation regexes to input_validations.js
- Add those validators to text fields without validaiton
This commit is contained in:
graham-dds 2020-01-21 10:12:04 -05:00
parent 156d733aee
commit 3cf9fdac76
12 changed files with 46 additions and 17 deletions

View File

@ -9,6 +9,12 @@ export default {
unmask: [], unmask: [],
validationError: 'Please enter a response', validationError: 'Please enter a response',
}, },
clinNumber: {
mask: false,
match: /^\d{4}$/,
unmask: [],
validationError: 'Please enter a 4-digit CLIN number',
},
date: { date: {
mask: [/\d/, /\d/, '/', /\d/, /\d/, '/', /\d/, /\d/, /\d/, /\d/], mask: [/\d/, /\d/, '/', /\d/, /\d/, '/', /\d/, /\d/, /\d/, /\d/],
match: /(0[1-9]|1[012])[- \/.](0[1-9]|[12][0-9]|3[01])[- \/.](19|20)\d\d/, match: /(0[1-9]|1[012])[- \/.](0[1-9]|[12][0-9]|3[01])[- \/.](19|20)\d\d/,
@ -34,6 +40,20 @@ export default {
unmask: ['$', ','], unmask: ['$', ','],
validationError: 'Please enter a dollar amount', validationError: 'Please enter a dollar amount',
}, },
defaultStringField: {
mask: false,
match: /^[A-Za-z0-9\-_ \.]{1,100}$/,
unmask: [],
validationError:
'Please enter a response of no more than 100 alphanumeric characters',
},
defaultTextAreaField: {
mask: false,
match: /^[A-Za-z0-9\-_ \.]{1,1000}$/,
unmask: [],
validationError:
'Please enter a response of no more than 1000 alphanumeric characters',
},
clinDollars: { clinDollars: {
mask: createNumberMask({ prefix: '$', allowDecimal: true }), mask: createNumberMask({ prefix: '$', allowDecimal: true }),
match: /^-?\d+\.?\d*$/, match: /^-?\d+\.?\d*$/,
@ -53,6 +73,13 @@ export default {
unmask: [','], unmask: [','],
validationError: 'Please enter a number', validationError: 'Please enter a number',
}, },
name: {
mask: false,
match: /.{1,100}/,
unmask: [],
validationError:
'This field accepts letters, numbers, commas, apostrophes, hyphens, and periods.',
},
phoneExt: { phoneExt: {
mask: createNumberMask({ mask: createNumberMask({
prefix: '', prefix: '',
@ -71,7 +98,7 @@ export default {
unmask: [], unmask: [],
validationError: 'Portfolio names can be between 4-100 characters', validationError: 'Portfolio names can be between 4-100 characters',
}, },
requiredField: { required: {
mask: false, mask: false,
match: /.+/, match: /.+/,
unmask: [], unmask: [],

View File

@ -230,6 +230,8 @@
&--anything, &--anything,
&--portfolioName, &--portfolioName,
&--requiredField, &--requiredField,
&--defaultStringField,
&--defaultTextAreaField,
&--taskOrderNumber, &--taskOrderNumber,
&--email { &--email {
input { input {

View File

@ -13,7 +13,7 @@
) }} ) }}
<div class="accordion-table__item-content new-env"> <div class="accordion-table__item-content new-env">
<div class="h4">{{ "portfolios.applications.enter_env_name" | translate }}</div> <div class="h4">{{ "portfolios.applications.enter_env_name" | translate }}</div>
{{ TextInput(new_env_form.name, label="", validation="requiredField", optional=False) }} {{ TextInput(new_env_form.name, label="", validation="defaultStringField", optional=False) }}
<div class="action-group"> <div class="action-group">
{{ SaveButton(text=('common.save' | translate), element="input", form="add-new-env") }} {{ SaveButton(text=('common.save' | translate), element="input", form="add-new-env") }}
<a class='action-group__action icon-link icon-link--default' v-on:click="toggle"> <a class='action-group__action icon-link icon-link--default' v-on:click="toggle">

View File

@ -81,7 +81,7 @@
<base-form inline-template> <base-form inline-template>
<form action="{{ url_for('applications.update_environment', environment_id=env['id']) }}" method="post" v-on:submit="handleSubmit"> <form action="{{ url_for('applications.update_environment', environment_id=env['id']) }}" method="post" v-on:submit="handleSubmit">
{{ edit_form.csrf_token }} {{ edit_form.csrf_token }}
{{ TextInput(edit_form.name, validation='requiredField', optional=False) }} {{ TextInput(edit_form.name, validation='defaultStringField', optional=False) }}
{{ {{
SaveButton( SaveButton(
text=("common.save_changes" | translate) text=("common.save_changes" | translate)

View File

@ -119,8 +119,8 @@
{% macro InfoFields(member_form) %} {% macro InfoFields(member_form) %}
<div class="user-info"> <div class="user-info">
{{ TextInput(member_form.first_name, validation='requiredField', optional=False) }} {{ TextInput(member_form.first_name, validation='name', optional=False) }}
{{ TextInput(member_form.last_name, validation='requiredField', optional=False) }} {{ TextInput(member_form.last_name, validation='name', optional=False) }}
{{ TextInput(member_form.email, validation='email', optional=False) }} {{ TextInput(member_form.email, validation='email', optional=False) }}
{{ PhoneInput(member_form.phone_number, member_form.phone_ext)}} {{ PhoneInput(member_form.phone_number, member_form.phone_ext)}}
{{ TextInput(member_form.dod_id, validation='dodId', optional=False) }} {{ TextInput(member_form.dod_id, validation='dodId', optional=False) }}

View File

@ -26,14 +26,14 @@
{{ form.csrf_token }} {{ form.csrf_token }}
<div class="form-row"> <div class="form-row">
<div class="form-col"> <div class="form-col">
{{ TextInput(form.name, optional=False) }} {{ TextInput(form.name, validation="name", optional=False) }}
{{ ('portfolios.applications.new.step_1_form_help_text.name' | translate | safe) }} {{ ('portfolios.applications.new.step_1_form_help_text.name' | translate | safe) }}
</div> </div>
</div> </div>
<hr> <hr>
<div class="form-row"> <div class="form-row">
<div class="form-col form-col--two-thirds"> <div class="form-col form-col--two-thirds">
{{ TextInput(form.description, paragraph=True, optional=True) }} {{ TextInput(form.description, validation="defaultTextAreaField", paragraph=True, optional=True) }}
{{ ('portfolios.applications.new.step_1_form_help_text.description' | translate | safe) }} {{ ('portfolios.applications.new.step_1_form_help_text.description' | translate | safe) }}
</div> </div>
</div> </div>

View File

@ -22,8 +22,8 @@
<base-form inline-template> <base-form inline-template>
<form method="POST" action="{{ url_for('applications.update', application_id=application.id) }}" class="col col--half"> <form method="POST" action="{{ url_for('applications.update', application_id=application.id) }}" class="col col--half">
{{ application_form.csrf_token }} {{ application_form.csrf_token }}
{{ TextInput(application_form.name, optional=False) }} {{ TextInput(application_form.name, validation="name", optional=False) }}
{{ TextInput(application_form.description, paragraph=True, optional=True, showOptional=False) }} {{ TextInput(application_form.description, validation="defaultTextAreaField", paragraph=True, optional=True, showOptional=False) }}
<div class="action-group action-group--tight"> <div class="action-group action-group--tight">
{{ SaveButton(text='common.save_changes'|translate) }} {{ SaveButton(text='common.save_changes'|translate) }}
</div> </div>

View File

@ -41,7 +41,7 @@
<div class="form-row"> <div class="form-row">
<div class="form-col"> <div class="form-col">
{% if fields %} {% if fields %}
{{ TextInput(fields.number, optional=False) }} {{ TextInput(fields.number, validation='clinNumber', optional=False) }}
{% else %} {% else %}
<textinput :name="'clins-' + clinIndex + '-number'" inline-template> <textinput :name="'clins-' + clinIndex + '-number'" inline-template>
<div v-bind:class="['usa-input usa-input--validation--' + validation, { 'usa-input--error': showError, 'usa-input--success': showValid, 'usa-input--validation--paragraph': paragraph, 'no-max-width': noMaxWidth }]"> <div v-bind:class="['usa-input usa-input--validation--' + validation, { 'usa-input--error': showError, 'usa-input--success': showValid, 'usa-input--validation--paragraph': paragraph, 'no-max-width': noMaxWidth }]">

View File

@ -11,11 +11,11 @@
<div class='panel__content'> <div class='panel__content'>
<div class='form-row'> <div class='form-row'>
<div class='form-col form-col--half'> <div class='form-col form-col--half'>
{{ TextInput(form.first_name, validation='requiredField', optional=False) }} {{ TextInput(form.first_name, validation='name', optional=False) }}
</div> </div>
<div class='form-col form-col--half'> <div class='form-col form-col--half'>
{{ TextInput(form.last_name, validation='requiredField', optional=False) }} {{ TextInput(form.last_name, validation='name', optional=False) }}
</div> </div>
</div> </div>

View File

@ -20,7 +20,7 @@
<form method="POST" action="{{ url_for('portfolios.edit', portfolio_id=portfolio.id) }}" autocomplete="false"> <form method="POST" action="{{ url_for('portfolios.edit', portfolio_id=portfolio.id) }}" autocomplete="false">
{{ portfolio_form.csrf_token }} {{ portfolio_form.csrf_token }}
{{ TextInput(portfolio_form.name, validation="portfolioName", optional=False) }} {{ TextInput(portfolio_form.name, validation="portfolioName", optional=False) }}
{{ TextInput(portfolio_form.description, paragraph=True) }} {{ TextInput(portfolio_form.description, validation="defaultTextAreaField", paragraph=True) }}
<div class='edit-portfolio-name action-group'> <div class='edit-portfolio-name action-group'>
{{ SaveButton(text='Save Changes', additional_classes='usa-button-big') }} {{ SaveButton(text='Save Changes', additional_classes='usa-button-big') }}
</div> </div>

View File

@ -27,8 +27,8 @@
{% macro InfoFields(member_form) %} {% macro InfoFields(member_form) %}
<div class="user-info"> <div class="user-info">
{{ TextInput(member_form.first_name, validation='requiredField', optional=False) }} {{ TextInput(member_form.first_name, validation='name', optional=False) }}
{{ TextInput(member_form.last_name, validation='requiredField', optional=False) }} {{ TextInput(member_form.last_name, validation='name', optional=False) }}
{{ TextInput(member_form.email, validation='email', optional=False) }} {{ TextInput(member_form.email, validation='email', optional=False) }}
{{ PhoneInput(member_form.phone_number, member_form.phone_ext)}} {{ PhoneInput(member_form.phone_number, member_form.phone_ext)}}
{{ TextInput(member_form.dod_id, validation='dodId', optional=False) }} {{ TextInput(member_form.dod_id, validation='dodId', optional=False) }}

View File

@ -21,13 +21,13 @@
{{ form.csrf_token }} {{ form.csrf_token }}
<div class="form-row form-row--bordered"> <div class="form-row form-row--bordered">
<div class="form-col"> <div class="form-col">
{{ TextInput(form.name, optional=False, classes="form-col") }} {{ TextInput(form.name, validation="name", optional=False, classes="form-col") }}
{{"forms.portfolio.name.help_text" | translate | safe }} {{"forms.portfolio.name.help_text" | translate | safe }}
</div> </div>
</div> </div>
<div class="form-row form-row--bordered"> <div class="form-row form-row--bordered">
<div class="form-col"> <div class="form-col">
{{ TextInput(form.description, paragraph=True) }} {{ TextInput(form.description, validation="defaultTextAreaField", paragraph=True) }}
{{"forms.portfolio.description.help_text" | translate | safe }} {{"forms.portfolio.description.help_text" | translate | safe }}
</div> </div>
</div> </div>