0

I have a component using Laravel livewire which disappear after I submit the form inside of it.

Here is the blade content:

<div class="w-full flex flex-col justify-start items-start px-5 wow delay-100 fadeInUp">
    <h3 class="w-full flex flex-row justif-start items-center text-center text-2xl font-medium text-gray-700 mt-5 mb-0">
        {{ $survey->name }}
    </h3>
    <div class="w-full mt-5">
        <div class="prose w-full max-w-full">
            {!! $survey->description !!}
        </div>
    </div>
    <form wire:submit.prevent="submit" class="w-full mt-10">
        @foreach($survey->fields as $field)
            <div class="w-full flex flex-col justify-start items-start gap-2 mb-10" wire:key="field{{ $field->id }}">
                <span class="font-medium" @class([
                            'text-gray-700',
                            'text-danger-700' => $errors_list && $errors_list->has($field->slug)
                    ])>
                    {{ $field->name }}
                    @if($field->is_required)
                        <sup class="font-medium text-danger-700">*</sup>
                    @endif
                </span>
                <div class="prose w-full max-w-full">
                    {!! $field->description !!}
                </div>
                <div class="w-full">
                    @switch($field->type)
                        @case('text')
                            <div class="w-full flex flex-row justify-start items-center gap-2">
                                {{ html()->text($field->slug)->class($field_class)->attribute('wire:model.defer', 'model.' . $field->slug) }}
                            </div>
                            @break;
                        @case('textarea')
                            <div class="w-full flex flex-row justify-start items-center gap-2">
                                {{ html()->textarea($field->slug)->class($field_class)->attribute('wire:model.defer', 'model.' . $field->slug) }}
                            </div>
                            @break;
                        @case('select')
                            <div class="w-full flex flex-row justify-start items-center gap-2">
                                {{ html()->select($field->slug, explode(',', $field->values))->class($field_class)->attribute('wire:model.defer', 'model.' . $field->slug) }}
                            </div>
                            @break;
                        @case('multiselect')
                            <div class="w-full flex flex-row justify-start items-center gap-2">
                                {{ html()->multiselect($field->slug, explode(',', $field->values))->class($field_class)->attribute('wire:model.defer', 'model.' . $field->slug) }}
                            </div>
                            @break;
                        @case('file')
                            <div class="w-full flex flex-row justify-start items-center gap-2">
                                {{ html()->file($field->slug) }}
                            </div>
                            @break;
                        @case('checkbox')
                            @foreach(explode(',', $field->values) as $value)
                                <div class="w-full flex flex-row justify-start items-center gap-2" wire:key="{{ $field->slug . '_' . $value }}">
                                    {{ html()->checkbox($field->slug, false, $value)->id($field->slug . '_' . $value)->attribute('wire:model.defer', 'model.' . $field->slug) }}
                                    {{ html()->label($value, $field->slug . '_' . $loop->index)->class('p-0') }}
                                </div>
                            @endforeach
                            @break;
                        @case('radio')
                            @foreach(explode(',', $field->values) as $value)
                                <div class="w-full flex flex-row justify-start items-center gap-2" wire:key="{{ $field->slug . '_' . $value }}">
                                    {{ html()->radio($field->slug, false, $value)->id($field->slug . '_' . $value)->attribute('wire:model.defer', 'model.' . $field->slug) }}
                                    {{ html()->label($value, $field->slug . '_' . $loop->index)->class('p-0') }}
                                </div>
                            @endforeach
                            @break;
                        @case('date')
                            <div class="w-full flex flex-row justify-start items-center gap-2">
                                {{ html()->date($field->slug, null, __('Y-m-d'))->class($field_class)->attribute('wire:model.defer', 'model.' . $field->slug) }}
                            </div>
                            @break;
                        @case('datetime')
                            <div class="w-full flex flex-row justify-start items-center gap-2">
                                {{ html()->datetime($field->slug, null, __('Y-m-d g:i A'))->class($field_class)->attribute('wire:model.defer', 'model.' . $field->slug) }}
                            </div>
                            @break;
                        @case('time')
                            <div class="w-full flex flex-row justify-start items-center gap-2">
                                {{ html()->time($field->slug, null, __('g:i A'))->class($field_class)->attribute('wire:model.defer', 'model.' . $field->slug) }}
                            </div>
                            @break;
                    @endswitch
                </div>

            </div>

        @endforeach

        <div class="w-full flex flex-row justify-start items-center gap-2">
            <button type="submit" class="px-3 py-1 text-white bg-fprimary hover:text-fprimary hover:bg-white border border-fprimary rounded">
                {{ __('Submit') }}
            </button>
        </div>
    </form>
</div>

And the submit function, is only checking the errors:

protected function rules(): array 
{
    return $this->survey->form_rules;
}

public function submit()
{
    $this->validate();
}

All works well before the line $this->validate(), after I call this function the component disappear from the rendered view. But if the form is valid and no errors are fired when form is validated, all works well.

FYI, I am rendering the livewire component in a blade page:

<livewire:survey :survey="$survey"></livewire:survey>

I know this issue is already discussed in other questions, but I tried all the solutions without getting it work.

3 Answers 3

4

I managed to solve the problem by just removing the comments from the top of the file and just leave one root element (comments translated into DOM elements)

Sign up to request clarification or add additional context in comments.

1 Comment

this help me, i just removed the top comment from livewire blade template and it starts working
1

