Javascript-форум (https://javascript.ru/forum/)
-   jQuery (https://javascript.ru/forum/jquery/)
-   -   Изменение данных в таблице (https://javascript.ru/forum/jquery/80581-izmenenie-dannykh-v-tablice.html)

savsoft 25.06.2020 03:43

Изменение данных в таблице
 
Всем привет. Есть таблица, которую формирует php скрипт. В каждой строке есть кнопка изменить, по которой открывается форма для изменения данных. Возникла необходимость исправить данные в таблице, точнее изменить данные в 1-ой или 2-х колонках. Клиент не хочет изменять каждую строку отдельно, а хочет исправить значения прямо в таблице. Добавлять форму на таблицу и обрабатывать на php как-то не очень красиво получается. Решил изменять данные, через jquery удалять класс (original) и добавлять класс (edited). Потом по нажатию кнопки через ajax запрос обновлять данные в базе и менять класс назад. Вроде работает. Вот код

<script>
		$(function() {
			$(".matname").change(function(){
				$(this).removeClass("original");
				$(this).addClass("edited");
			}); 				
		});		
	</script>

	<script>
		$(function() {
			$("#saveedited").click(function(){
				$.each($('.edited'), function(index, item) { 
					
					// Здесь пишем в базу
					
					$('#' + item.id).addClass("original");
					$('#' + item.id).removeClass("edited");
				});
			});
		});		
	</script>


Так использовать проблем не будет или есть какой более правильный способ?

laimas 25.06.2020 05:28

Цитата:

Сообщение от savsoft
Клиент не хочет изменять каждую строку отдельно, а хочет исправить значения прямо в таблице.

А какой смысл клиент вкладывает в понятие "изменять"? Если это на клиенте потренироваться и забыть, на здоровье (причем тут правда стили), а если это изменение данных, то как без формы?

savsoft 25.06.2020 12:58

Цитата:

Сообщение от laimas (Сообщение 526376)
А какой смысл клиент вкладывает в понятие "изменять"? Если это на клиенте потренироваться и забыть, на здоровье (причем тут правда стили), а если это изменение данных, то как без формы?

Есть тысячи материалов, которые имеют название. Они выводятся в таблицу, где их можно фильтровать разными способами. Когда запускали приложение, названия вводили, мягко говоря, разнообразно. Теперь решили привести в порядок. Вот, например отфильтровали группу материалов, штук 20. И нужно им всем изменить только название и иногда номер по порядку. Значит нужно 20 раз войти в форму, изменить название, сохранить. А можно прямо в таблице, сделать поле input (textarea) для названия и сразу по месту изменять. Записи, которые изменены, но не сохранены, как-то выделять, например красным. Давая отдельный класс. Потом, по нажатию кнопки, пройти по всем измененным, но не сохраненным записям - записям с этим отдельным классом и через ajax записать в базу, и убрать выделение.

laimas 25.06.2020 13:50

Можно было долго не рассказывать. Если таблица строится на базе данных сервера из базы, а "изменения", это обновление их в базе, то это все равно форма или по крайней мере ее элементы. Хотя можно конечно и заморачиваться, собирая данные скриптом. То есть два пути:

1) Таблица с элементами ввода это форма. Можно любые изменения вносить в любых ее строках. Каждая строка может иметь кнопку Удалить для этой записи в БД. Форма имеет одну кнопку Обновить. Серверу отправляется форма и он производит обновление записей в базе. Изменить только название и номер, это для базы мелочь, даже если это тысячи записей. разукрашивать для этого ячейки не нужно, отдаете все данные для UPDATE. И потом, что значит изменить - держать образ данных отдельно как объект, а при действиях в таблице сравнивать с ним, отмечая в ней неравные? Только так можно знать изменилось или нет. Тогда скриптом собрать все поля из таблицы, значения которых не равны им в объекте и отправить все на сервер.

2) Те же самые элементы формы а кнопки Обновить/Удалить для каждой строки. Серверу отправляются данные только конкретной записи, которая обновляется/удаляется.

Я не представляю человека, который бы не допустил ошибки работая с большим объемом табличных данных. Обычно их выводят либо постранично, либо по фильтру, что сокращает вероятность ошибок.

laimas 25.06.2020 14:53

.change {
    background-color: #FFA5A5;
}


<table id="data">
<tr><td><input data-val="abcd" name="data[11][name]" value="abcd" /></td><td><input data-val="5" name="data[11][range]" value="5" /></td></tr>
<tr><td><input data-val="qwer" name="data[22][name]" value="qwer" /></td><td><input data-val="8" name="data[22][range]" value="8" /></td></tr>
</table>
<button id="send">Update</button>


var tbl = $('#data').on('input', 'input', function() {
    this.classList.toggle('change', this.dataset.val != this.value.trim())
});

$('#send').click(function() {
    var o = tbl.find('input.change');
    if(o.length) {
        o = o.map(function() {
            return {[this.name]: this.value}
        })
        console.log(o)
        //$.ajax()
    }
});


Примерно так, если сравнивать и отправлять только измененные.

savsoft 25.06.2020 14:56

Цитата:

Сообщение от laimas (Сообщение 526402)
Можно было долго не рассказывать. Если таблица строится на базе данных сервера из базы, а "изменения", это обновление их в базе, то это все равно форма или по крайней мере ее элементы. Хотя можно конечно и заморачиваться, собирая данные скриптом. То есть два пути:

1) Таблица с элементами ввода это форма. Можно любые изменения вносить в любых ее строках. Каждая строка может иметь кнопку Удалить для этой записи в БД. Форма имеет одну кнопку Обновить. Серверу отправляется форма и он производит обновление записей в базе. Изменить только название и номер, это для базы мелочь, даже если это тысячи записей. разукрашивать для этого ячейки не нужно

