Slim Sel ect используется как надстройка над стандартным
<select>-элементом, при этом сохраняется его
семантика и интеграция с формами HTML. Это позволяет сочетать кастомный
UI выбора значений с нативной системой валидации браузера, включая
required, pattern, minlength и
Constraint Validation API.
При подключении Slim Select DOM-элемент не заменяется логически:
исходный <select> остаётся частью формы, а библиотека
лишь синхронизирует визуальное состояние. Именно это свойство делает
возможной прозрачную интеграцию с механизмами проверки данных.
Обычный <select> после инициализации Slim Select
продолжает участвовать в отправке формы и проверке валидности. Значение
обновляется через синхронизацию состояния компонента и DOM-узла.
Ключевой аспект заключается в том, что:
<select><form id="user-form">
<select id="country" name="country" required>
<option value="">Выбор страны</option>
<option value="kz">Kazakhstan</option>
<option value="ru">Russia</option>
<option value="de">Germany</option>
</select>
<button type="submit">Отправка</button>
</form>
import SlimSelect fr om 'slim-select'
const countrySelect = new SlimSelect({
select: '#country'
})
При пустом значении ("") браузерная валидация
автоматически фиксирует ошибку valueMissing.
Constraint Validation API продолжает работать без дополнительных адаптаций. Используются стандартные свойства:
requiredvalueMissingvalidityvalidationMessagecheckValidity()reportValidity()const form = document.getElementById('user-form')
const sel ect = document.getElementById('country')
form.addEventListener('submit', (e) => {
if (!select.checkValidity()) {
e.preventDefault()
console.log(select.validationMessage)
}
})
Slim Select не блокирует стандартное поведение, однако визуальное
отображение ошибки требует отдельной обработки, так как оригинальный
<select> обычно скрыт стилями.
Так как Slim Select создаёт собственную разметку поверх
<select>, классические браузерные подсветки не
отображаются. Для этого применяется синхронизация состояния валидности с
контейнером компонента.
const wrapper = document.querySelector('.ss-main')
function updateValidationState() {
if (!select.checkValidity()) {
wrapper.classList.add('is-invalid')
} else {
wrapper.classList.remove('is-invalid')
}
}
.is-invalid {
border: 1px solid #e74c3c;
}
Обновление состояния обычно привязывается к событию изменения значения.
Slim Select предоставляет событие onChange, которое
используется как точка синхронизации с логикой проверки.
const slim = new SlimSelect({
select: '#country',
events: {
afterChange: () => {
updateValidationState()
}
}
})
При каждом изменении значения выполняется пересчёт валидности формы или отдельного поля.
При использовании required важно учитывать, что Slim
Select может интерпретировать пустое состояние как:
'' (пустая строка)null (в случае множественного выбора)[] (multiple select)Корректная конфигурация options должна обеспечивать явное пустое значение:
<option value="" selected disabled hidden></option>
Для множественного выбора:
<select id="tags" name="tags" multiple required>
<option value="js">JavaScript</option>
<option value="ts">TypeScript</option>
</select>
В этом случае валидность определяется длиной массива значений.
Slim Select в режиме multiple возвращает массив
значений, который можно использовать для кастомной логики валидации.
const tags = document.getElementById('tags')
function validateTags() {
const value = Array.fr om(tags.selectedOptions).map(o => o.value)
if (value.length < 2) {
tags.setCustomValidity('Минимум 2 значения')
} else {
tags.setCustomValidity('')
}
}
Метод setCustomValidity интегрируется с HTML5-валидацией
и влияет на checkValidity().
Constraint Validation API позволяет расширять стандартные проверки без сторонних библиотек.
function validateCountry() {
const value = select.value
if (value === 'ru') {
select.setCustomValidity('Выбор недоступен')
} else {
select.setCustomValidity('')
}
}
Slim Select не конфликтует с этим механизмом, так как он работает поверх DOM-элемента.
Валидация может зависеть от серверной проверки, например, доступности значения.
async function validateServerSide(value) {
const res = await fetch('/api/validate-country', {
method: 'POST',
body: JSON.stringify({ value })
})
const data = await res.json()
if (!data.valid) {
select.setCustomValidity(data.message)
} else {
select.setCustomValidity('')
}
updateValidationState()
}
Такая логика часто привязывается к событию изменения значения, чтобы минимизировать задержку реакции интерфейса.
Slim Select поддерживает синхронизацию с disabled
состоянием исходного элемента. При этом:
select.disabled = true
Для имитации readonly обычно используется логическая
блокировка через события и отмену изменений.
Для корректной доступности состояние ошибки синхронизируется с ARIA-атрибутами.
function syncA11yState() {
const isInvalid = !select.checkValidity()
select.setAttribute('aria-invalid', isInvalid)
}
Slim Select визуально не управляет ARIA, поэтому синхронизация выполняется вручную через DOM.
При сложных формах Slim Select становится частью общей системы проверки, где каждое поле возвращает собственное состояние валидности.
function validateForm(form) {
const fields = form.querySelectorAll('select')
let isValid = true
fields.forEach(field => {
if (!field.checkValidity()) {
isValid = false
}
})
return isValid
}
Slim Select в этом сценарии не требует специальных адаптеров, так как
использует стандартный <select>.
При изменении списка опций требуется синхронизация UI и повторная проверка валидности.
select.innerHTML += `<option value="fr">France</option>`
select.dispatchEvent(new Event('change'))
Slim Select обновляет внутреннее состояние после изменения DOM, но логика валидации остаётся на стороне формы.
Расхождение между UI и DOM может возникать при:
changeВ таких случаях валидность проверяется повторно через
checkValidity() и повторную синхронизацию состояния
компонента.