Checked checkbox not working in edit form

Hi,
As part of learning, I try to create a simple blog where, when adding a new post, I can additionally indicate the tags that I have defined in a separate table. When adding a new post, everything works fine, I have a problem that when I edit a given post, I do not see the selection on the previously selected tags. Checkbox visually does not show that it is selected. Interestingly, editing the code, I see that the checkbox is checked.

I have no idea why I can’t see the tick on the page.

update.blade.php

$all_tags = App\Models\Tag::orderBy('tag_name', 'asc')->get();
@foreach ($all_tags as $key => $tag)
     <label class="inline-flex items-center">
          <input type="checkbox" class="form-checkbox" name="tags" value="{{ $tag->tag_id }}" id="exampleFormControlInput3" wire:model="tags.{{ $tag->tag_id }}" {{ (App\Models\PostTag::where('post_id', $post_id)->where('tag_id', $tag->tag_id)->exists()) ? 'checked' : '' }}>
          <span class="ml-2">{{ $tag->tag_name }}</span>
     </label>
@endforeach

looking at the code result I can see

<input type="checkbox" class="form-checkbox" name="tags" value="9" id="exampleFormControlInput3" wire:model="tags.9" checked>

Thanks for any help

please refactor the code if possible. `

" ``` "
code

" ``` "
remove the quotations

Ok
You’re right
Done

i am not sure if you did that in blade or gave it for example.
but you can’t do all that in blade. Please do read the documentation and watch youtube videos.

I think your problem is that you are trying to control state of the checkbox using attribute checked and this is not right, you need to init checkbox state in your array variable:

$this->tags[$tag->tag_id] = App\Models\PostTag::where('post_id', $post_id)->where('tag_id', $tag->tag_id)->exists();

That’s it.

@Dimonka2 you proposition is very well. When i use this code i see checkbox is checked in edit form but when i change tags or other form ements and save form. I see exception:

“Livewire encountered corrupt data when trying to hydrate the [posts] component. Ensure that the [name, id, data] of the Livewire component wasn’t tampered with between requests.”

Hard to say, why this happens. Probably it would be easier if you could share your “save” code.

This is my component

<?php

namespace App\Http\Livewire;

use App\Models\Post;
use App\Models\PostTag;
use Illuminate\Support\Facades\Auth;
use Livewire\Component;
use Log;

class Posts extends Component
{
    public $tags = [];
    public $tag_id;
    public $posts;
    public $post_id;
    public $author_id;
    public $title;
    public $content;
    public $visible;

    public $updateMode = false;

    /**
     * The attributes that are mass assignable.
     *
     * @var array
     */
    public function render()
    {
        $this->posts = Post::all();

        return view('livewire.posts');
    }

    /**
     * The attributes that are mass assignable.
     *
     * @var array
     */
    private function resetInputFields()
    {
        $this->post_id = '';
        $this->author_id = '';
        $this->title = '';
        $this->content = '';
        $this->visible = '';
        $this->tag_id = '';
        $this->tags = '';
    }

    /**
     * The attributes that are mass assignable.
     *
     * @var array
     */
    public function store()
    {
        $validatedDate = $this->validate([
            'title' => 'required',
            'content' => 'required',
            'visible' => 'required',
        ]);

        //Save post
        $post = Post::create([
            'author_id' => Auth::id(),
            'title' => $this->title,
            'content' => $this->content,
            'visible' => $this->visible,
        ]);

        foreach ($this->tags as $key => $value) {
            PostTag::create([
                'tag_id' => $value,
                'post_id' => $post->post_id,
            ]);
        }

        session()->flash('message', 'Post Created Successfully.');

        Log::info('Post Created Successfully: '.$post->post_id);

        $this->resetInputFields();
    }

    /**
     * The attributes that are mass assignable.
     *
     * @var array
     */
    public function edit($id)
    {
        $post = Post::findOrFail($id);
        $this->post_id = $id;
        $this->author_id = Auth::id();
        $this->title = $post->title;
        $this->content = $post->content;
        $this->visible = $post->visible;
        $this->updateMode = true;
    }

    /**
     * The attributes that are mass assignable.

     *

     * @var array
     */
    public function cancel()
    {
        $this->updateMode = false;
        $this->resetInputFields();
    }

    /**
     * The attributes that are mass assignable.
     *
     * @var array
     */
    public function update()
    {
        $validatedDate = $this->validate([
            'title' => 'required',
            'content' => 'required',
            'visible' => 'required',
        ]);

        $post = Post::find($this->post_id);
        $post->update([
            'author_id' => Auth::id(),
            'title' => $this->title,
            'content' => $this->content,
            'visible' => $this->visible,
        ]);

        PostTag::where('post_id', $this->post_id)->delete();

        foreach ($this->tags as $key => $value) {
            PostTag::create([
                'tag_id' => $value,
                'post_id' => $post->post_id,
            ]);
        }

        $this->updateMode = false;

        session()->flash('message', 'Post Updated Successfully.');

        Log::info('Post Updated Successfully: '.$post->post_id);

        $this->resetInputFields();
    }

