formers / former

A powerful form builder, for Laravel and other frameworks (stand-alone too)
https://formers.github.io/former/
1.34k stars 205 forks source link

[L5] Checkboxes removed on validation redirect withInput #534

Closed biwerr closed 7 years ago

biwerr commented 8 years ago

I have some Problems with generating Checkboxes to attach Roles to a specific User. If the validation fails laravel redirects the request to the edit form withInput(), but Former ignores the available roles and displays only the selected roles.

Method 1

$groups = [];
        foreach(Role::all() as $role)
        {
            $groups[$role->name]=[
                'value' => $role->id,
                'checked' => $model->hasRole($role->name),
                'name' => 'roles_selection['.$role->name.']',
            ];
        }
$form.= Former::checkboxes('roles_selection[]',"Roles",$groups);

On Edit image

After Redirect withInput() image

Method 2

$form.= Former::checkboxes('roles[]',"label",Role::all()->lists('name','id')->toArray()); I have tried to use the relation ($user->roles), but on i got a rendering error if i try this Method Former\Form\Fields\Checkbox::__toString() must not throw an exception

Error is thrown at: getGroupIndexFromItem() because there is no count index in array $item. Count Index is only set if $item->values is type of array (see Checkable.php#L94)

image

public static function getGroupIndexFromItem($item)
    {
        $groupIndex = preg_replace('/^.*?\[(.*)\]$/', '$1', $item['name']);
        if (empty($groupIndex) or $groupIndex == $item['name']) {
            return $item['count'];
        }

        return $groupIndex;
    }
claar commented 8 years ago

Try something like this?

$groups = [];
$checked = [];

foreach(Role::all() as $role) {
    $groups[$role->name]=[
        'value' => $role->id,
        'name' => 'roles_selection['.$role->id.']',
    ];
    if ($model->hasRole($role->name)) {
      $checked[] = $role->id;
    }
}
$checkboxes = Former::checkboxes('roles_selection[]', "Roles", $groups);
foreach ($checked as $roleId) {
    $checkboxes = $checkboxes->check("roles_selection[$roleId]");
}
$form.= $checkboxes;

[Edited to fix bug]

claar commented 8 years ago

Here's a few working examples I keep around in my example file if it helps:

<?= Former::checkboxes('asd[]')->checkboxes([
    'foo' => ['name' => 'asd[0]', 'value' => 'XX'],
    'bar' => ['name' => 'asd[1]', 'value' => 'YY'],
]) ?>

<?= Former::checkbox('invmethod')->text('hi') ?>

<?= Former::checkboxes('hehe')->grouped()->checkboxes(['A' => 'foo[1]', 'B' => 'foo[2]'])->check('foo[2]') ?>
<?= Former::checkboxes('blahblah[]')->checkboxes([
    'A' => 'foo[1]',
    'B' => 'foo[2]',
    'C' => 'foo[3]',
    'D' => 'foo[4]',
])->check('foo[2]')->check('foo[3]') ?>

<?= Former::radios('radio[]')->radios(['A' => 'foo[1]', 'B' => 'foo[2]'])->check(1) ?>

<?= Former::radios('radio2[]')->radios(['A' => ['name' => 'foo[1]', 'value' => 2], 'B' => ['name' => 'foo[2]', 'value' => 3]])->check(2) ?>

<?= Former::populate(['bar' => ['A', 'C']]) ?>
<?= Former::multiselect('bar')->options(['A' => 'Apple', 'B' => 'Boy', 'C' => 'Church']) ?>
claar commented 8 years ago

For method 2, try:

$form.= Former::checkboxes('roles[]')->checkboxes(Role::lists('name','id')->all());

biwerr commented 8 years ago

Method 1: works for me, but i have one question: In Groups array the role->name is uses as key whereas role->id is used in the checked array. Is that because the Key/Value is flipped in the Checkable Trait?

Method2: @claar with this, the current user roles are not checked $form.= Former::checkboxes('roles[]',"Roles",[])->checkboxes(Role::lists('name','id')->all());

claar commented 7 years ago

Closing old issues. Please reopen if needed.