1 | <template>
|
2 | <form @submit.prevent="send"
|
3 | v-form="contactForm"
|
4 | class="borderRadius25 marginRightAuto marginLeftAuto displayFlex
|
5 | bgWhisper">
|
6 |
|
7 | <div class="flex1 padding30">
|
8 |
|
9 |
|
10 | <div class="marginBottom30 widthTwelve">
|
11 |
|
12 | <div class="marginBottom10">
|
13 | <label for="name" class="colorMidGray fontSize14">
|
14 | Your name
|
15 | </label>
|
16 | </div>
|
17 |
|
18 | <input id="name"
|
19 | type="text"
|
20 | class="inputText widthTwelve"
|
21 | v-model="contactData.name"
|
22 | pattern="[A-Za-z\s'\-]+"
|
23 | minlength="3"
|
24 | required>
|
25 |
|
26 | <div v-if="contactForm.$wasSubmitted"
|
27 | class="marginTop12 widthTwelve colorRed fontSize14">
|
28 | <div v-if="contactForm.name.valueMissing">
|
29 | Name is required.
|
30 | </div>
|
31 | <div v-if="contactForm.name.tooShort">
|
32 | Please enter your first and last name.
|
33 | </div>
|
34 | <div v-if="contactForm.name.patternMismatch">
|
35 | Please use only letters, spaces, dashes, and apostrophes.
|
36 | </div>
|
37 | </div>
|
38 |
|
39 | </div>
|
40 |
|
41 |
|
42 | <div class="marginBottom30 widthTwelve">
|
43 |
|
44 | <div class="marginBottom10">
|
45 | <label for="email" class="colorMidGray fontSize14">
|
46 | Your email address
|
47 | </label>
|
48 | </div>
|
49 |
|
50 | <input id="email"
|
51 | type="email"
|
52 | class="inputText widthTwelve"
|
53 | v-model="contactData.email"
|
54 | required>
|
55 |
|
56 | <div v-if="contactForm.$wasSubmitted"
|
57 | class="marginTop12 widthTwelve colorRed fontSize14">
|
58 | <div v-if="contactForm.email.valueMissing">
|
59 | Email is required.
|
60 | </div>
|
61 | <div v-if="contactForm.email.typeMismatch">
|
62 | Please enter a valid email address.
|
63 | </div>
|
64 | </div>
|
65 |
|
66 | </div>
|
67 |
|
68 |
|
69 | <div class="marginBottom30 widthTwelve">
|
70 |
|
71 | <div class="marginBottom10">
|
72 | <label for="phone" class="colorMidGray fontSize14">
|
73 | Your phone number
|
74 | </label>
|
75 | </div>
|
76 |
|
77 | <input id="phone"
|
78 | type="text"
|
79 | class="inputText widthTwelve"
|
80 | v-model="contactData.phone"
|
81 | pattern="^(\+\d{1,2}\s)?\(?\d{3}\)?[\s.-]?\d{3}[\s.-]?\d{4}$"
|
82 | required>
|
83 |
|
84 | <div v-if="contactForm.$wasSubmitted"
|
85 | class="marginTop12 widthTwelve colorRed fontSize14">
|
86 | <div v-if="contactForm.phone.valueMissing">
|
87 | Phone is required.
|
88 | </div>
|
89 | <div v-if="contactForm.phone.patternMismatch">
|
90 | Please use only numbers, spaces, dashes, and parenthesis.
|
91 | </div>
|
92 | </div>
|
93 |
|
94 | </div>
|
95 |
|
96 |
|
97 | <div class="widthTwelve">
|
98 |
|
99 | <div class="marginBottom10">
|
100 | <label for="project" class="colorMidGray fontSize14">
|
101 | Your company/project name
|
102 | </label>
|
103 | </div>
|
104 |
|
105 | <input id="project"
|
106 | type="text"
|
107 | class="inputText widthTwelve"
|
108 | v-model="contactData.project">
|
109 |
|
110 | </div>
|
111 |
|
112 | </div>
|
113 |
|
114 | <div class="flex1 padding30">
|
115 |
|
116 |
|
117 | <div class="marginBottom30">
|
118 |
|
119 | <div class="marginBottom10">
|
120 | <label for="description" class="colorMidGray fontSize14">
|
121 | How can we help you?
|
122 | </label>
|
123 | </div>
|
124 |
|
125 | <textarea id="description"
|
126 | class="textArea widthTwelve resizeVertical"
|
127 | rows="13"
|
128 | @input="hasOneWordValidator"
|
129 | v-model="contactData.description"
|
130 | required>
|
131 | </textarea>
|
132 |
|
133 | <div v-if="contactForm.$wasSubmitted"
|
134 | class="marginTop12 widthTwelve colorRed fontSize14">
|
135 | <div v-if="contactForm.description.valueMissing">
|
136 | Description is required.
|
137 | </div>
|
138 | <div v-if="contactForm.description.customError">
|
139 | {{ contactForm.description.customMessage }}
|
140 | </div>
|
141 | </div>
|
142 |
|
143 | </div>
|
144 |
|
145 |
|
146 | <transition name="fade">
|
147 | <div v-if="formSent" class="colorOlive fontSize18 textCenter">
|
148 | Thanks! We'll be in touch soon.
|
149 | </div>
|
150 | </transition>
|
151 |
|
152 |
|
153 | <div v-if="!formSent" class="textRight fontSize20">
|
154 |
|
155 |
|
156 | <button type="reset"
|
157 | class="button circular width140 height50 marginRight30 bgGray">
|
158 | <span class="verticalMiddle">Reset</span>
|
159 | <reset-icon></reset-icon>
|
160 | </button>
|
161 |
|
162 |
|
163 | <button type="submit"
|
164 | class="button circular width140 height50"
|
165 | :class="{ 'disabled': contactForm.$isInvalid }">
|
166 | <span class="verticalMiddle">Send</span>
|
167 | <plane-icon></plane-icon>
|
168 | </button>
|
169 |
|
170 | </div>
|
171 |
|
172 | </div>
|
173 |
|
174 | </form>
|
175 | </template>
|
176 |
|
177 | <script>
|
178 | import VueForm from '../../dist/vueform'
|
179 | import ResetIcon from './ResetIcon'
|
180 | import PlaneIcon from './PlaneIcon'
|
181 |
|
182 | export default {
|
183 | name: 'ContactForm',
|
184 | components: { ResetIcon, PlaneIcon },
|
185 | data () {
|
186 | return {
|
187 | formSent: false,
|
188 | contactData: {},
|
189 | contactForm: new VueForm()
|
190 | }
|
191 | },
|
192 | methods: {
|
193 | send () {
|
194 | if (this.contactForm.$isValid) {
|
195 | console.log('VALID')
|
196 | this.formSent = true
|
197 | } else {
|
198 | console.log('INVALID')
|
199 | }
|
200 | },
|
201 | hasOneWordValidator ({ target }) {
|
202 | const id = target.getAttribute('id')
|
203 | if (target.value.match(/\w+/)) {
|
204 | this.contactForm.$setCustomValidity(id)
|
205 | } else {
|
206 | const errorMessage = 'Description must contain at least one word.'
|
207 | this.contactForm.$setCustomValidity(id, errorMessage)
|
208 | }
|
209 | }
|
210 | }
|
211 | }
|
212 | </script>
|