Сериализация формы с групповыми полями

109
15 февраля 2021, 03:20

Мне нужно передать поля формы get параметром, при этом группы полей например:

<input name="test" value="1">
<input name="test" value="2"/>
<input name="test" value="3"/>

должны передаваться в виде site.ru?test=1,2,3

Сам сделал, но мне кажется, что есть решение получше. Делаю так:

$.fn.serializeObject = function () {
    "use strict";
    const result = {};
    const extend = function (i, element) {
        const node = result[element.name];
        if ('undefined' !== typeof node && node !== null) {
            if ($.isArray(node)) {
                node.push(element.value);
            } else {
                result[element.name] = [node, element.value];
            }
        } else {
            result[element.name] = element.value;
        }
    };
    $.each(this.serializeArray(), extend);
    return result;
};

и

$('body').on('change','.filter', function () {
        const params = $('.filters').serializeObject();
        const urlParams = {};
        $.each(params, function(id) {
            ret = $('input[name^="'+id+'"]:checked').map(function() {
                return this.value;
            }).get().join(',');
            urlParams[id] = ret;
        });
        $.ajax({
            type: "GET",
            url: document.location.href,
            data: urlParams,
            success: function(data){
                $(".product-content").html($(data).find('.product-list'));
            }
        });
    });

Так-же этот вариант не совсем подходит так как мне нужно менять url через window.history.replaceState

И если я делаю

success: function(data){
                $(".product-content").html($(data).find('.product-list'));
                window.history.replaceState({},'',this.url)
            }

Параметры каждый раз добавляются к url-у...

Answer 1

Решение сделал: Сериализуем форму в объект:

$.fn.serializeObject = function () {
    "use strict";
    const result = {};
    const extend = function (i, element) {
        const node = result[element.name];
        if ('undefined' !== typeof node && node !== null) {
            if ($.isArray(node)) {
                node.push(element.value);
            } else {
                result[element.name] = [node, element.value];
            }
        } else {
            result[element.name] = element.value;
        }
    };
    $.each(this.serializeArray(), extend);
    return result;
};

Выполняем по изменению нужного элемента:

$('body').on('change','.filter', function () {
    const params = $('.filters').serializeObject();
    let currentKey;
    if(isEmpty(params)){
        updateQueryStringParam($(this).prop('name'), $(this).val(), true);
    }else{
        currentKey = $(this).prop('name');
        if($('input[name^="'+currentKey+'"]:checked').length === 0){
            updateQueryStringParam($(this).prop('name'), $(this).val(), true);
        }else {
            $.each(params, function (id, val) {
                let value;
                if ($.isArray(val)) {
                    value = val.join(',');
                } else {
                    value = val;
                }
                updateQueryStringParam(id, value);
            });
        }
    }
});

Метод получения url с нужными параметрами не удаляя текущие и удаляя те, которых нет:

     function updateQueryStringParam(param, value, remove = false) {
    const baseUrl = [location.protocol, '//', location.host, location.pathname].join('');
    const urlQueryString = document.location.search;
    let newParam = param + '=' + value,
        params = '?' + newParam;
    if (urlQueryString) {
        const keyRegex = new RegExp('([\?&])' + param + '[^&]*');
        if (urlQueryString.match(keyRegex) !== null) {
            params = urlQueryString.replace(keyRegex, remove ? '' : "$1" + newParam);
        } else {
            params = urlQueryString + '&' + newParam;
        }
    }
    if(params.indexOf('?') === -1 ){
        params = params.replace('&','?');
        console.log(params);
    }
    window.history.replaceState({}, "", baseUrl + params);
    return baseUrl + params;
}

Проверка объекта на empty:

function isEmpty(obj) {
            for(const key in obj) {
                if(obj.hasOwnProperty(key))
                    return false;
            }
            return true;
        }

Если кто-то предложит более изящное решение - буду рад)

READ ALSO
Высота блока под картинку с &ldquo;position: absolute&rdquo;

Высота блока под картинку с “position: absolute”

У меня в блоке есть картинка со свойством "position", которое имеет значение "asbolute"Картинка намного больше блока, и мне бы хотелось, чтобы блок...

126
Как прижать footer к низу страницы

Как прижать footer к низу страницы

Footer находится посередине страницы и никуда не двигаетсяПодскажите, пожалуйста, в чем проблема?

116
Как работает этот метод LSB стеганографии?

Как работает этот метод LSB стеганографии?

Два вопроса по программе, использующую метод LSB СтеганографииДело в том, что у меня немного проблемы с понимаем того, зачем нужна та или иная...

107