dongxianji0968 2014-11-23 09:53
浏览 31
已采纳

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

What I am trying to achieve:

  • My form consists of four fields of #item, #unit, #price, and #total.

  • A user can input multiple lines of #item and #unit. For this, if the user clicks on "Add new line', there will appear a new line to receive user input for item and unit (quantity). If the user clicks on "-" on an already existing line, the line will be removed.

  • Which item is selected is identified on real-time using javascript change().

  • The price of the selected item is dynamically retrieved using ajax and the price data is appended into the #price element and #total element is also filled up by calculating #unit x #price.

To achieve this, here's what I did.

First, my HTML form as below.

<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>

And javascript code to implement dynamic add/remove of input forms.

<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>

Lastly, jQuery to call 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>

I have no problem dynamically adding and removing lines for the input form.

The problem is that form elements in each line is given a name as an array like below;

<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]" />

I guess that since there are multiple #items with varying names, jQuery does not know which #item it needs to pay attention to. However, I have no idea, either, as to how to properly call ajax with the concerned #item.

Any advice is highly appreciated.

  • 写回答

1条回答 默认 最新

  • dongzhong2008 2014-11-23 10:38
    关注

    Ok, as I said, ids should be unique for a page, so for similar items you should use classes:

    ....
    <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]" />
    ....
    

    So, for change event use something like

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

    No quite get what exactly wrong is happening, but I think you have too many items with price is and thus issuing prblems. So this line does next: gets all #price elements and appends results to each of them.

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

    You should clarify which #price item you exactly need. First, as I already mentioned - use classes for multiple similar fields jQuery(".price") Second, add some clarification what field exactly should be updated. There can be many ways, I show two

    One way, use next function.

    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
    }
    

    Another way, Use kind of context, ie some div, in bounds of which your elements are grouped. I suggest changing your html like this

    <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>
    

    So, every block of your fields will be wrapped in a div. After that we can tell jQUery to find .price element only in a div in which changed select is located

    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.
    }
    

    So, this is all that I can say)

    本回答被题主选为最佳回答 , 对您是否有帮助呢?
    评论

报告相同问题?

悬赏问题

  • ¥15 matlab图像高斯低通滤波
  • ¥15 针对曲面部件的制孔路径规划,大家有什么思路吗
  • ¥15 钢筋实图交点识别,机器视觉代码
  • ¥15 如何在Linux系统中,但是在window系统上idea里面可以正常运行?(相关搜索:jar包)
  • ¥50 400g qsfp 光模块iphy方案
  • ¥15 两块ADC0804用proteus仿真时,出现异常
  • ¥15 关于风控系统,如何去选择
  • ¥15 这款软件是什么?需要能满足我的需求
  • ¥15 SpringSecurityOauth2登陆前后request不一致
  • ¥15 禅道二次开发编辑版本,上传不了发行包