当元素名称是数组时,如何检查选择元素更改

时间:2014-11-23 09:53:30

标签: php jquery ajax

我想要实现的目标:

  • 我的表单由#item#unit#price#total四个字段组成。

  • 用户可以输入多行#item#unit。为此,如果用户点击“添加新行”,则会出现一个新行以接收项目和单位(数量)的用户输入。如果用户在现有行上单击“ - ”,则该行将为除去。

  • 使用javascript change()实时识别选择的项目。

  • 使用ajax动态检索所选项目的价格,并将价格数据附加到#price元素中,并通过计算#total填充#unit x #price元素。

为实现这一目标,这就是我所做的。

首先,我的 HTML表单如下所示。

<form id="form">

    <input type="submit" name="create" value="Create" />


    <!-- dynamically add more lines -->
    <div class="form-group table-row hide" id="template">       

        <!-- remove button-->
        <div class="table-cell" style="width: 45px;">
            <a class="btn btn-default removeButton">
                <span class="glyphicon glyphicon-minus">
                </span>
            </a>
        </div>

        <!-- user input: item -->
        <div class="table-cell">
            <select id="item" class="form-control">
                <option value=""></option>
                <option value="item-1">Item 1</option>
                <option value="item-2">Item 2</option>
                <option value="item-3">Item 3</option>
            </select>
        </div>

        <!-- user input: quantity -->
        <div class="table-cell">
            <input id="unit" min="1" step="1" value="1" type="number" class="form-control"  />
        </div>      

        <!-- price is dynamically filled up using ajax -->
        <div class="table-cell">
            <input id="price" type="text" class="form-control"  />
        </div>

        <!-- total is dynamically calculated -->
        <div class="table-cell">
            <input id="total" type="text" class="form-control" />
        </div>

    </div>

    <button type="button" class="btn btn-default addButton">Add new line</button>

</form>

javascript代码实现动态添加/删除输入表单

<script>
jQuery(document).ready(function($) {

    var     idx = new Number( 0 );

    $('#form')

        // Add button click handler
        .on('click', '.addButton', function() {
            var $template = $('#template'),
                $clone    = $template
                                .clone()
                                .removeClass('hide')
                                .removeAttr('id')
                                .insertBefore($template);
            // assign name attributes with proper array name and index
            $clone.find('#item').attr('name', 'lines[' + idx + '][item]').attr('required', 'required').val('');
            $clone.find('#unit').attr('name', 'lines[' + idx + '][unit]').attr('required', 'required').val('');
            $clone.find('#price').attr('name', 'lines[' + idx + '][price]').attr('required', 'required').val('');
            $clone.find('#total').attr('name', 'lines[' + idx + '][total]').val('');

            idx = idx + 1;

        })

        // Remove button click handler
        .on('click', '.removeButton', function() {
            if (confirm("<?php _e( 'Are you sure you wish to remove this line? This cannot be undone.', 'doumi' ); ?>")) {
                var $row    = $(this).parents('.form-group');

                // Remove element containing the option
                $row.remove();
                idx = idx - 1;
            }
        });     

});
</script>

最后, jQuery调用ajax

<script>

    /*  Get Item Price */
    jQuery('#item').change(function(){
        var $item_id=$('#item').val();

        var ajaxurl = '<?php echo admin_url('admin-ajax.php'); ?>';

        // call ajax
        jQuery("#price").empty();
        jQuery.ajax({
            url: ajaxurl,
            /* ******************************************************************** */
            /* ajax_get_item_price is a function that returns the price of the item */
            /* ******************************************************************** */
            data:' action=ajax_get_item_price&item_id='+$item_id,
            type:'GET',
             success:function(results) {
                jQuery("#price").append(results);
            }
        });
    });

</script>

我可以动态添加和删除输入表单的行。

问题是每行中的表单元素的名称如下所示;

<select id="item" name="lines[0][item]"></select>
<input id="unit" name="lines[0][unit]" />
<input id="price" name="lines[0][price]" />
<input id="total" name="lines[0][total]" />

<select id="item" name="lines[1][item]"></select>
<input id="unit" name="lines[1][unit]" />
<input id="price" name="lines[1][price]" />
<input id="total" name="lines[1][total]" />

<select id="item" name="lines[2][item]"></select>
<input id="unit" name="lines[2][unit]" />
<input id="price" name="lines[2][price]" />
<input id="total" name="lines[2][total]" />

...
...
...

<select id="item" name="lines[n][item]"></select>
<input id="unit" name="lines[n][unit]" />
<input id="price" name="lines[n][price]" />
<input id="total" name="lines[n][total]" />

我想因为有多个#item具有不同的名称,所以jQuery不知道它需要注意哪个#item。但是,我也不知道如何使用相关的#item正确调用ajax。

非常感谢任何建议。

1 个答案:

答案 0 :(得分:1)

好吧,正如我所说,id对于页面应该是唯一的,所以对于类似的项目,你应该使用类:

....
<select class="item" name="lines[2][item]"></select>
<input class="unit" name="lines[2][unit]" />
<input class="price" name="lines[2][price]" />
<input class="total" name="lines[2][total]" />
....

因此,对于change事件,请使用类似

的内容
jQuery('.item').change(function(){
    // to narrow the items, use this
    var this$ = $( this );
    // this$ contain exactly one item, which is currently changing
    // do stuff
});

不知道究竟发生了什么错误,但我认为你的price项目太多了,因而发布了问题。 因此,下一行将执行此操作:获取所有#price元素,并将结果附加到每个元素。

success:function(results) {
    jQuery("#price").append(results);
}

您应该澄清您确切需要哪个#price项目。 首先,正如我已经提到的 - 使用多个类似字段的类jQuery(".price") 其次,添加一些说明确切应该更新的字段。 可以有很多方法,我展示两个

单向,使用next功能。

success:function(results) {
    this$.next('.price').eq(0).append(results);
    // here we refer to this$ - we try to find all `.price` element 
    // which come after our `select`
    // as there can be a lot of them we take only the first one
}

另一种方式,在元素分组的边界中使用context种类,即一些div。 我建议像这样更改你的HTML

<div class="item-wrapper">
    <select class="item" name="lines[2][item]"></select>
    <input class="unit" name="lines[2][unit]" />
    <input class="price" name="lines[2][price]" />
    <input class="total" name="lines[2][total]" />
</div>

因此,你的字段的每个块都将包含在div中。 之后,我们可以告诉jQUery仅在已更改.price所在的div中找到select元素

success:function(results) {
    var parent$ = this$.parent();   
    // again we refer to this$ getting its parent which is div
    parent$.find('.price').append(results);
    // here we try to find `.price` element located in a parent$ div. 
    // As it is definitely only one, we don't need to use any other code.
}

所以,这就是我能说的全部)