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

时间:2017-12-19 02:19:08

标签: php laravel laravel-5.2

关于如何在表单提交后正确保留Laravel中的复选框字段,这里有很多问题( exampleexampleexample ),这个问题与此无关。

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

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

验证失败后重新填充表单输入的标准方法是使用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种情况:

  • 案例1:数据库状态0(未选中),已提交状态已检查。 old('unicorns')将为1,因此测试评估true,选中复选框 - 确定!

  • 案例2:数据库状态1(已选中),未提交已提交状态。由于old('unicorns')为空,old()会回退到默认值$model->unicorns1),因此测试会评估true,并选中复选框 - 但是我们只是取消选中它! FAIL!

(其他两种情况没有问题,复选框没有从数据库中的状态改变)。

如何解决这个问题?

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

  

注意:$ errors变量绑定到视图...

我想为此创建一个全球帮手,$errors不会在那里工作。无论如何,这种方法感觉......笨重而且太复杂。

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

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

6 个答案:

答案 0 :(得分:1)

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

我有一个Html帮助器,创建为described in this question,并在config/app.php中别名,如this answer to that question的第一部分所述。我为它添加了一个静态方法:

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

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

答案 1 :(得分:1)

我这样做

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

答案 2 :(得分:0)

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

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

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

这对你有用吗?

答案 3 :(得分:0)

从Don's Panic的回答中,你可以在刀片中这样做:

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

希望它有所帮助。

答案 4 :(得分:0)

我遇到了同样的问题,发现了这个旧帖子。想分享我的解决方案:

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

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

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

当没有old()数组时,就没有帖子,因此将DB值$model->unicorns用作条件,如下所示:

{{ $model->unicorns?' checked':'' }}将正确计算值为0或1

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

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

有点杂耍,您有嵌套的三元组,但是效果很好。

答案 5 :(得分:-1)

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

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

编辑:

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