jQuery扩展方法将select元素序列化为字典

时间:2014-10-25 18:58:26

标签: javascript jquery serialization

我的表格看起来像这样:

<form>
    <input name="foo" value="1" />

    <input name="bar[1]" value="a" />
    <input name="bar[2]" value="b" />
    <input name="bar[3]" value="c" />

    <select name="test" multiple>
        <option value="1" selected>a</option>
        <option value="2" selected>b</option>
        <option value="3" selected>c</option>
    </select>
</form>

我可以像这样序列化表格:

$('form').serialize();

产生:

"foo=1&bar%5B1%5D=a&bar%5B2%5D=b&bar%5B3%5D=c&test=1&test=2&test=3"

我想将select元素序列化为字典,而不是生成它:

"foo=1&bar%5B1%5D=a&bar%5B2%5D=b&bar%5B3%5D=c&test%5B1%5D=a&test%5B2%5D=b&test%5B3%5D=c"

这是我到目前为止所做的:

function serializeSelectListAsDictionary() {
    var name = $(this).attr('name'),
        obj = {};

    if (!$(this).is('select') || !name) {
        return '';
    }

    $(this).children('option:selected').each(function() {
        var key = name + '[' + $(this).val() + ']',
            value = $(this).html();

        obj[key] = value;
    });

    return $.param(obj);
}

$.fn.serializeDictionary = function() {
    var serialized;

    if (this.is('select')) {
        return serializeSelectListAsDictionary.apply(this);
    }

    serialized = this.serialize();

    this.find('select').each(function() {
        serialized = serialized.replace($(this).serialize(), serializeSelectListAsDictionary.apply(this));
    });

    return serialized;
};

当我这样称呼时,这很有效:

$('form').serializeDictionary();

但是当我尝试选择多个元素时会出现问题。假设我在表单中添加了另一个select元素:

<form>
    <input name="foo" value="1" />

    <input name="bar[1]" value="a" />
    <input name="bar[2]" value="b" />
    <input name="bar[3]" value="c" />

    <select name="test" multiple>
        <option value="1" selected>a</option>
        <option value="2" selected>b</option>
        <option value="3" selected>c</option>
    </select>

    <select name="blah" multiple>
        <option value="4" selected>d</option>
        <option value="5" selected>e</option>
        <option value="6" selected>f</option>
    </select>
</form>

然后,如果我像这样调用我的扩展方法:

$('select').serializeDictionary();

它产生:

"test%5B1%5D=a&test%5B2%5D=b&test%5B3%5D=c&test%5B4%5D=d&test%5B5%5D=e&test%5B6%5D=f"

输出应如下所示:

"test%5B1%5D=a&test%5B2%5D=b&test%5B3%5D=c&blah%5B4%5D=d&blah%5B5%5D=e&blah%5B6%5D=f"

我认为我的serializeSelectListAsDictionary函数只在第一个元素上被调用,但我不知道如何解决这个问题。

小提琴:http://jsfiddle.net/t5aze4r9/1

1 个答案:

答案 0 :(得分:1)

问题出在serializeDictionary函数上。它假定它只接收一个要序列化的元素。它适用于$('form').serializeDictionary();,因为它只匹配一个form元素。但如果你有两个form,你会看到与$('select').serializeDictionary();相同的问题。

当选择器匹配多个元素时,会出现问题,因为您只序列化第一个元素。你需要对匹配的元素进行某种迭代。

这是一个试图尽可能保持代码结构的提案:

$.fn.serializeDictionary = function() {
    var serialized = this.serialize();

    // Here is the key! You need to iterate over all the matched elements.
    this.each(function() {
        if ($(this).is('select')) {
            serialized = serialized.replace($(this).serialize(), serializeSelectListAsDictionary.apply(this));
        } else {         
            $(this).find('select').each(function() {
                serialized = serialized.replace($(this).serialize(), serializeSelectListAsDictionary.apply(this));
            });
        } 
    });

    return serialized;
};

请参阅updated code