    /**
     * The attributes that are mass assignable.

     *

     * @var array
     */
    public function delete($id)
    {
        Post::find($id)->delete();
        session()->flash('message', 'Post Deleted Successfully.');
    }
}

this is my view update:

<form>
    <span class="text-green-300 text-3xl font-bold">Update post</span>
    <input type="hidden" wire:model="post_id">
    <div class="form-group mt-2">
        <label for="exampleFormControlInput1" class="block text-gray-700 text-sm font-bold mb-2">Title:</label>
        <input type="text" class="shadow appearance-none border rounded w-full py-2 px-3 text-gray-700 leading-tight focus:outline-none focus:shadow-outline" id="exampleFormControlInput1" placeholder="Enter Title" wire:model="title" maxlength="100"
            autocomplete="off">
        @error('title') <span class="text-red-500">{{ $message }}</span>@enderror
    </div>
    <div class="form-group mt-2">
        <label for="exampleFormControlInput2" class="block text-gray-700 text-sm font-bold mb-2">Content:</label>
        <textarea type="text" class="shadow appearance-none border rounded w-full py-2 px-3 text-gray-700 leading-tight focus:outline-none focus:shadow-outline" id="exampleFormControlInput2" placeholder="Enter content" wire:model="content" autocomplete="off"></textarea>
        @error('content') <span class="text-red-500">{{ $message }}</span>@enderror
    </div>
    <div class="form-group mt-2">
        <label for="exampleFormControlInput3" class="block text-gray-700 text-sm font-bold mb-2">Tags:</label>
        <div class="mt-2">
            @php
            $all_tags = App\Models\Tag::orderBy('tag_name', 'asc')->get();
            @endphp
            @foreach ($all_tags as $key => $tag)
            <label class="inline-flex items-center">
                <input type="checkbox" class="form-checkbox" name="tags[]" value="{{ $tag->tag_id }}" id="exampleFormControlInput3" wire:model="tags.{{ $key }}" {{ $this->tags[$key] = App\Models\PostTag::where('post_id', $post_id)->where('tag_id', $tag->tag_id)->exists() ? 'checked' : '' }}>
                <span class="ml-2">{{ $tag->tag_name }} {{ $tag->tag_id }}</span>
            </label>
            @endforeach
        </div>
        @error('tags') <span class="text-red-500">{{ $message }}</span>@enderror
    </div>
    <div class="form-group mt-2">
        <label for="exampleFormControlInput4" class="block text-gray-700 text-sm font-bold mb-2">Visible:</label>
        <div class="mt-2">
            <div>
                <label class="inline-flex items-center">
                    <input type="radio" class="form-radio" name="visible" value="1" id="exampleFormControlInput4"
                        wire:model="visible" />
                    <span class="ml-2">Yes</span>
                </label>
            </div>
            <div>
                <label class="inline-flex items-center">
                    <input type="radio" class="form-radio" name="visible" value="0" id="exampleFormControlInput4"
                        wire:model="visible" />
                    <span class="ml-2">No</span>
                </label>
            </div>
        </div>
        @error('visible') <span class="text-red-500">{{ $message }}</span>@enderror
    </div>
    <button wire:click.prevent="update()"
        class="inline-flex justify-center rounded-md border border-transparent px-4 py-2 my-3.5 bg-green-400 text-base leading-6 font-medium text-white shadow-sm hover:bg-green-500 focus:outline-none focus:border-green-700 focus:shadow-outline-green transition ease-in-out duration-150 sm:text-sm sm:leading-5">Update
        post</button>
    <button wire:click.prevent="cancel()"
        class="inline-flex justify-center rounded-md border border-transparent px-4 py-2 my-3.5 bg-gray-400 text-base leading-6 font-medium text-white shadow-sm hover:bg-gray-500 focus:outline-none focus:border-gray-700 focus:shadow-outline-gray transition ease-in-out duration-150 sm:text-sm sm:leading-5">Cancel
        post</button>
</form>

try to remove public property posts:

public $posts;

and just pass posts to the view:

    public function render()
    {
        return view('livewire.posts')->with('posts', Post::all() );
    }

Is the same situation

Hi @tomekn, I am facing the same issue but did not find any solution till now, did you find anything, if yes do let me know, please.
Thank you

Just for understand…why you need the “value” attribute defined if you are binding a property to the input? I think, that the magic things in livewire will load the value that have the property when render the component… can you explain me that?