В другом месте приложения я так и делал. Но здесь не хочу отправлять форму. Разукрашиваю ячейки по двум причинам, пользователь видит, что есть еще не записанные данные и мне легко их выбрать по имени класса.

savsoft 25.06.2020 14:59

Цитата:

Сообщение от laimas (Сообщение 526405)
.change {
    background-color: #FFA5A5;
}


<table id="data">
<tr><td><input data-val="abcd" name="data[11][name]" value="abcd" /></td><td><input data-val="5" name="data[11][range]" value="5" /></td></tr>
<tr><td><input data-val="qwer" name="data[22][name]" value="qwer" /></td><td><input data-val="8" name="data[22][range]" value="8" /></td></tr>
</table>
<button id="send">Update</button>


var tbl = $('#data').on('input', 'input', function() {
    this.classList.toggle('change', this.dataset.val != this.value)
});

$('#send').click(function() {
    var o = tbl.find('input.change');
    if(o.length) {
        o = o.map(function() {
            return {[this.name]: this.value}
        })
        console.log(o)
        //$.ajax()
    }
});


Примерно так, если сравнивать и отправлять только измененные.

А чем хуже, если просто присваивать измененным ячейкам отдельный класс, а потом просто пройтись по всем элементам с таким классом?

laimas 25.06.2020 15:01

Цитата:

Сообщение от savsoft
А чем хуже, если просто присваивать измененным ячейкам отдельный класс

Вы что редактируете - ячейки таблицы или данные? Если данные, то почему не поля формы (не важно в ней ли они или вне ее)? Если поля формы, то что вы будете отправлять на сервер - ячейку или данные поля формы под ее именем как ключом? А если данные поля, то зачем посредник в виде ячейки?

laimas 25.06.2020 15:08

Можно вообще удалить таблицу и вполне обойтись без нее, и используя css grid сформировать таблицу из любых элементов плюс полей формы. Работать то все равно нужно с полями.

savsoft 25.06.2020 15:50

Цитата:

Сообщение от laimas (Сообщение 526408)
Вы что редактируете - ячейки таблицы или данные? Если данные, то почему не поля формы (не важно в ней ли они или вне ее)? Если поля формы, то что вы будете отправлять на сервер - ячейку или данные поля формы под ее именем как ключом? А если данные поля, то зачем посредник в виде ячейки?

