Search code examples
laravellaravel-livewirealpine.js

alpine js, x-model binds to wrong value when switching tabs


running into an issue with alpine js.

First of all I have a master component that allows the user to switch between two tabs

@props(['pages', 'blogs'])

<div x-data="init()" class="overview row mb30">
    <div class="pageContent__content__languages disFlex mb20 bBottom">
                    <span
                        @click.prevent='tab = "pages"'
                        :class='{ "active": tab === "pages" }'
                        class="pageContent__content__languages__item disFlex aiCenter pt10 pb10 pr10 pl10 mr10 pointer">
                     Pagina's
                    </span>
        <span
            @click.prevent='tab = "blogs"'
            :class='{ "active": tab === "blogs" }'
            class="pageContent__content__languages__item disFlex aiCenter pt10 pb10 pr10 pl10 bRadius mr10 pointer">
                         Blogs
                    </span>
    </div>

    <div x-show="tab === 'pages'">
        <x-form.edit.navigation.pages :pages="$pages" />
    </div>

    <div x-show="tab === 'blogs'">
        <x-form.edit.navigation.blogs :blogs="$blogs" />
    </div>

    <button type="button" wire:click="navigationAddToMenu" class="btn blue w100 mt10">
        Toevoegen aan menu
    </button>
</div>



@push('scripts')
    @once
        <script type='text/javascript'>
            function init() {
                return {
                    selected: @entangle('selected'),
                    tab: 'pages',
                };
            }
        </script>
    @endonce
@endpush

These tabs either display pages or blogs depending on which tab is clicked.

Inside of these blade components is just a foreach loop to display the items,

@props(['pages'])
<div style="grid-area: unset" class="pageContent__settings bRadius--lrg disFlex fdCol">
    <table class="overview__wrapper">
        <tbody class="bRadius--lrg">
        @foreach($pages as $page)
            <tr class="overview__row bBottom">
                <td class="overview__row__checkbox">
                    <input x-model='selected'  value='{{ $page->id }}' type="checkbox"
                           id="col-row-{{$loop->index}}">
                    <label for="col-row-{{$loop->index}}"></label>
                </td>
                <td class="overview__row__name lh1">
                    {{ $page->page_name }}
                </td>
            </tr>
        @endforeach
        </tbody>
    </table>
</div>

The blog blade component is nearly identical.

Now the user is able to check a checkbox to add items to their menu, this is binded using the @entangle directive and the x-model on the checkbox.

So far when the user is on the default tab pages and they select a page the correct ID is retrieved from the checkbox, BUT when the user switches tab to the blogs display, and clicks a checkbox the value is retrieved from the pages tab.

e.g.

1 page and 1 blog, page has id of 1 blog has id of 2. User is on the pages tab and clicks on the checkbox the correct value of 1 is now added to the selected array, user switches tabs to blogs and clicks the checkbox the expected behavior would be to have the id of 2 added to the selected array, but it still adds 1.

Inspecting the HTML and the loops do add unique ids to each of their items.


Solution

  • Fixed it, need to make my ids on the input more unique, instead of doing

         <input x-model='selected' value='{{ $blog->id }}' type="checkbox"
                               id="col-row-{{$loop->index}}">
                        <label for="col-row-{{$loop->index}}"></label>
    

    I added a extra identifier

         <input x-model='selected' value='{{ $blog->id }}' type="checkbox"
                               id="col-row-blogs-{{$loop->index}}">
                        <label for="col-row-blogs-{{$loop->index}}"></label>
    

    and pages for the pages.

    This fixed the issue