Laravel 验证失败后的复选框状态

Laravel checkbox state after failed validation

SO 上有很多关于如何在提交表单后正确保留 Laravel 中的复选框字段的问题( , , ), 这个问题不是关于那个的。

请注意我也很清楚Laravel's old() method, and that it accepts a default value。我的问题是关于 old() 似乎不适用于复选框的特殊情况。

我正在编辑表单,更新数据库中已有的数据。该表单最初将使用数据库中的值填充。

验证失败后重新填充表单输入的标准方法是使用 old()。对于大多数输入类型,类似以下的内容有效:

<input type='text' name='unicorns' value='{{ old('unicorns', $model->unicorns) }}'>

在初始页面加载时(在提交表单之前)这工作正常。由于尚未提交任何内容,old('unicorns')null,因此将使用默认值 $model->unicorns,文本字段的值反映当前数据库状态。

提交新值后,验证失败,old('unicorns') 将是新值,即使新值是空字符串,文本字段的值再次反映提交状态,如我们所愿.

然而,当未选中的复选框根本没有出现在请求中时,这会分解为复选框。考虑:

<input type='checkbox' name='unicorns' value='1' @if old('unicorns', $model->unicorns) checked @endif>

在初始页面加载时,这工作正常,就像文本字段一样。但在验证失败后,对于复选框从其初始状态更改的 2 种情况:

(其他2种情况没有问题,checkbox没有从DB中的状态改变)

如何解决这个问题?

我最初认为解决此问题的最佳方法是测试是否存在验证错误 - 如果存在,请使用 old() 值,没有默认回退;如果不是,请使用 old() 和默认回退。测试失败验证的一种方法是检查 $errors。这似乎可行,但它 only works within a view AFAICT,因为(来自 Laravel 文档):

Note: The $errors variable is bound to the view ...

我想为此创建一个全局助手,$errors 在那里不起作用。无论如何,这种方法感觉...笨拙且过于复杂。

我错过了什么吗?有解决这个问题的巧妙 Laravel 方法吗? old() 根本不适用于这种特殊情况,这似乎很奇怪。

这不是一个新问题,其他人是如何处理的?

我实际上在保留复选框状态时做了一个简单的三元运算符:

<input name='remember' type='checkbox' value='1' {{ old('remember') ? 'checked' : '' }}>

编辑:

<input name='remember' type='checkbox' value='yes' {{ old('remember') == 'yes' ? 'checked' : '' }}>

这是我在问题中提到的解决方案。它运作良好,6 个月后,它看起来不像我发布问题时那么笨拙。不过,我很高兴听到其他人是如何做到这一点的。

我有一个 Html 助手,创建为 , and aliased in config/app.php as described in the first part of 。我给它添加了一个静态方法:

namespace App\Helpers;
use Illuminate\Support\ViewErrorBag;

class Html {
    /**
     * Shortcut for populating checkbox state on forms.
     *
     * If there are failed validation errors, we should use the old() state
     * of the checkbox, ignoring the current DB state of the field; otherwise
     * just use the DB value.
     *
     * @param string $name The input field name
     * @param string $value The current DB value
     * @return string 'checked' or null;
     */
    public static function checked($name, $value) {
        $errors = session('errors');

        if (isset($errors) && $errors instanceof ViewErrorBag && $errors->any()) {
            return old($name) ? 'checked' : '';
        }

        return ($value) ? 'checked' : '';
    }
}

现在在我看来我可以像这样使用它:

<input type='checkbox' name='unicorns' value='1' {{ \Html::checked('unicorns', $model->unicorns) }}>

这会在初始加载时和验证失败后正确处理数据库和提交状态的所有组合。

我遇到了类似的情况,我的解决方案是在复选框字段之前添加一个隐藏字段。所以,在你的情况下它会是这样的:

<input type='hidden' name='unicorns' value='0'>
<input type='checkbox' name='unicorns' value='1' {!! old('unicorns', $model->unicorns) ? ' checked' : '' !!}>

这样,当未勾选该复选框时,该字段的值 0 仍会出现在 post 请求中。勾选后,复选框的值将覆盖隐藏字段中的值,因此顺序很重要。您不需要通过这种方法使用您的自定义 class。

这对你有用吗?

根据 Don't Panic 的回答,你可以在 blade 中这样做:

<input type="checkbox" class="form-check-input" value='true'
@if ($errors->any())
{{ old('is_private') ? 'checked' : '' }}
@else
{{ isset($post) && $post->is_private ? 'checked' : '' }}
@endif
>

希望对您有所帮助。

我这样做

 <input id="main" class="form-check-inline"
 type="checkbox" name="position" {{old('position',$position->status)?'checked':''}}>

我遇到了同样的问题并找到了这个旧的 post。想分享我的解决方案:

<input type="checkbox" name="unicorns" class="form-check-input" id="verified" {{ !old()?$model->unicorns:old('unicorns')?' checked':'' }}>

{{ !old()?$model->unicorns:old('unicorns')?' checked':'' }}

嵌套三元组:第一个三元组为第二个提供条件:

当没有old()数组时,也就没有post,所以DB值$model->unicorns会作为条件,像这样:

{{ $model->unicorns?' checked':'' }} 将正确评估 0 或 1

的值

但是如果 old() 数组存在,我们可以使用 old('unicorns') 变量的存在作为条件,如下所示:

{{ old('unicorns')?' checked':'' }} 将正确评估值 on 或无值。

这有点像变戏法,你有嵌套的三元组,但效果很好。