title: laravel livewire inline edit is breaking my layout
body: <p>I have a blade template which calls a laravel livewire component which renders a table that has an inline edit component. Adding and removing rows is working but the inline edit is breaking my layout.
  <a href="https://i.stack.imgur.com/lvScr.png" rel="nofollow noreferrer"><img src="https://i.stack.imgur.com/lvScr.png" alt="Broken layour" /></a></p>
  <p>If I now manually reload the page then the layout gets fixed
  <a href="https://i.stack.imgur.com/KExek.png" rel="nofollow noreferrer"><img src="https://i.stack.imgur.com/KExek.png" alt="Fixed layout after reloading page" /></a></p>
  <p>My code as follows. First is the blade part which calls the quote component</p>
  <pre><code>&lt;!-- Quote Information --&gt;
              &lt;div class=&quot;max-w-7xl mx-auto py-10 sm:px-6 lg:px-8&quot;&gt;
                  &lt;div class=&quot;md:grid md:grid-cols-3 md:gap-6&quot;&gt;
                      &lt;div class=&quot;md:col-span-1 flex justify-between&quot;&gt;
                          &lt;div class=&quot;px-4 sm:px-0&quot;&gt;
                              &lt;h3 class=&quot;text-lg font-medium text-gray-900&quot;&gt;Quote Information&lt;/h3&gt;
  
                              &lt;p class=&quot;mt-1 text-sm text-gray-600&quot;&gt;
                                  Enter details for expected hours and hourly rate charged.
                              &lt;/p&gt;
                          &lt;/div&gt;
                      &lt;/div&gt;
  
                      &lt;div class=&quot;mt-5 md:mt-0 md:col-span-2&quot;&gt;
                          &lt;div class=&quot;px-4 py-5 bg-white sm:p-6 shadow sm:rounded-tl-md sm:rounded-tr-md&quot;&gt;
                              @livewire(&quot;quote-table&quot;, ['job' =&gt; $job])
                          &lt;/div&gt;
                          &lt;div
                              class=&quot;flex items-center justify-end px-4 py-3 bg-gray-50 text-right sm:px-6 shadow sm:rounded-bl-md sm:rounded-br-md&quot;&gt;
                              &lt;button type=&quot;submit&quot;
                                      class=&quot;inline-flex items-center px-4 py-2 bg-gray-800 border border-transparent rounded-md font-semibold text-xs text-white uppercase tracking-widest hover:bg-gray-700 active:bg-gray-900 focus:outline-none focus:border-gray-900 focus:ring focus:ring-gray-300 disabled:opacity-25 transition&quot;
                                      wire:loading.attr=&quot;disabled&quot; wire:target=&quot;photo&quot;&gt;
                                  Save
                              &lt;/button&gt;
                          &lt;/div&gt;
                          &lt;div class=&quot;hidden sm:block&quot;&gt;
                              &lt;div class=&quot;py-8&quot;&gt;
                                  &lt;div class=&quot;border-t border-gray-200&quot;&gt;&lt;/div&gt;
                              &lt;/div&gt;
                          &lt;/div&gt;
                      &lt;/div&gt;
                  &lt;/div&gt;
              &lt;/div&gt;
  </code></pre>
  <p>My QuoteTable component (QuoteTable.php)</p>
  <pre><code>&lt;?php
  
  namespace App\Http\Livewire;
  
  use App\Models\Job;
  use App\Models\QuoteItem;
  use App\Models\WorkGroup;
  use Livewire\Component;
  
  class QuoteTable extends Component
  {
      public int $i = 1;
      public string $inputSearchString = '';
      public WorkGroup $work_group;
      public int $quote_id;
      public string $title;
      public string $time;
      public int $workgroup_id;
      public string $totalHours = '00:00';
      public float $totalQuote = 0.0;
      public Job $job;
  //    public Quote $quote;
      public QuoteItem $quoteItem;
  
      protected $listeners = ['refreshTotals'];
  
      public function mount( Job $job )
      {
          $quoteItems = QuoteItem::where( 'quote_id', $job-&gt;number )-&gt;get();
          $this-&gt;number = $job-&gt;number;
          $this-&gt;quoteItems = $quoteItems;
      }
  
      public function selectWorkGroup(WorkGroup $work_group)
      {
          if ( $work_group-&gt;id &gt; 0 ) {
              $this-&gt;workgroup_id = $work_group-&gt;id;
              $this-&gt;work_group = $work_group;
              $this-&gt;title = $work_group-&gt;title;
              $this-&gt;inputSearchString = '';
              // Now we can update the quote item by creating a new one or removing the existing one
              $item = QuoteItem::where( 'quote_id', $this-&gt;number )
                  -&gt;where( 'work_group_id', $this-&gt;workgroup_id )
                  -&gt;first();
              if ( isset( $item ) ) {
                  $item-&gt;delete();
              } else {
                  $item = new QuoteItem();
                  $item-&gt;addItem( $this-&gt;work_group, $this-&gt;number );
              }
  
              $this-&gt;refreshTotals();
              $this-&gt;quoteItems = QuoteItem::where( 'quote_id', $this-&gt;number )-&gt;get();
  
          }
      }
  
      public function render()
      {
          $workGroups = WorkGroup::where( 'user_id', '&gt;', 0 )-&gt;orderBy( 'title', 'asc' )-&gt;get();
          $this-&gt;refreshTotals();
          return view( 'livewire.quote-table' )-&gt;with( 'workGroups', $workGroups );
      }
  
      /**
       * @return void
       */
      public function refreshTotals(): void
      {
          $this-&gt;totalHours = 0.00;
          $this-&gt;totalQuote  = 0.00;
          foreach ($this-&gt;quoteItems as $item) {
              //$rows[] = $item-&gt;id;
              $this-&gt;totalQuote  += $item-&gt;total;
              $this-&gt;totalHours += $this-&gt;toFloat( $item-&gt;hours );
          }
      }
  
      private function toFloat( $timeString ) {
          list ( $h, $m ) = explode(':', $timeString );
  
          return $h + ( $m / 60 );
      }
  }
  </code></pre>
  <p>The blade for this component (quote-table.blade.php)</p>
  <pre><code>&lt;div class=&quot;col-span-6 sm:col-span-4&quot;&gt;
      &lt;label class=&quot;block font-medium text-sm text-gray-700&quot; for=&quot;client_id&quot;&gt;
          Work Group
      &lt;/label&gt;
      &lt;?php $items = array() ?&gt;
  
      &lt;?php foreach( $quoteItems as $item ) {
          $items[] = $item-&gt;work_group_id;
      }
  
      foreach( $workGroups as $workGroup ) {
          if( in_array( $workGroup-&gt;id, $items) ) {
              ?&gt;
              &lt;input wire:click=&quot;selectWorkGroup( {{ $workGroup-&gt;id }} )&quot; type=&quot;checkbox&quot; name=&quot;teams[{{ $workGroup-&gt;id }}]&quot;  checked=&quot;checked&quot; value=&quot;{{ $workGroup-&gt;id }}&quot;&gt; {{ $workGroup-&gt;title }}
              &lt;?php
          } else {
              ?&gt;
              &lt;input wire:click=&quot;selectWorkGroup( {{ $workGroup-&gt;id }} )&quot; type=&quot;checkbox&quot; name=&quot;teams[{{ $workGroup-&gt;id }}]&quot; value=&quot;{{ $workGroup-&gt;id }}&quot;&gt; {{ $workGroup-&gt;title }}
              &lt;?php
          }
      } ?&gt;
  
      &lt;table id=&quot;jobs&quot; class=&quot;table table-striped table-bordered table-hover&quot;&gt;
          &lt;thead&gt;
              &lt;td&gt;Team&lt;/td&gt;
              &lt;td&gt;Hours&lt;/td&gt;
              &lt;td&gt;Rate&lt;/td&gt;
              &lt;td&gt;Total&lt;/td&gt;
          &lt;/thead&gt;
          &lt;tbody&gt;
          @foreach( $quoteItems as $row )
              &lt;tr&gt;
                  &lt;td&gt;
                      {{ $row-&gt;team }}
                  &lt;/td&gt;
                  &lt;td&gt;
                      @livewire( 'inline-edit', ['item' =&gt; $row, 'type' =&gt; 'hours', 'number' =&gt; $job-&gt;number] )
                  &lt;/td&gt;
                  &lt;td&gt;
                      @livewire( 'inline-edit', ['item' =&gt; $row, 'type' =&gt; 'rate', 'number' =&gt; $job-&gt;number] )
                  &lt;/td&gt;
                  &lt;td&gt;
                      @livewire( 'inline-edit', ['item' =&gt; $row, 'type' =&gt; 'total', 'number' =&gt; $job-&gt;number] )
                  &lt;/td&gt;
              &lt;/tr&gt;
          @endforeach
          &lt;/tbody&gt;
          &lt;tfoot&gt;
              &lt;td&gt;&lt;/td&gt;
              &lt;td&gt;{{ $totalHours }}&lt;/td&gt;
              &lt;td&gt;&lt;/td&gt;
              &lt;td&gt;£{{ $totalQuote }}&lt;/td&gt;
          &lt;/tfoot&gt;
      &lt;/table&gt;
  &lt;/div&gt;
  </code></pre>
  <p>And as can be seen in this there are 3 inline edit calls per row and the parameters passed to this determine which field to use. The component (InlineEdit.php) is as follows:</p>
  <pre><code>&lt;?php
  
  namespace App\Http\Livewire;
  
  use App\Models\QuoteItem;
  use Illuminate\Support\Str;
  use Livewire\Component;
  
  /**
   * @property mixed $work_group_id
   * @property $number
   * @property mixed $team
   * @property string $rate
   * @property string $hours
   * @property string $total
   */
  class InlineEdit extends Component
  {
      public int $rowId;
      public string $shortId;
      public string $origName;
      public string $newName;
      public string $isName;
      public string $timeOrText;
      //public $type;
  
      public function mount(QuoteItem $item, $type, $number )
      {
          $this-&gt;number = $number;
          $this-&gt;rowId = $item-&gt;id;
          $this-&gt;work_group_id = $item-&gt;work_group_id;
          $this-&gt;team = $item-&gt;team;
          $this-&gt;rate = $item-&gt;rate;
          $this-&gt;hours = $item-&gt;hours;
          $this-&gt;total = $item-&gt;total;
          $this-&gt;shortId = strtolower( $item-&gt;team ) . '_' . $type;
  
          $this-&gt;timeOrText = 'text';
          if ( $type === 'hours' ) {
              $this-&gt;origName = $item-&gt;hours;
              $this-&gt;timeOrText = 'time';
          } elseif( $type === 'rate' ) {
              $this-&gt;origName = $item-&gt;rate;
  
          } else {
              $this-&gt;origName = $this-&gt;total;
          }
  
          $item-&gt;{$this-&gt;shortId} = $this-&gt;origName;
  
          $this-&gt;type = $type;
  
          $this-&gt;init( $item, $type );
      }
  
      public function render()
      {
          return view('livewire.inline-edit');
      }
  
      public function submit()
      {
          $item = QuoteItem::where( 'work_group_id', $this-&gt;work_group_id )-&gt;where( 'quote_id', $this-&gt;number )-&gt;first();
          //$row = new \stdClass();
          $newName = (string)Str::of($this-&gt;newName)-&gt;trim()-&gt;substr(0, 100); // trim whitespace &amp; more than 100 characters
          //$newName = $newName === $this-&gt;shortId ? null : $newName; // don't save it as widget name it if it's identical to the short_id
          if ( $this-&gt;type === 'hours' ) {
              $item-&gt;hours = $newName;
          } elseif ( $this-&gt;type === 'rate' ) {
              $item-&gt;rate = $newName;
          } else {
              $item-&gt;total = $newName;
          }
          $item-&gt;total = $item-&gt;getItemTotal();
          $item-&gt;save();
  
          $origName = $newName ?? null;
          $type = $this-&gt;type;
  
          $this-&gt;init( $item, $type ); // re-initialize the component state with fresh data after saving
          $this-&gt;dispatchBrowserEvent('notify', \Str::studly($this-&gt;type).' successfully updated!');
          $this-&gt;emit( 'refreshTotals' );
      }
  
      private function init( QuoteItem $item, $type )
      {
          $this-&gt;rowId = $item-&gt;id;
          if ( $type === 'hours' ) {
              $this-&gt;origName = $item-&gt;hours;
              $this-&gt;timeOrText = 'time';
              $this-&gt;isName = $item-&gt;hours ?? false;
          } elseif ( $type === 'rate' ) {
              $this-&gt;origName = $item-&gt;rate;
              $this-&gt;timeOrText = 'text';
              $this-&gt;isName = $item-&gt;rate ?? false;
          } else {
              $this-&gt;origName = $item-&gt;total;
              $this-&gt;timeOrText = 'text';
              $this-&gt;isName = $item-&gt;total ?? false;
          }
  
          $item-&gt;{$this-&gt;shortId} = $this-&gt;origName;
  
          $this-&gt;newName = $this-&gt;origName;
  
          $this-&gt;type = $type;
      }
  }
  </code></pre>
  <p>and its associated blade file (inline-edit.blade.php)</p>
  <pre><code>&lt;div&gt;
      &lt;div
          x-data=&quot;
          {
               isEditing: false,
               isName: '{{ $isName }}',
               focus: function() {
                  const textInput = this.$refs.textInput;
                  textInput.focus();
                  textInput.select();
               }
          }
      &quot;
          x-cloak
      &gt;
          &lt;div
              class=&quot;p-2&quot;
              x-show=!isEditing
          &gt;
          &lt;span
              x-bind:class=&quot;{ 'font-bold': isName }&quot;
              x-on:click=&quot;isEditing = true; $nextTick(() =&gt; focus())&quot;
          &gt;{{ $origName }}&lt;/span&gt;
          &lt;/div&gt;
          &lt;div x-show=isEditing class=&quot;flex flex-col&quot;&gt;
              &lt;form class=&quot;flex&quot; wire:submit.prevent=&quot;submit&quot;&gt;
                  &lt;input
                      id=&quot;{{ $shortId }}&quot;
                      type=&quot;{{$timeOrText}}&quot;
                      class=&quot;&quot;
                      placeholder=&quot;&quot;
                      x-ref=&quot;textInput&quot;
                      wire:model.lazy=&quot;newName&quot;
                      x-on:keydown.enter=&quot;isEditing = false&quot;
                      x-on:keydown.escape=&quot;isEditing = false&quot;
                  &gt;
                  &lt;button
                      type=&quot;button&quot;
                      class=&quot;px-1 ml-2 text-3xl font-bold text-red-600&quot;
                      title=&quot;Cancel&quot;
                      x-on:click=&quot;isEditing = false&quot;
                  &gt;✘&lt;/button&gt;
                  &lt;button
                      type=&quot;submit&quot;
                      class=&quot;px-1 ml-1 text-3xl font-bold text-green-600&quot;
                      title=&quot;Save&quot;
                      x-on:click=&quot;isEditing = false&quot;
                  &gt;✔&lt;/button&gt;
              &lt;/form&gt;
              &lt;small class=&quot;text-xs&quot;&gt;Enter to save, Esc to cancel&lt;/small&gt;
          &lt;/div&gt;
      &lt;/div&gt;
      &lt;input type=&quot;hidden&quot; name=&quot;{{ $shortId }}&quot; id=&quot;{{ $shortId }}&quot; value=&quot;{{ $origName }}&quot;/&gt;
  &lt;/div&gt;
  </code></pre>
  <p>The majority of this works. If i click a checkbox the row for that type is shown, clicking again removes it. If i click on one of the 3 inner fields on a row i can edit the data and submit it. The data is saved to the correct item and I then refresh the totals via an emit in the InlineEdit.php submit function. At this point it breaks the layout and needs a full page reload to fix it. I've spent some considerable time trying to get this to work but it seems I am hitting a brick wall.</p>
  <p>thanks</p>