Йо-йо! Сейчас (июнь 2019) я делаю небольшой сайт для бонусной системы одной известной сети кафе в своём городе. Т.к. все данные я получаю по API я решил сделать SPA на реакте.
У этой статьи появились «братья») Смотрите как валидировать данные в видео-формате: валидация формы регистрации, валидация файлов, валидация данных юридических лиц
Схема взаимодействия на сайте такая: пользователь авторизуется по номеру телефона и из API подтягиваются данные. В API я отправляю данные в формате 89999999999. То есть никаких +7, скобочек и т.д.
Конечно же встал вопрос как валидировать номер телефона. хотелось сделать всё просто и модно, выкачав что-то из npm. Сегодня я расскажу как решил данную задачу.
Код компонента с формой на примере моей страницы регистрации:
import React, { Component } from 'react'; class Page__REGISTER extends Component{ constructor(props){ super(props); this.state = { phone: '', password: '', isValidPhone: false, isValidPassword: false }; } render(){ return( <main> <h1>Регистрация</h1> <p>Введите ваши данные</p> <form method="POST"> <label>Ваш телефон</label><br /> <input id="name" name="phone" type="tel" /><br /> <label>Введите жалаемы пароль</label><br /> <input id="pass" name="pass" type="password" /><br /> <label>Подтвердите пароль</label><br /> <input id="pass_suc" name="pass_suc" type="password" /><br /> <button type="submit">Отправить</button></form> </main> ) } } export default Page__REGISTER;
Итак, у нас есть форма, там телефон и два поля для ввода пароля, их мы пока опустим. Сейчас нас интересует только номер телефона. Так же я создал state, в котором будет храниться логин, пароль и данные о валидности.
На отправку формы я назначу обработчик. В этом поможет синтетическое событие из react’а onSubmit. Для этого в тэге form добавит атрибут onSubmit={this.handlerSubmit}, а в state this.handlerSubmit = this.handlerSubmit.bind(this), ну и конечно же метод handlerSubmit в классе компонента.
Получится вот что:
import React, { Component } from 'react'; class Page__REGISTER extends Component{ constructor(props){ super(props); this.state = { phone: '', password: '', isValidPhone: false, isValidPassword: false }; this.handlerSubmit = this.handlerSubmit.bind(this); } handlerSubmit(event){ event.preventDefault(); } render(){ return( <main> <h1>Регистрация</h1> <p>Введите ваши даннык</p> <form method="POST" onSubmit={this.handlerSubmit}> <label>Ваш телефон</label><br /> <input id="name" name="phone" type="tel" /><br /> <label>Введите жалаемы пароль</label><br /> <input id="pass" name="pass" type="password" /><br /> <label>Подтвердите пароль</label><br /> <input id="pass_suc" name="pass_suc" type="password" /><br /> <button type="submit">Отправить</button></form> </main> ) } } export default Page__REGISTER;
Обратите внимание, что в метод handlerSubmit я передал событие и отменил действия по умолчанию.
Далее я буду описывать код handlerSybmit, чтобы не дублировать много кода.
handlerSubmit(event){ event.preventDefault(); const form = event.target; const inputsData = form.querySelectorAll('input'); const arrDataFromForm = {}; Array.from(inputsData).map((e)=>{ const name = e.name; const value = (name !== 'phone') ? e.value // Записываю пароли : e.value.replace(/\D/g, '').replace(/^7/, '8'); // Чищу номера телефона от лишних символов arrDataFromForm[name] = value; }); }
Что я сделал: взял форму из события, получил все input’ы, создал объект, в который буду собирать данные с помощью map(), прошёлся по input’ам, в мапе обрабатывал данные и записывал их в свой объект.
Так как мне нужно было отправлять номер телефона на сайт в определённом формате, я сразу отчистил его от +7 и других ненужных символов вот так:
e.value.replace(/\D/g, '').replace(/^7/, '8');
Первый replace удали все не числовые символы, а второй заменил первую 7 на 8. Такой подход позволяет пользователю вводить любой номер и не использовать тупые маски. Для конверсии и удобства это лучшее решение.
Наконец мы дошли до того ради чего я писал статью. Для того, чтобы проверить валиден номер телефона или нет, мы скачаем либу из npm. Библиотека называется validator, вот её страничка на npm.
Устанавливаем библиотеку:
npm i validator --save
Импортируем в наш компонент:
import validator from 'validator';
Когда мы прошли предыдущие шаги пора изменить наш компонент. Для валидации нам понадобиться метод validator.isMobilePhone(numbel, arr(local)). В этот метод мы передаём номер телефона и локаль относительно которой мы проверяем наш номер телефона. Например, в России номера начинаются с +7 или 8 и если в методе мы передадим локаль ru-RU, то валидатор проверит начинается номер именно с этих чисел или нет, а так же других правил записи русских номеров телефона.
После преобразований у меня получился следующий компонент:
import React, { Component } from 'react'; class Page__REGISTER extends Component{ constructor(props){ super(props); this.state = { phone: '', password: '', isValidPhone: false, isValidPassword: false }; this.handlerSubmit = this.handlerSubmit.bind(this); // Создаю ref, чтобы было удобно работать с input'ом this.inputNameRef = React.createRef(); } handlerSubmit(event){ event.preventDefault(); const form = event.target; const inputsData = form.querySelectorAll('input'); const arrDataFromForm = {}; Array.from(inputsData).map((e)=>{ const name = e.name; const value = (name !== 'phone') ? e.value // Записываю пароли : e.value.replace(/\D/g, '').replace(/^7/, '8'); // Чищу номера телефона от лишних символов arrDataFromForm[name] = value; }); // Проверка номера на валидность if(validator.isMobilePhone(arrDataFromForm["phone"], ['ru-RU'])){ // Изменил state this.setState({ isValidPhone:true, phone: arrDataFromForm["phone"] }); } else { // Предупреждаю, что номер неверный alert('Неверный номер телефона'); // Подсвечиваю input с номером телефона для удобства this.inputNameRef.current.focus(); } } render(){ return( <main> <h1>Регистрация</h1> <p>Введите ваши даннык</p> <form method="POST" onSubmit={this.handlerSubmit}> <label>Ваш телефон</label><br /> {// Создаю ref для input'а} <input ref={this.inputNameRef} id="name" name="phone" type="tel" /><br /> <label>Введите жалаемы пароль</label><br /> <input id="pass" name="pass" type="password" /><br /> <label>Подтвердите пароль</label><br /> <input id="pass_suc" name="pass_suc" type="password" /><br /> <button type="submit">Отправить</button></form> </main> ) } } export default Page__REGISTER;
Обратите внимание, что я создал ref для удобного обращения к input’у
В данном модуле есть очень много разных проверок, например, является ли строка base64 или нет, является ли строка email’ом, json’ом и многое другое. А также в нём есть несколько методов отчистки строк от всякого шлака.