CSR-254: add generic textInput component and add validation on form-test
This commit is contained in:
parent
549a8b3593
commit
42d2d6334b
4 changed files with 147 additions and 9 deletions
38
src/common-components/text-input/text-input.spec.js
Normal file
38
src/common-components/text-input/text-input.spec.js
Normal file
|
|
@ -0,0 +1,38 @@
|
|||
import { shallowMount } from "@vue/test-utils";
|
||||
import textInput from "./text-input";
|
||||
|
||||
describe("text-input.vue", () => {
|
||||
|
||||
it("Should render a text input", async () => {
|
||||
// Act
|
||||
const wrapper = shallowMount(textInput, {
|
||||
propsData: {
|
||||
name: "test",
|
||||
label: "unit test label",
|
||||
},
|
||||
});
|
||||
|
||||
// Assert
|
||||
const input = wrapper.find("input");
|
||||
|
||||
expect(input.exists()).toBe(true);
|
||||
});
|
||||
|
||||
it("Should return aria-required state", async () => {
|
||||
// Act
|
||||
const wrapper = shallowMount(textInput, {
|
||||
propsData: {
|
||||
name: "test",
|
||||
label: "unit test label",
|
||||
isRequired: true
|
||||
},
|
||||
});
|
||||
|
||||
// Assert
|
||||
const input = wrapper.find("input");
|
||||
|
||||
expect(input.attributes()["aria-required"]).toEqual("true");
|
||||
|
||||
});
|
||||
|
||||
});
|
||||
70
src/common-components/text-input/text-input.vue
Normal file
70
src/common-components/text-input/text-input.vue
Normal file
|
|
@ -0,0 +1,70 @@
|
|||
<!-- Simple implementation of an input field -->
|
||||
<template>
|
||||
<div class="d-flex w-50 mb-2">
|
||||
<input
|
||||
type="text"
|
||||
:name="name"
|
||||
:value="inputValue"
|
||||
:id="name"
|
||||
:aria-required="isRequired"
|
||||
@input="handleChange"
|
||||
@blur="handleBlur"
|
||||
/>
|
||||
<label
|
||||
:for="name"
|
||||
:aria-labelledby="name"
|
||||
class="d-flex justify-content-center py-3 px-4"
|
||||
>
|
||||
<span class="m-0">{{label}}</span>
|
||||
</label>
|
||||
</div>
|
||||
<div v-show="errorMessage" class="row px-3 form-test-error">
|
||||
{{ errorMessage }}
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import { useField } from 'vee-validate';
|
||||
|
||||
export default {
|
||||
name: "textInput",
|
||||
props: {
|
||||
type: {
|
||||
type: String,
|
||||
default: "text",
|
||||
},
|
||||
value: {
|
||||
type: String,
|
||||
default: "",
|
||||
},
|
||||
name: {
|
||||
type: String,
|
||||
required: true,
|
||||
},
|
||||
label: {
|
||||
type: String,
|
||||
required: true,
|
||||
},
|
||||
isRequired: Boolean,
|
||||
},
|
||||
setup(props) {
|
||||
const {
|
||||
value: inputValue,
|
||||
errorMessage,
|
||||
handleBlur,
|
||||
handleChange,
|
||||
meta,
|
||||
} = useField(props.name, undefined, {
|
||||
initialValue: props.value,
|
||||
});
|
||||
|
||||
return {
|
||||
handleChange,
|
||||
handleBlur,
|
||||
errorMessage,
|
||||
inputValue,
|
||||
meta,
|
||||
};
|
||||
},
|
||||
};
|
||||
</script>
|
||||
|
|
@ -1,8 +1,8 @@
|
|||
<template>
|
||||
<Form :validation-schema="schema" @submit="onSubmit" v-slot="{values}">
|
||||
<div class="row px-3">
|
||||
<div class="row px-3 mt-4">
|
||||
<!-- The role="radiogroup" and aria-labelledby must be included in the parent component for the group -->
|
||||
<h6 class="mx-2 my-0">How many chips are we repairing?</h6>
|
||||
<h3 class="mx-2 mt-4 mb-0">How many chips are we repairing?</h3>
|
||||
<div role="radiogroup" aria-labelledby="demo-group" class="d-flex flex-row p-0">
|
||||
<!-- The h3 and id must be included. The id must match the aria-labelledby of the parent div. -->
|
||||
<h3 class="sr-only" id="demo-group">
|
||||
|
|
@ -51,14 +51,14 @@
|
|||
screenReaderOnlyText=" opens new window"
|
||||
/>
|
||||
</div>
|
||||
<div class="row px-3">
|
||||
<div class="row px-3 form-test-error">
|
||||
<error-message name="demo"></error-message>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="row g-2">
|
||||
<div class="row g-2 mt-4">
|
||||
<div class="col">
|
||||
<h6 class="mx-2 my-4">Which windshield part needs fixed?</h6>
|
||||
<h3 class="mx-2 mt-4 mb-0">Which windshield part needs fixed?</h3>
|
||||
<fieldset>
|
||||
<legend class="sr-only">Which windshield part needs fixed?</legend>
|
||||
<listCard
|
||||
|
|
@ -90,12 +90,25 @@
|
|||
/>
|
||||
</fieldset>
|
||||
</div>
|
||||
<div class="row px-3">
|
||||
<div class="row px-3 form-test-error">
|
||||
<error-message name="demo2"></error-message>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="row g-2 mt-4">
|
||||
<div class="col">
|
||||
<h3 class="mx-2 mt-4 mb-0">Enter your VIN</h3>
|
||||
<textInput
|
||||
name="demo3"
|
||||
type="text"
|
||||
label="VIN (Required)"
|
||||
:isRequired="true"
|
||||
/>
|
||||
</div>
|
||||
<!-- Here, the error block is included in the component level textInput -->
|
||||
</div>
|
||||
|
||||
<div class="g-2 mx-2 my-4">
|
||||
<div class="g-2 mx-2 mt-6">
|
||||
<button>Get your estimate</button>
|
||||
<p>Values</p>
|
||||
<pre>{{ values }}</pre>
|
||||
|
|
@ -113,12 +126,15 @@ import buttonPrimary from "@/ux-components/button-primary/button-primary";
|
|||
import buttonSecondary from "@/ux-components/button-secondary/button-secondary";
|
||||
import buttonBack from "@/common-components/button-back/button-back";
|
||||
import listCard from "@/ux-components/list-card/list-card";
|
||||
import textInput from "@/common-components/text-input/text-input";
|
||||
import listButton from "@/ux-components/list-button/list-button";
|
||||
import alert from "@/ux-components/alert/alert";
|
||||
import vehicleBanner from "@/common-components/vehicle-banner/vehicle-banner";
|
||||
import funnelHeader from "@/common-components/funnel-header/funnel-header";
|
||||
import listButtonHorizontal from "@/ux-components/list-button-horizontal/list-button-horizontal";
|
||||
import checkbox from "@/ux-components/checkbox/checkbox";
|
||||
import { useField } from 'vee-validate';
|
||||
|
||||
export default {
|
||||
name: "App",
|
||||
data() {
|
||||
|
|
@ -135,7 +151,13 @@ export default {
|
|||
return true;
|
||||
}
|
||||
return 'Please select a windshield part';
|
||||
}
|
||||
},
|
||||
demo3: (value) => {
|
||||
if (value && value.length > 0) {
|
||||
return true;
|
||||
}
|
||||
return 'Invalid VIN. Please enter X, Y, Z...';
|
||||
},
|
||||
}
|
||||
}
|
||||
},
|
||||
|
|
@ -148,6 +170,7 @@ export default {
|
|||
// alert,
|
||||
// vehicleBanner,
|
||||
listButtonHorizontal,
|
||||
textInput,
|
||||
Form,
|
||||
ErrorMessage,
|
||||
// checkbox,
|
||||
|
|
@ -160,3 +183,10 @@ export default {
|
|||
},
|
||||
};
|
||||
</script>
|
||||
|
||||
<style lang="scss">
|
||||
.form-test-error {
|
||||
color: red;
|
||||
font-weight: bold;
|
||||
}
|
||||
</style>
|
||||
|
|
@ -22,7 +22,7 @@
|
|||
<span class="m-0" :class="[this.textPosition]">{{buttonID}}</span>
|
||||
<span v-if="buttonLabelSubCopy" class="m-0 small" :class="[this.textPosition]">{{buttonLabelSubCopy}}</span>
|
||||
<span v-if="screenReaderOnlyText" class="sr-only">{{screenReaderOnlyText}}</span>
|
||||
</label>
|
||||
</label>
|
||||
</div>
|
||||
<div v-else class="col list-group list-button-horizontal d-flex flex-column mb-2">
|
||||
<input
|
||||
|
|
|
|||
Loading…
Reference in a new issue