【问题标题】:What's the cleanest way to implement a dynamic HTML form?实现动态 HTML 表单的最简洁方法是什么?
【发布时间】:2017-05-21 08:56:02
【问题描述】:

我想制作一个 HTML 表单,用户可以在其中一次编辑一组元素。用户必须能够删除元素、编辑元素和添加新元素。我使用 PHP (Laravel) 作为后端,使用 jQuery 作为动态表单。

我最初的想法基本上是这样做的:

<form id="bars">
    @foreach($foo as $bar)
        <input type="text" name="name[]" value="{{$bar->name}}" required>
        <input type="color" name="color[]" value="{{$bar->color}}" required>
        <input type="checkbox" name="completed[]"{{$bar->completed ? ' checked' : ''}}>
        <span class="deleteRow"></span>
    @endforeach
</form>

<div id="template" style="display:none;">
        <input type="text" name="name[]" required>
        <input type="color" name="color[]" required>
        <input type="checkbox" name="completed[]"{{$bar->completed ? ' checked' : ''}}>
        <span class="deleteRow"></span>
</div>

<script>
    $(document).ready(function() {
    // Remove rows
        $('form').on('click', '.deleteRow', function() {
            $(this).closest('tr').remove();
        });

        // Clone new rows from template
        $('#addRow').click(function() {
            $('#template tr')
                .clone()
                .appendTo('#bars');
        });
    });
</script>

这是 Blade 模板,我从中删除了所有不相关的代码和样式。此方法使用以下概念:

  • [] 在输入名称中,以便将发布的数据放入数组中。在处理过程中,我最终得到三个数组 namecolorcompleted,它们将包含 POST 数据。
  • 现有元素由 Blade 模板以表单形式呈现在服务器端
  • 新行从“表单模板”中克隆,并在用户单击“新行”按钮时添加到表单中。

这很简单,在大多数情况下都有效(我以前用过),但在这种情况下它不起作用,因为有一个小问题:复选框。未选中的复选框不会被发布,这意味着 completed[] 数组的大小将小于其他数组,我无法检查哪些元素已选中复选框。

现在我可以修改我的 JS,使其跟踪索引并在每个输入名称中显式插入索引(例如 name[0]name[1] 等),但这种方法很复杂,因为表格必须预先填写数据,并且一开始不能为空。

我可以,而不是通过 Blade 模板填充数据,让 JS 也处理它(通过 JSON API),但这也会很快变得复杂,因为 JS 现在必须“解析”表单模板并填写所有内容值。

以干净的方式完成此任务的最佳做法是什么?

【问题讨论】:

  • (document).ready( ... )更改为$(document).ready( ... )
  • 啊,我当然是那个意思;)这只是复制粘贴代码时的错误。我已经编辑了问题。
  • 哦,哈哈:D 我正在查看您的代码,一切似乎都很好:/您确定您已包含必要的所有内容吗?
  • 在什么方面看起来不错?并不是代码没有运行。这是我要问的一个实施问题;这个提议的解决方案在我的情况下不起作用,因为我的复选框破坏了输入名称中的 [] 方法。 (未选中的复选框未发布)所以我正在寻找另一种没有此问题的干净方法。
  • 您可以为动态字段设置索引,例如:name[1]checkbox[1](添加某种关系)。然后当你在后端循环你的数组时,你可以看到哪个复选框(如果有的话)是相关的。您需要在初始循环中打印该索引,然后在从模板中添加新元素时动态添加它。

标签: javascript php jquery forms laravel


【解决方案1】:

我最终得到的是以下内容:

<form id="bars">
    @foreach($foo as $i => $bar)
        <input type="hidden" name="id[{{$i}}]" value="{{$status->id}}">
        <input type="text" class="form-control" name="name[{{$i}}]" value="{{$status->name}}" required>
        <input type="color" name="color[{{$i}}]" value="{{$bar->color}}" required>
        <input type="checkbox" name="completed[{{$i}}]"{{$bar->completed ? ' checked' : ''}}>
        <span class="deleteRow"></span>
    @endforeach
</form>

<div id="template" style="display:none;">
        <input type="text" name="name[$i]" required>
        <input type="color" name="color[$i]" required>
        <input type="checkbox" name="completed[$i]"{{$bar->completed ? ' checked' : ''}}>
        <span class="deleteRow"></span>
</div>

<script>
    $(document).ready(function() {
    // Remove rows
        $('form').on('click', '.deleteRow', function() {
            $(this).closest('tr').remove();
        });

        // Clone new rows from template
        $('#addRow').click(function() {
            $('#template tr')
                .clone()
                .html(function(i, oldHTML) {
                    return oldHTML.replace(/\$i/g, $('#bars tr').length);
                })
                .appendTo('#bars');
        });
    });
</script>

这主要是@MagnusEriksson 建议我做的(非常感谢!),但通过不必保留计数器而只需使用表单内的行数作为克隆行的索引,以一种稍微干净的方式解决了。

【讨论】:

    猜你喜欢
    • 2020-08-19
    • 1970-01-01
    • 2023-02-10
    • 2018-02-09
    • 1970-01-01
    • 2015-04-27
    • 1970-01-01
    • 2020-06-08
    • 2011-03-21
    相关资源
    最近更新 更多