【问题标题】:Assigning an increment value to dynamic fields为动态字段分配增量值
【发布时间】:2013-12-06 15:09:11
【问题描述】:

我有从 jquery 函数生成的动态输入字段。可以通过单击这些输入字段的按钮来添加或删除。这些字段由 mysql 表中的数据填充。每个填充的输入都有一个从数据库中获取的唯一 ID。添加新字段时,我从 ajax 请求中获得了下一个 AUTO_INCREMENT。然后我可以增加 +1,但对于所有字段。我只想为新字段执行此操作。如果由于某种原因从另一个应用程序进行插入查询事务,它将更新 start increment from 字段,然后使用正确的值更新其余字段(检查我的意思是什么 jsFiddle(http://jsfiddle.net/f9XP8/2/)。

问题在于如何将它们组合在一起。我只想关注能够添加一个新字段并为其分配适当的下一个person_id 以进行数据库插入。 LIVE EXAMPLE

<script>
$(document).ready(function () {
    var $increment_num = $('#increment_num');
    var interval = 100;  //3000 = 3 seconds
    function doAjax() {
        $.ajax({
            type: 'POST',
            url: 'personAutoIncrement.php',
            data: $(this).serialize(),
            dataType: 'json',
            success: function (data) {
                    var $cloned = $('#input_table tr');
                    var num = parseInt(data);
                    $increment_num.val(num);
                    $cloned.each(function(i){
                        $(this).find('[name^="increment_id"]').first().val(num+i);
                    })
            },
            complete: function (data) {
                // Schedule the next
                setTimeout(doAjax, interval);

        }
    });
    }
    setTimeout(doAjax, interval);
    var click_count = 0;
    $('#btnAdd').click(function () {
    click_count++;
        var $clones     = $('#input_table tr'),
            num         = $clones.size() + 1,
            next_num    = parseInt($clones.last().find('input[name^="increment_id"]').val()) + 1,
            $template   = $clones.first(),
            newSection  = $template.clone().attr('id', 'pq_entry_'+num),
            ident       = 'increment_id_'+num;
            person_id = 'person_id_'+num;
            person_fname = 'person_fname_'+num;
            person_lname = 'person_lname_'+num;

        // clear out all sections of new input
        newSection.find('input').not('[name^="increment_id"]').val('');

        newSection.find('input[name^="increment_id"]').attr({
            'id': ident,
            'name': ident
        }).val(/*next_num*/);
        newSection.find('input[name^="person_id"]').attr({
            'id': person_id,
            'name': person_id
        }).val(/*next_num*/);
        newSection.find('input[name^="person_fname"]').attr({
            'id': person_fname,
            'name': person_fname
        }).val(/*next_num*/);


        $('#input_table').append(newSection);
        $('#btnDel').prop('disabled', '');
        if (num == 100) $('#btnAdd').prop('disabled', 'disabled');
    });

    $('#btnDel').click(function () {
        var num = $('.clonedSection').length; // how many duplicate input fields we currently have
        $('#pq_entry_' + num).remove(); // remove the last element

        // enable the "add" button
        $('#btnAdd').prop('disabled', '');

        // if only one element remains, disable the "remove" button
        if (num - 1 == 1) $('#btnDel').prop('disabled', 'disabled');
    });

    $('#btnDel').prop('disabled', 'disabled');
});
</script>

html

<table>
    <thead>
        <tr>
            <th>ID from DB</th>
            <th>First Name</th>
        </tr>
    </thead>
    <tbody id="input_table">
        <tr id="pq_entry_1">
            <td><input type="text" id="increment_id_1" name="increment_id_1" readonly value="5" /></td>
            <td><input type="text" name="first_name" placeholder="First Name" /></td>
        </tr>
    </tbody>
</table>
<input type='button' id='btnAdd' value='add text box' />
<input type='button' id='btnDel' value='Delete' /></br>
</table>

【问题讨论】:

  • 为什么不能直接将 AUTO_INCREMENT 字段委托给您的数据库层?您不应该在客户端上搞砸它:即使显示 ID 字段通常也是一个坏主意。我宁愿在最终提交后直接从服务器(即 db-server)检索新 id。
  • 您使用的是 MySQL 还是类似的 RDBMS?
  • @RobM。我正在使用 MySQL。要不要我贴一下mysql/php代码?
  • @RobM。有什么想法可以完成这项工作吗?

标签: javascript jquery


【解决方案1】:

如果我没记错的话,您想知道如何增加某些行,但允许“冻结”其他行(因为它们已保存到数据库中)。我已经对您的代码进行了一些更改,以下是重要说明:

  1. 我删除了动态名称属性。不需要动态生成字段名,只需分配 data-* 属性来保存 id 或参考tr.find('input[name="person_id"]')
  2. tr 添加了data-saved 属性,以了解是否应将其包含在更新后的auto increment id 中,或者是否应保持原样
  3. 在每行旁边添加了一个保存按钮,因为它只是在行上设置data-saved 属性,如果需要,您可以添加 AJAX 调用来保存记录

Updated Fiddle

Javascript:

$(document).ready(function () {
    var $increment_num = $('#increment_num');
    var interval = 5000;  //3000 = 3 seconds
    function doAjax() {
        $.ajax({
            type: 'POST',
            url: 'personAutoIncrement.php',
            data: $(this).serialize(),
            dataType: 'json',
            success: function (data) {
                var $cloned = $('#input_table tr').not('[data-saved]');
                var num = parseInt(data);
                $increment_num.val(num);
                $cloned.each(function(i){
                    var $this = $(this);
                    $this.find('[name^="person_id"]').first().val(num+i);
                })
            },
            complete: function (data) {
                // Schedule the next
                setTimeout(doAjax, interval);
            }
        });
    }
    setTimeout(doAjax, interval);
    var click_count = 0;

    $('#btnAdd').click(function () {
        click_count++;
        var $clones     = $('#input_table tr'),
            num         = $clones.size() + 1,
            next_num    = parseInt($clones.last().find('input[name^="person_id"]').val()) + 1,
            $template   = $clones.first(),
            newSection  = $template.clone().attr('id', 'pq_entry_'+num),
            person_id   = 'person_id_'+num;
            person_fname = 'person_fname_'+num;
            person_lname = 'person_lname_'+num;

        newSection.removeAttr('data-saved');

        // clear out all sections of new input
        newSection.find('input[type="text"]').val('');

        newSection.find('input[name^="person_id"]').attr({
            'id': person_id
        }).val(next_num);

        newSection.find('input[name^="person_fname"]').attr({
            'id': person_fname
        });

        newSection.find('input[type="button"]').attr('data-ident', next_num);


        $('#input_table').append(newSection);
        $('#btnDel').prop('disabled', '');
        if (num == 100) $('#btnAdd').prop('disabled', 'disabled');
    });

    $('.save-button').click(function(){
        var $parent = $(this).parents('.clonedSection')
        var id = $parent.find('input[name="person_id"]').val();
        // do whatever else here, save to db
        $parent.attr('data-saved', '1');
    })

    $('#btnDel').click(function () {
        var num = $('.clonedSection').length; // how many duplicate input fields we currently have
        $('#pq_entry_' + num).remove(); // remove the last element

        // enable the "add" button
        $('#btnAdd').prop('disabled', '');

        // if only one element remains, disable the "remove" button
        if (num - 1 == 1) $('#btnDel').prop('disabled', 'disabled');
    });

    $('#btnDel').prop('disabled', 'disabled');
});

HTML:

<form>
<strong>Start Increment from Next ID to be inserted in the DB:</strong><input id="increment_num" name="increment_num"  type="text" /></br>
<table>
    <thead>
        <tr><th>ID from DB</th><th></th>
        <th>First Name</th></tr>
    </thead>
    <tbody id="input_table" >
        <tr id="pq_entry_1" class="clonedSection" data-saved="1">
            <td><input type="text" name="person_id" value='1' readonly /></td>
            <td><input id="person_fname_1" name="person_fname" placeholder=" First Name" type="text" value='James'/></td>
            <td><input type="button" class="save-button" value="Save" />
        </tr>
        <tr id="pq_entry_2" class="clonedSection" >
            <td><input type="text" name="person_id" value='2' readonly /></td>
            <td><input id="person_fname_2" name="person_fname" placeholder=" First Name" type="text" value='Cynthia'/></td>
            <td><input type="button" class="save-button" value="Save" />
        </tr>
    </tbody>
</table>
<input type='button' id='btnAdd' value='add another Person' />
<input type='button' id='btnDel' value='Delete' /></br>
</form>

说了这么多,我可能会通过隐藏元素来处理这个问题:

&lt;input type="hidden" name="person_id" value="1" /&gt;

当新行生成时无效:

&lt;input type="hidden" name="person_id" value="" /&gt;

然后在我的 PHP 中,我将允许 MySQL 以如下方式处理自动递增 id:

<?php
    $params = $_POST;
    if(is_numeric($params['person_id'])){
       $sql = sprintf('UPDATE person SET fname = "%s", lname = "%s" WHERE person_id = %u LIMIT 1', 
          mysql_real_escape_string($params['fname']), 
          mysql_real_escape_string($params['lname']), 
          intval($params['person_id'])
       );
    } else {
       // the NULL tells MySQL to select the correct next increment id automatically
       $sql = sprintf('INSERT INTO person (id, fname, lname) VALUES (NULL, "%s", "%s")',
         mysql_real_escape_string($params['fname']),
         mysql_real_escape_string($params['lname']);
       );
    }

?>

【讨论】:

  • 这非常有效!谢谢你。小咨询:既然我每3秒做一次ajax调用,我应该考虑做Server Sent Events(SSE's)吗?
  • 很高兴我能帮上忙。关于 SSE,我个人会选择 websockets,但如果你有 SSE 经验并且它适合你的用例,那么肯定:)
  • 谢谢。我会更多地阅读它。 Rob 单击delete 按钮时从数据库中删除用户的建议是什么?
  • 我会将删除按钮移动到每一行(如保存按钮)并使用与我为$('.save-button')定义的点击处理程序非常相似的逻辑
  • Rob 关于delete new field button 的另一次咨询(这与delete user button 无关):如何让从数据库中的值填充的字段无法删除?以某种方式将它们锁定。用户可以添加新字段或删除这些新字段,但他们不能删除已经存在的字段。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2015-04-13
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多