Редактирую данные, в таблице стоят обычные input/textarea поля, но форму не хочу, так как будет обновление страницы, хочу без обновления. С javascript/jquery опыта мало, поэтому сам смог сделать меняя класс у инпутов, которые изменились, а потом пройтись по всем измененным инпутам и через ajax обновить данные в базе. Понятно, что можно и форму обработать без сабмита, но пока не знаю как.

laimas 25.06.2020 16:05

savsoft, вас куда-то занесло, не в ту степь. Поля ввода никоим образом не определяют метод обмена данными с сервером, это чисто ваша прихоть - как захочется, так и будет.

Вас никто не заставляет отправлять форму, в примере ее и нет, ибо в данном случае отправление только измененных полей, что браузер сам не определит. Поэтому при активации отправления такие поля и собирает js-сценарий в объект, который и отправляется на сервер так, как вам хочется.

Что тут не понятного и в чем проблема? Вам же нужны поля, а не ... Что вы уперлись в таблицу, не только ее ячейкам можно задать стили, другие html-элементы также "имеют на это право", зачем вам посредники, которые в конечном итоге просто усложняют работу JS?

savsoft 25.06.2020 17:56

Понял, спасибо

laimas 25.06.2020 18:01

Только если делать так как в примере, то так как изменено в нем:

this.classList.toggle('change', this.dataset.val != this.value.trim())

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

А полям ввода можно через стили удалить бордюры, растянуть их на всю ячейку таблицы, они и будут восприниматься как ее ячейки.

Главное связать имена полей с конкретными записями в базе.

Vlasenko Fedor 25.06.2020 22:01

<style>
    td[contenteditable=true] {
        background: aqua;
    }
</style>
<table border="1" align="center" cellpadding="4" cellspacing="0">
    <tr>
        <th>#</th>
        <th>Имя</th>
        <th>Фамилия</th>
        <th>Опции</th>
    </tr>
    <tbody>
    <tr>
        <td data-field="id">1</td>
        <td class="data" data-field="name">Иван</td>
        <td class="data" data-field="family">Петров</td>
        <td class="options">
            <a class="edit" href="#">Edit</a>
            <a class="save" href="#" style="display: none">Save</a>
            <a class="cancel" href="#" style="display: none">Cancel</a>
        </td>
    </tr>
    <tr>
        <td data-field="id">2</td>
        <td class="data" data-field="name">Александр</td>
        <td class="data" data-field="family">Сидоров</td>
        <td class="options">
            <a class="edit" href="#">Edit</a>
            <a class="save" href="#" style="display: none">Save</a>
            <a class="cancel" href="#" style="display: none">Cancel</a>
        </td>
    </tr>
    </tbody>
</table>
<script src="https://code.jquery.com/jquery-2.2.4.min.js"
        integrity="sha256-BbhdlvQf/xTY9gja0Dq3HiwQF8LaCRTXxZKRutelT44="
        crossorigin="anonymous"></script>
<script>
    jQuery(document).ready(function ($) {
        $('.options').on('click', 'a', function (e) {
            e.preventDefault();
            var $tr = $(this).parents('tr');
            var $edit = $tr.find('.data');
            function showEdit() {
                $tr.find('a').hide();
                $tr.find('a.edit').show();
                $edit.attr('contenteditable', 'false');
            }
            switch (e.target.className) {
                case 'edit':
                    $edit.attr('contenteditable', 'true');
                    $(this).hide().siblings().show();
                    break;
                case 'save':
                    var data = {};
                    $tr.find('[data-field]').each(function (_, v) {
                        data[$(v).data('field')] = $(v).text();
                    });
                    console.log(data);
                    /*$.post('index.php', data, function (res) {
                        if (res) {
                            $edit.attr('contenteditable', 'false');
                        }
                    }, 'json').fail(function (error) {
                        alert(error.statusText)
                    });*/
                    showEdit();;
                    break;
                case 'cancel':
                    showEdit();
                    break;
            }
        });
    });
</script>

Вариант с contenteditable

laimas 25.06.2020 22:08

Офигеть, а зачем, ради понтов или ? :)


Часовой пояс GMT +3, время: 18:19.