netojose / laravel-bootstrap-4-forms

Bootstrap 4 forms for Laravel 5/6/7/8
MIT License
183 stars 58 forks source link

fill() isn't populating checkboxes #75

Open ataylor32 opened 5 years ago

ataylor32 commented 5 years ago

Here is my form:

{!! Form::open()->route('posts.update', [$post->id])->fill($post)->patch() !!}
{!! Form::text('title', 'Title')->attrs(['maxlength' => '255'])->required() !!}
{!! Form::textarea('body', 'Body')->attrs(['class' => 'wysiwyg'])->required() !!}
<input type="hidden" name="allow_comments" value="0">
{!! Form::checkbox('allow_comments', 'Allow comments?', '1')->wrapperAttrs(['class' => 'wrapper-allow_comments']) !!}
{!! Form::submit('Update Post') !!}
{!! Form::close() !!}

The allow_comments field is a boolean field, as you can see in the migration file:

$table->boolean('allow_comments');

When I go to edit a post that has its allow_comments field set to 1, the checkbox renders as unchecked. I would expect it to render as checked.

netojose commented 5 years ago

@ataylor32 , the comparison for determinate if the field is checked or not is made using ===. So 1 !== '1' or true !== '1'

You should use the same values and types, for this check work as expected. Suggestions:

  1. Make sure you are using the same value/types for name/value fields

  2. Format you model output, using Laravel accessors:

    // Post model:
    ...
    getAllowCommentsAttribute($value){
    return $value ? '1' : null;
    }
    ...
  3. Convert model to array, and edit specific value:

    
    // on Controller:
    $data = $post->toArray();
    $data['allow_comments'] = $data['allow_comments'] ? '1' : null;

// on View: {!! Form::open()->fill($data) !!}


4. Check the value inline, using the checkbox method fourth parameter:
```php
{!! Form::checkbox('allow_comments', 'Allow comments?', '1', $post->allow_comments)!!}
  1. Check the value inline, using the checked method:
    {!! Form::checkbox('allow_comments', 'Allow comments?', '1')->checked($post->allow_comments)!!}
ataylor32 commented 5 years ago

Thanks for your time and input on this!

Since the allow_comments field is a boolean field, Laravel will have its value set to 0 or 1 (in both cases, it's an integer, not a string). So I thought I could fix this by changing the third parameter of Form::checkbox('allow_comments', 'Allow comments?', '1') from '1' (a string) to 1 (an integer), which seems to be what your first suggestion is, but the checkbox remained unchecked. So I tried your fourth and fifth suggestions, but the checkbox remained unchecked for both of those suggestions too. I didn't try your third suggestion. Finally, I tried your second suggestion, and that's what worked. This is what I used:

public function getAllowCommentsAttribute($value) {
   return $value ? '1' : '0';
}

With this approach, it's the same values as what Laravel uses by default, only as a string ('0' or '1') instead of an integer (0 or 1).

My question is: why didn't changing the third parameter of Form::checkbox('allow_comments', 'Allow comments?', '1') from '1' (a string) to 1 (an integer) work? Laravel has the model instance's allow_comments set to 1 (an integer), so shouldn't the checkbox have been checked? Is that a bug? I have a fair amount of boolean fields in the forms in my project and I'd rather not set up accessors for each of them if it can be avoided.

Thanks again for your help!

netojose commented 5 years ago

@ataylor32 you are right, no make sense change model attributes only for work a form field (is too aggressive).

I will make additional tests here (create a database, with a table, with a boolean field and try to simulate the same scenario). In my opinion, since Laravel knows this field is a boolean, maybe the Laravel apply some cast and already there is an internal accessor, and return true/false value.

I will make some tests to see the results, but I think when the field was a checkbox/radio, I can change the verification, using another approach instead of ===.

ataylor32 commented 5 years ago

Do you have a guess as to when you might have a chance to work on this? It's fine if you don't, but I thought I'd ask. Also, would it help if I created a simple project demonstrating the bug?

kaziu687 commented 5 years ago

Bug seems to exists in that line of code https://github.com/netojose/laravel-bootstrap-4-forms/blob/47eef3e73c534df1f9d2ce10cc2521b71c09b383/src/FormBuilder.php#L266

$formData[$name] (true) is compared with $value ("on")