Svelte — each block — группировка и сохранение данных

Admin Svelte

Пример работы bind:value на основе each блока.

Код ниже:
— формирует таблицу через each из данных, которые приходят с бэкенда;
— сохраняет введенные данные из input и отправляет их на бэк.

В данном коде реализация только фронта, демонстрирует работу svelte. То что происходит на бэкенде, здесь не важно и приводится для иллюстрации.

1. Блок JS

Здесь есть важный момент. Нам обязательно надо сложить полученные данные через onMount. В ином случае svelte не будет работать с bind, когда нам надо будет сохранить данные тем способом, который приведен ниже.

Получаем данные с бэкенда:

<script>
    import {onMount} from "svelte";
    import {getFetchOther} from '../../main';

    let settings = [];
    onMount(async () => {
        getFetch('settings/get-user-timers/').then((r) => {settings = r});
    });

Функция сохранения, которая будет срабатывать автоматически при каждом вводе данных в инпут:

<script>
    function changeValue(setting) {
        getFetchOther('settings/save_user_timer/' + setting.name + '/' + setting.timer + '/' + setting.percent);
    }
</script>

2. Блок Svelte

Здесь выводится таблица из данных в переменной settings.

Конструкция on:change={changeValue(setting)}, при изменении содержимого input отправляет данные в функцию changeValue (выше). Она, в свою очередь, отправляет данные для сохранения на бэкенд.

Теги input можно заменить на textarea.

<div class="table table-links">
    <div class="header">
        <div class="cell title name">Название</div>
        <div class="cell title timer">Таймер (в мин)</div>
        <div class="cell title percent">Коофициент в %</div>
    </div>
    <div class="body">
        {#each settings as setting, i}
            <div class="item">
                <div class="cell name">{setting.name}</div>
                <div class="cell timer">
                    <input type="text" bind:value="{setting.timer}" on:change={changeValue(setting)}>
                </div>
                <div class="cell percent">
                    <input type="text" bind:value="{setting.percent}" on:change={changeValue(setting)}>
                </div>
            </div>
        {/each}
    </div>
</div>

3. Svelte + contenteditable

Этот вариант мне нравится больше всего. Не нужны никакие input или textarea. Можно прямо в блоке div редактировать данные и сохранять их.

on:change в этом случае меняется на on:input и bind:value меняется на bind:innerHTM.

<div
    class="cell description edit"
    contenteditable="true"
    bind:innerHTML="{budget.description}"
    on:input="{saveUsersData(budget)}"
    on:paste="{handlePaste}"
    on:keydown="{handleKeydown}"
></div>

Убираем теги в contenteditable при вставке из буфера обмена

Для того чтобы в contenteditable из буфера обмена не генерировались и не вставлялись лишние теги добавим функцию:

function handlePaste(e) {
    e.preventDefault();

    // Получаем из буфера обмена данные в виде простого текста
    var text = (e.originalEvent || e).clipboardData.getData('text/plain');

    // Осуществляем вставку самостоятельно
    document.execCommand("insertHTML", false, text);
}

На js это было бы так:

document.addEventListener("paste", function (e) {
    // Отменяем вставку
    e.preventDefault();

    // Получаем из буфера обмена данные в виде простого текста
    var text = (e.originalEvent || e).clipboardData.getData('text/plain');

    // Осуществляем вставку самостоятельно
    document.execCommand("insertHTML", false, text);
});

Убираем вставку DIV по клавише Enter из contenteditable

function handleKeydown(e) {
    if (e.key === 'Enter') {
        e.preventDefault();
        document.execCommand('insertHTML', false, '<br><br>');
    }
}

Если вам пригодилась информация, вы можете поблагодарить автора сайта символическим пожертвованием:

Добавить комментарий

Напишите свой комментарий, если вам есть что добавить/поправить/спросить по теме текущей статьи:
"Svelte — each block — группировка и сохранение данных"