代码之家  ›  专栏  ›  技术社区  ›  Kien Pham

如何使用jquery和$form helper添加新的表单字段?

  •  4
  • Kien Pham  · 技术社区  · 16 年前

    我正在尝试让用户执行“单击此处添加更多信息”链接。我正在尝试对输入字段执行此操作,以便字段的id必须递增。

    我希望jquery在每次单击时都添加此项,其中$i是每个字段递增的数目:

    <div id="info"></div>
    <?php echo $form->input("User.$i.first_name"); ?>
    <a href = 'add/' id='addInfo'>Add info</a>
    

    这是到目前为止我的jquery代码:

    var current = 1;
    $('#addInfo').click(function(){            
        var newField = '<h4>Info#' + current + '</h4>';
        $('#info').append(newField)
        current++;
        return false;
    });
    

    我提出的解决方案之一是在javascript中手动创建输入字段并将其分配给newfield。我认为应该有一种方法可以创建第一个工作集,然后使用jquery复制第一个内容,然后增加新字段的数量。

    谢谢!

    3 回复  |  直到 10 年前
        1
  •  3
  •   Andrew Kolesnikov    16 年前

    其思想是计算所有现有字段并缓存该数字。

    currentFields = $('#yourFormname input').size(); // caches
    

    现在,附加另一个文本字段,并根据上面计算的字段数为其指定一个名称。

    $('#addInfo').click(function(){            
        $('#info').append('<input type="text" name="data[User]['+currentFields+'][first_name]"');
        currentFields++;
        return false;
    });
    

    急板地!

    最后,您可以克隆一个字段html,然后用新计算的替换它的name属性,而不是将字段作为字符串追加。

        2
  •  1
  •   Fury    10 年前

    感谢安德鲁指引我正确的方向。我能够克隆表单,甚至添加一个链接来删除最后克隆的输入。这个解决方案不需要我在javascript中生成表单,因此所有的格式仍然完整,需要编写的代码更少。

    我知道这会弄乱auth组件,并且我的表单将被黑洞,因为散列将是错误的。稍后我将不得不在后端手动清理它。基本上,我将第一个字段替换为当前增量的id为1。我看到它需要唯一名称和id的三个地方是标签、输入名称和输入id。我不知道是否有人有更好的解决方案来替换这些html值,但我必须来回转换以替换它。

    以下是我的解决方案:

    // HTML 
    <div id="user">
         <div class="users">
              <h4>User #1</h4>
              <?php echo $form->input("User.1.first_name", array(
                        'label' => 'First Name',
                        'error' => 'Please enter a valid first name.'
                    ));?>
    
               <?php echo $form->input("User.1.last_name", array(
                        'label' => 'First Name',
                        'error' => 'Please enter a valid last name.'
                    ));?>
         </div>
    </div>
    
    <div id="moreUsers"></div>
    

    //javascript代码:

    var currentUserCount = 1;
    
    $('#addUser').click(function(){
                currentUserCount = cloning('#user', '#moreUser', currentUserCount);
                return false;
            });
    
    $('#removeUser').click(function(){
                    $('.users:last').remove();
                    currentUserCount--;
                }
                return false;
            });
    
        function cloning(from, to, counter) {
                    var clone = $(from).clone();
                    counter++;
    
                    // Replace the input attributes:
                    clone.find(':input').each(function() {
                        var name = $(this).attr('name').replace(1,counter);
                        var id = $(this).attr('id').replace(1,counter);
                        $(this).attr({'name': name, 'id': id}).val('');
                    });
    
                    // Replace the label for attribute:
                    clone.find('label').each(function() {
                        var newFor = $(this).attr('for').replace(1,counter);
                        $(this).attr('for', newFor);
                    });
    
                    // Replace the text between html tags:
                    clone = clone.html().replace(1,counter);
                    $(to).before(clone);
                    return counter;
                } // end cloning
    
        3
  •  -1
  •   ᴍᴇʜᴏᴠ   10 年前

    这是给搜索时发现这个问题的人的便条(就像我一样)。

    要使输入名“可克隆”,不必保持增量并执行这种难看的连接。cakephp识别空值并将其转换为 [] ,这更优雅,因为浏览器和服务器将为您执行输入枚举工作。

    下面是我所说的一个例子:

    echo $form->input("User..first_name"); 
    echo $form->input("User.first_name."); 
    

    这将分别使您:

    <input name="data[User][][first_name]">
    <input name="data[User][first_name][]">
    

    然后可以使用javascript来克隆、清理和附加节点。下面是一个简单的例子:

    var container=document.getElementById('info');
    var element=wrapper.getElementsByTagName('input')[0];
    var clone=element.cloneNode(true);
    var clone_inputs=clone.getElementsByTagName('input');
    for (var i=0; i<clone_inputs.length; i++) {
        clone_inputs[i].value='';
    }
    var result=container.appendChild(clone);
    

    不用做了 .replace() 或 data[User]['+currentFields+'][first_name] ,这是一个更加灵活,同时又不那么难看的解决方案。

    更新 如果你使用 Security Component 具有 form tampering prevention 已启用您可能希望解锁这些输入以防止提交被黑洞:

    $this->Form->unlockField('User.first_name'); // no trailing dot
    echo $this->Form->input("User.first_name."); 
    

    希望这有帮助。