Как я могу иметь атрибут ‹input type =…, который изменяется в зависимости от экземпляров компонента Svelte, имея свое значение в системе реактивности?

У меня есть компонент FormRow, который выглядит примерно так (информация о стиле и макете, поэтому мне нужен компонент, здесь для краткости удалена):

<script>
  export let label;
  export let type;
  export let value;
</script>
<input type={type} bind:value={value}>

и используется он так:

<FormRow title="Email: " type="email" value={email}/>
<FormRow title="Username:"  type="text" value={username}/>
<FormRow title="Password: " type="password" value={password}/>
<FormRow title="Confirm Password: " type="password" value={confirmPassword}/>

с намерением получить доступ к переменным электронной почты, имени пользователя, пароля и confirmPassword в JS при отправке формы и, возможно, использовать реактивность для добавления проверки ввода (в дополнение к проверке на стороне сервера, конечно). Но когда я пытаюсь скомпилировать это, я получаю такую ​​ошибку:

ERROR in ./src/pages/_components/FormRow.svelte
Module build failed (from ./node_modules/svelte-loader/index.js):
Error: ValidationError: 'type' attribute cannot be dynamic if input uses two-way binding (31:22)
29:         {title}
30:     </label>
31:     <input id="input" type={type} bind:value={value}>

Я думаю, что понимаю, в чем проблема (тип и значение не могут быть одновременно установлены через систему реактивности), но я не вижу, как выполнить то, что я хочу (многоразовый и универсальный компонент FormRow). Я подумал, что может быть какой-то другой способ установить атрибут типа для каждого экземпляра FormRow, поскольку мне не нужно, чтобы он изменялся во время выполнения для какого-либо конкретного экземпляра, но я не смог найти какой-либо метод, чтобы он варьировался для каждого экземпляра. компонентная база, подобная этой в документации Svelte.


person john01dav    schedule 14.02.2021    source источник


Ответы (1)


В зависимости от типа ввода Svelte будет использовать другой прослушиватель событий при привязке к элементу. Например, bind:value на <input type="text"> слушает событие ввода на предмет обновлений, а bind:checked на <input type="checkbox"> слушает событие изменения. Svelte необходимо знать, к какому типу относится вход во время компиляции, чтобы сгенерировать эти слушатели, поэтому он не позволяет атрибуту типа быть динамическим, когда вы используете двустороннюю привязку.

Если вам нужен динамический тип ввода, вам нужно будет самостоятельно сгенерировать слушателей для обновления значения. Предполагая, что вы будете использовать только те типы, которые отправляют событие input при обновлении их value, вы можете сделать следующее:

<!-- FormRow.svelte -->
<script>
    export let label;
    export let type;
    export let value = '';
    
    function handleInput(e) {
        value = e.target.value;
    }
</script>
<label><input type={type} value={value} on:input={handleInput}> {label}</label>

<!-- App.svelte -->
<script>
    import FormRow from './FormRow.svelte';
    let value = 'hello';    
</script>

<p>
    Current value: {value}
</p>
<FormRow label="test" type="text" bind:value={value} />
person Geoff Rich    schedule 14.02.2021
comment
У меня есть этот метод, реализованный в моей базе кода, но когда входной тег инициализируется, переменная value устанавливается в значение undefined. Добавить пустую строку по умолчанию несложно, но как насчет того, когда клиент загружает значение во входные данные (например, сохраненный пароль)? - person john01dav; 17.02.2021
comment
Неопределенный случай - хорошая находка, я добавлю к ответу пустую строку по умолчанию. Связанное значение все еще кажется обновляется, когда клиент вводит значение - я даже попытался загрузить сохраненный пароль из моего диспетчера паролей. Вы видите другое поведение? - person Geoff Rich; 17.02.2021
comment
Я не думаю, что поведение в каком-то одном браузере будет достаточным. Меня беспокоит, гарантируют ли веб-стандарты, что они будут генерировать событие изменения при каждом автозаполнении. Если стандарта нет, то полагаться на него кажется рискованным, поскольку он может произвольно измениться в браузере или другой браузер может сделать это по-другому. - person john01dav; 18.02.2021