Form helper - checkboxes are checked when they should not be
PUBLISHED 2 YEARS AGO BY ROOKWOOD
Using standard illuminate/html, I'm building a form to assign users to groups. Boring, vanilla stuff. I'm trying to have the edit form show current assignments as already checked. You know, like every other such form ever. The problem I'm running into is that when running the test within the form helper, the checkbox is ALWAYS showing as checked, even if both boolean results should return null.
Example
{!! Form::checkbox('groups[]', $group->id, $user->groups->has($group->id) ? null : null, ['id' => $group->name,]) !!}
Whether or not the user is in the group, it should return null (see third argument), but the box shows as checked (checked="checked" in the html).
I tested the logic elsewhere, and it works fine, but for some reason, with this form helper, it is not working as I would expect.
Have you tried passing just
$user->groups->has($group->id) (which ought to return a boolean) as the third parameter, rather than null out of curiosity?
I had a fix for this issue back in 4.2, but I guess since the HTML and Form builders were on their way out of core, it wasn't considered a priority:
@rookwood
your 3rd parameter needs to be false to have them checked off
{!! Form::checkbox('terms', null, false, [ 'class' => 'form-control']) !!}
so it should be something like:
{!! Form::checkbox('terms', null, $user->groups->has($group->id) ? : false , [ 'class' => 'form-control']) !!}
Null or False doesn't matter. The issue ended up being a problem with form-model binding. The User object had a relation on it named groups for obvious reasons. When using form-model binding, the function checks to see if the input name has a matching model property. Since $user->groups would always return an Eloquent collection (even if empty), the actual logic to check if the relation existed wasn't evaluated. I could have put false, null, or anything else there, and the box would still show as checked.
I would never have figured this out without xdebug. That is seriously the best damn thing ever.
I've had the same issue and turned it as simple Form::open(), and manualy populated my fields.
That would work, obviously; I was just trying to use form-model binding to make it easy to have the form partial shared between create/edit actions.
It's an incredibly useful way to manage relationship assignments, and I am surprised it still hasn't been fixed in the official package (laravelcollective/html). Guess it's time for another pull request...
Hi all. Did anyone found a solution for this issue? In my case everything was working fine until I upgraded to Laravel 5.1 (from L5.0).
In my sample project, I did Laravel 5 fundamentals lessons from Laracasts with Many-to-many relation between articles and tags. Now, when I create new article obviously all checkboxes are unchecked by default but for existing articles (when I hit edit route) all are checked even when they are not assigned to this article (no relation in the article_tag table).
As @rookwood said: null or false doesn't matter. I tried to hardcode 3rd argument for testing but all checked.
This is my original part that was working before L5 upgrade.
@foreach($tags as $tag_id => $tag_name)
<section class="col-md-2">
{!! Form::checkbox('tag_list[]', $tag_id, '', ['id' => 'tag_' . $tag_id]) !!}
<label for="{!! 'tag_' . $tag_id !!}">{!! $tag_name !!}</label>
</section>
@endforeach
Currently it's an empty string. This is common for all article routes (both create and edit). Any help how to fix this?
@pmall, do you mean how my two models (Article and Tag) are related?
Tag.php
/**
* Get the articles associated with the given tag.
*
* @return \Illuminate\Database\Eloquent\Relations\BelongsToMany
*/
public function articles()
{
return $this->belongsToMany('Darwin\Article');
}
Article.php
* An article can have many tags.
* Get the tags associated with the given article.
*
* @return \Illuminate\Database\Eloquent\Relations\BelongsToMany
*/
public function tags()
{
return $this->belongsToMany('Darwin\Tag')->withTimestamps();
}
/**
* Gets a list of tags associated with this article.
*
* @return array
*/
public function getTagListAttribute()
{
return $this->tags->lists('id');
} ```
As mentioned above the problem is your model tag_list attribute has the same name as your checkbox (tag_list[]).
Here you should remove the getTagListAttribute and add a boolean method hasTag($tag_id). Then :
@foreach($tags as $tag_id => $tag_name)
<section class="col-md-2">
{!! Form::checkbox('tag_list[]', $tag_id, $article->hasTag($tag_id), ['id' => 'tag_' . $tag_id]) !!}
<label for="{!! 'tag_' . $tag_id !!}">{!! $tag_name !!}</label>
</section>
@endforeach
So there is no conflict anymore.
@pmall, could you just tell me how does "hasTag" method inside Article.php model should look like? I'm passing tag ID and I get FatalErrorException: Method name must be a string.
Thank you.
hasTag($tag_id) should return whether the article is associated with the tag or not
Thanks @pmall.
in_array($tag_id, $tags_assigned)
placed inside foreach loop did the trick.







No comments:
Post a Comment