Search code examples
laravellaravel-livewirelaravel-jetstream

Pass Content from View to Livewire Component


I am kind of new to livewire. There is one thing I don't quite get. I know I can pass data to a livewire component by binding the value in the livewire tag. But what if I want to pass a whole content block to the component? To clarify what I mean let's say I have a component "card-wrapper":

<div class="card-wrapper">
 <!-- Content shall go here -->
</div>

Sure I can pass data to the component like

<livewire:card-wrapper :some_variable="$some_content" />

This is handy enough for passing data through my Component Controller. But what if I want to pass a content block like this to the component?

<div>
  <h2>Hello</h2>
  <img src="hello.jpg" />
</div>

Is there something like

card.blade.php

<div class="card-wrapper">
 {{ $slot }}
</div>

my-page.blade.php

<livewire:card-wrapper>
  <div>
    <h2>Hello</h2>
    <img src="hello.jpg" />
  </div>
</livewire>

so that the output would be

<div class="card-wrapper">
  <div>
    <h2>Hello</h2>
    <img src="hello.jpg" />
  </div>
</div>

like for the normal blade components? I hope I could explain what I need properly. Thanks for any help in advance!


Solution

  • I can think of different ways but my favorite is to simply have the Livewire php class provide it for me. It seems to me you are not utilizing how amazingly Livewire communicates back and forth with the server and client side... The simply answer to your question is not even Livewire related, but I know how with alpine, livewire, backend, blade, etc it can be confusing at first. You can define an entire HTML element in blade as variables easily! There are two things I think you might be missing. One is that to render in Blade an HTML you cant do: {{$slot}} It has to be: {!! $slot !!} second you can even pass an entire blade template from your view:

     $this->slot= view('livewire.'.$view)->render();
       
    

    You can not only have the $slot type of functionality but you could have blade components so for instance you can have a :

    <livewire:card-wrapper :some_variable="$my_html_rendered_from_an_entire_view" />
    

    my-page.blade.php

    <div class="card-wrapper">
        <h2>Hello</h2>
        <img src="hello.jpg" />
      </div>
    

    and even another-page.blade.php

    <?php
      //now this might not be a good place to put this but I am making a point, you can do stuff in your \App\HTTP\Livewire class
      $user = \App\Models\User::find($even_an_id_passed)->find();
    ?>
    <div class="card-wrapper">
        <h2>Hello {{$user->name}}</h2>
        <img src="hello.jpg" />
    </div>
    

    LivewireClass.php

    namespace App\Http\Livewire;
     
    use Livewire\Component;
    
    class myLiveWire extends Component
    {
        
        public $my_html_rendered_from_an_entire_view = null;
        
        protected $listeners = ['toEvenGetYourStuffFromOtherLivewires' => 'getHtml'];
        
        public function getHtml($view='my-page.blade.php',$uid=NULL,$params=[]) {
            $this->my_html_rendered_from_an_entire_view = view('livewire.'.$view)->with('uid',$uid)->render();
        }
        
        public function render()
        {
            return view('livewire.sidebar');//don't even need ->with() for $this vars
    
        }
    }
    

    Now back to where you wanted to call this variable you could even do something like inside whatever livewire:card-wrapper is:

    <div>
    {$my_html_rendered_from_an_entire_view}
    </div>