Change Nested Comonent for a Multi-Step Form

I’ve got the concept of nested components and firing events down. Is there currently a way to swap out components when the render is hit on update?

I currently have a create.parent, create.step1, and create.step2. In the parent I’ve tried an if statement on which component to show, and creating a property to swap out step1 for step2 @livewire($this->showing) with $this->showing set to ‘create.step1’ on mount, but updating that property doesn’t change it out.

Is this more involved, or am I overlooking something simple?

Great question. I’m not sure why that wouldn’t work. Have you tried to change to a conditional and see if that would work, like the following:

@if($this->showing == 'create.step1')
@if($this->showing == 'create.step2')

Just make sure you add a “key”: @livewire('create.step1', key('step1'))

Should work fine though.

The conditional was the first way I tried, but I didn’t key it. I went a different route on that because it was smelling of spaghetti, but I will definitely remember to key it when the need comes to try it again.

@xxdalexx Would you care to share which route you went down? I need to implement the exact same pattern using v1.0.12.

I don’t remember the specifics, but I do remember that my main problem at the time was I didn’t have my whole component wrapped in a div, so the real issue was dom diffing, I just didn’t catch that before posting here. Essentially what I was doing is pretty much the same as @iAmKevinMcKee’s answer.

The following markup works on v1.0.7 but not on v.1.0.12.

I am using $set in parent component to update the value of $current_step. The markup works on initial load but when updating the value of $current_step it throws an error. See below.

Parent is loaded using:

Route::livewire('/projects/{project}/edit', 'form')->name('project.edit');


@if ($current_step === 'step-1')
    <livewire:step1 :project="$project" :key="'step1'">

@if ($current_step === 'step-2')
    <livewire:step2 :project="$project" :key="'step2'">

Javascript console error:

index.js:20 Uncaught (in promise) TypeError: Cannot read property 'data' of null
    at new Component (index.js:20)
    at onNodeAdded (index.js:333)
    at callHook (morphdom.js:35)
    at handleNodeAdded (morphdom.js:140)
    at handleNodeAdded (morphdom.js:164)
    at handleNodeAdded (morphdom.js:164)
    at handleNodeAdded (morphdom.js:164)
    at morphdom.js:407
    at morphEl (morphdom.js:219)
    at morphdom.js:463
Component @ index.js:20
onNodeAdded @ index.js:333
callHook @ morphdom.js:35
handleNodeAdded @ morphdom.js:140
handleNodeAdded @ morphdom.js:164
handleNodeAdded @ morphdom.js:164
handleNodeAdded @ morphdom.js:164
(anonymous) @ morphdom.js:407
morphEl @ morphdom.js:219
(anonymous) @ morphdom.js:463
value @ index.js:248
value @ index.js:221
value @ index.js:167
value @ index.js:143
value @ index.js:23
Connection.driver.onMessage @ index.js:9
(anonymous) @ http.js:30
Promise.then (async)
(anonymous) @ http.js:25
Promise.then (async)
sendMessage @ http.js:23
value @ index.js:34
value @ index.js:127
later @ debounce.js:50
setTimeout (async)
(anonymous) @ debounce.js:54
value @ index.js:113
(anonymous) @ node_initializer.js:169
value @ index.js:390
handler @ node_initializer.js:131

All nested components have one root div. I am struggling to troubleshoot this so any input would be valuable.

Hey @jorgen I am running into this exact same issue. Same error on the same line. I also have root components.

Did you ever find a solution?

@colinmac17 No sorry, I was never able to resolve it and reverted to use Laravel for routing in my multi-step form.

This is strange. I managed to make working a whole huge tree with each element as a separate component. Maybe you were missing to put an object ID into a key, like

:key= $project->id . '_step2'

Otherwise you might have troubles with similar IDs

In his code, he’s explicitly labeling the :key field so I don’t think duplicate IDs is the issue.