I found the solution which is simply to remove the <div> element that contains all the other elements and leave the <form> element as the root.

So now I have the following code in my blade file:

<form wire:submit.prevent="submit" class="w-full mt-10 w-full flex flex-col justify-start items-start">
    <h3 class="w-full flex flex-row justif-start items-center text-center text-2xl font-medium text-gray-700 mt-5 mb-0">
        {{ $survey->name }}
    </h3>
    <div class="w-full mt-5 mb-10">
        <div class="prose w-full max-w-full">
            {!! $survey->description !!}
        </div>
    </div>
    @foreach($survey->fields as $field)
        <div class="w-full flex flex-col justify-start items-start gap-2 mb-10" wire:key="field{{ $field->id }}">
            <span class="font-medium @if($errors->has('model.' . $field->slug)) text-danger-700 @else text-gray-700 @endif">
                {{ $field->name }}
                @if($field->is_required)
                    <sup class="font-medium text-danger-700">*</sup>
                @endif
            </span>
            <div class="prose w-full max-w-full">
                {!! $field->description !!}
            </div>
            <div class="w-full">
                @switch($field->type)
                    @case('text')
                        <div class="w-full flex flex-row justify-start items-center gap-2">
                            {{ html()->text($field->slug)->class($field_class)->attribute('wire:model.defer', 'model.' . $field->slug) }}
                        </div>
                        @break;
                    @case('textarea')
                        <div class="w-full flex flex-row justify-start items-center gap-2">
                            {{ html()->textarea($field->slug)->class($field_class)->attribute('wire:model.defer', 'model.' . $field->slug) }}
                        </div>
                        @break;
                    @case('select')
                        <div class="w-full flex flex-row justify-start items-center gap-2">
                            {{ html()->select($field->slug, explode(',', $field->values))->class($field_class)->attribute('wire:model.defer', 'model.' . $field->slug) }}
                        </div>
                        @break;
                    @case('multiselect')
                        <div class="w-full flex flex-row justify-start items-center gap-2">
                            {{ html()->multiselect($field->slug, explode(',', $field->values))->class($field_class)->attribute('wire:model.defer', 'model.' . $field->slug) }}
                        </div>
                        @break;
                    @case('file')
                        <div class="w-full flex flex-row justify-start items-center gap-2">
                            {{ html()->file($field->slug) }}
                        </div>
                        @break;
                    @case('checkbox')
                        @foreach(explode(',', $field->values) as $value)
                            <div class="w-full flex flex-row justify-start items-center gap-2" wire:key="{{ $field->slug . '_' . $value }}">
                                {{ html()->checkbox($field->slug, false, $value)->id($field->slug . '_' . $value)->attribute('wire:model.defer', 'model.' . $field->slug) }}
                                {{ html()->label($value, $field->slug . '_' . $loop->index)->class('p-0') }}
                            </div>
                        @endforeach
                        @break;
                    @case('radio')
                        @foreach(explode(',', $field->values) as $value)
                            <div class="w-full flex flex-row justify-start items-center gap-2" wire:key="{{ $field->slug . '_' . $value }}">
                                {{ html()->radio($field->slug, false, $value)->id($field->slug . '_' . $value)->attribute('wire:model.defer', 'model.' . $field->slug) }}
                                {{ html()->label($value, $field->slug . '_' . $loop->index)->class('p-0') }}
                            </div>
                        @endforeach
                        @break;
                    @case('date')
                        <div class="w-full flex flex-row justify-start items-center gap-2">
                            {{ html()->date($field->slug, null, __('Y-m-d'))->class($field_class)->attribute('wire:model.defer', 'model.' . $field->slug) }}
                        </div>
                        @break;
                    @case('datetime')
                        <div class="w-full flex flex-row justify-start items-center gap-2">
                            {{ html()->datetime($field->slug, null, __('Y-m-d g:i A'))->class($field_class)->attribute('wire:model.defer', 'model.' . $field->slug) }}
                        </div>
                        @break;
                    @case('time')
                        <div class="w-full flex flex-row justify-start items-center gap-2">
                            {{ html()->time($field->slug, null, __('g:i A'))->class($field_class)->attribute('wire:model.defer', 'model.' . $field->slug) }}
                        </div>
                        @break;
                @endswitch
            </div>
            @error('model.' . $field->slug)
                <span class="text-sm font-medium text-danger-700">{{ $message }}</span>
            @enderror
        </div>
    @endforeach

    <div class="w-full flex flex-row justify-start items-center gap-2">
        <button type="submit" class="px-3 py-1 text-white bg-fprimary hover:text-fprimary hover:bg-white border border-fprimary rounded">
            {{ __('Submit') }}
        </button>
    </div>
</form>

If anyone can give me some information about why this change made it works it will be great, because I don't understand why having a <div> element as root element didn't work, and <form> works.

FYI, I have other pages containing <div> root element and all is working just fine.

Comments

0

Livewire requires that there be only one HTML element at the root of a components blade view.

Having multiple root elements can mean that parts of your view won't work with Livewire correctly, if at all. The solution is to ensure that you only have one root HTML element, such as a . If you have multiple elements, then wrap everything in a or another element that suits your layout.

attention: do not use a comment before or after of root element.

So in our example from above, we have wrapped everything in a which gets the button running:

<div> <!-- Added this wrapping div -->
<div>
    Some content
</div>

<button wire:click="doSomething">Do Something</button>

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.