Be part of JetBrains PHPverse 2026 on June 9 – a free online event bringing PHP devs worldwide together.

WallyJ's avatar

Pass Variable to Included Livewire Component

I have an include that includes a list of tasks. I am converting that list of tasks to a Livewire component.

I have read how to pass variables to a component here: https://laravel-livewire.com/docs/mount-method/

But I can't get the data to be recognized as part of the include. Is it a bad idea to use a Livewire component as part of an include?

Includes always inherit the variables of the parent. It seems that Livewire components stand on their own as far as data is concerned.

Also, the functions of "render" and "mount" are confusing. In a Laravel controller, the 'return view' statement is in the same part of the controller where the data is handled.

Any words of wisdom? Thanks!

0 likes
32 replies
bugsysha's avatar

This is how you pass to a nested component

@livewire('user-profile', $user)

And if you are using includes in blade then you can be explicit in your Livewire component by saying

@include('user-profile', ['user' => $user])
1 like
WallyJ's avatar

Thanks for the tip, though I'm still having trouble.

My relationship trail looks like this: Contact->Deal->Task

And the relationships are set up properly and the queries work fine everywhere. I am simply trying to add Livewire functionality.

My main view for a Contact has an include for deals.index:

@include('deals.index')

This file has a div that calls the new livewire view through its controller:

<div>
@livewire('tasks', $deals)
</div>

I added the variable $deals here which are associated with the tasks I want in my unordered list in my 'Tasks' Livewire component.

My livewire controller file looks like this:

<?php

namespace App\Http\Livewire;

use Livewire\Component;
use Illuminate\Http\Request;
use App\User;
use App\Contact;
use App\Deal;
use App\Task;

class Tasks extends Component
{
    public function render()
    {
        return view('livewire.tasks');
    }
}

My Livewire component view looks like this:

<div>
    Livewire Tasks
    <ul class="list-group">
        @foreach($deal->tasks as $task)
        <li class="list-group-item">
            <input type="checkbox" class="mr-4">
            <p>{{Carbon\Carbon::parse($task->taskduedate)->format('m/d/Y')}} - {{$task->tasktext}}</p>
        </li>
        @endforeach
    </ul>
    <ul class="list-group">
        <li class="list-group-item d-flex justify-content-between align-items-center">
            <div>
                <input type="checkbox" class="mr-4">
                Finish livewire screencast
            </div>
        </li>
        <li class="list-group-item d-flex justify-content-between align-items-center">
            <div>
                Mow the lawn
            </div>
        </li>
        <li class="list-group-item d-flex justify-content-between align-items-center">
            <div>
                Buy toilet paper
            </div>
        </li>
    </ul>
</div>

My view has a dynamic list followed by a static list I was using for testing.

The error I get is: Undefined variable: deal on this line:

@foreach($deal->tasks as $task)

I know that the $deals variable is being passed, but it seems that the relationship between Deals and Tasks is not picked up in a Livewire component the same way it is in a Blade view.

Should I put everything into a Livewire component with its controller and view, or is there something I am not passing correctly? Thanks!

bugsysha's avatar

But you are passing $deals to the Livewire component and not singular $deal as shown

<div>
@livewire('tasks', $deals)
</div>

So you need to wrap it within another foreach

@foreach($deals as $deal)
@foreach($deal->tasks as $task)
// do stuff
@endforeach
@endforeach
WallyJ's avatar

Yes. Isn't that why @foreach statements have ($deals as $deal) in them before using $deal->tasks? Again, this works in a regular view just fine. It pulls up the data. No variable errors. Only with Livewire.

bugsysha's avatar

I do not see that you have two foreach loops in what you've shown above? What am I missing?

Anyway Livewire components are designed for reactivity, how is this component reactive? You are not fetching the data from it nor you are doing any manipulation?

WallyJ's avatar

Sorry. Let me clarify. I did this in the main view that includes the Livewire tasks view. It has the first @foreach loop:

@foreach($deals as $deal)
bugsysha's avatar

Then you are wrong again, you have to change

@livewire('tasks', $deals)
// to
@livewire('tasks', $deal)
WallyJ's avatar

Ok. Made the change to:

@livewire('tasks', $deal)

Still get the Undefined variable: deal error on this line:

@foreach($deal->tasks as $task)

Do I need to add anything to the Livewire controller?

bugsysha's avatar

Try this

@livewire('tasks', $deal, key($deal->id))
bugsysha's avatar

Should I put everything into a Livewire component with its controller and view, or is there something I am not passing correctly? Thanks!

Probably yes. That is how it was designed to work.

bugsysha's avatar

Just move everything to Livewire component and it will work. It has to work.

WallyJ's avatar

I was thinking about doing that. Could it be that I need to do something with the mount() method to get the data passed over, besides the render() method for the view?

The mount() method example at https://laravel-livewire.com/docs/mount-method/ seems strange to me, but maybe it makes sense to you.

WallyJ's avatar

In their example, the variable sent is 'contactId', but the variable received by the mount function is 'id'. Then they run a query to define 'Contact', the defines the fields individually.

Doesn't seem like a practical Laravel style example.

bugsysha's avatar

By the looks of it, it seems that you have to pass following:

@livewire('tasks', $deal->id)
    public $deal;

    public function mount($dealId)
    {
        $this->deal = Deal::find($dealId);
    }

1 like
WallyJ's avatar

Good idea.

Though now I get this error:

Livewire component's [tasks] public property [deal] must be of type: [numeric, string, array, null, or boolean]. Only protected or private properties can be set as other types because JavaScript doesn't need to access them.

Because 'deal' is a collection, which I have been taught by Laravel to use Relationships along with Collections for all of my data. But now the Laravel Javascript PHP miracle can't use Collections?

What is my life?

WallyJ's avatar

I can't even dd($deal) at the top of the Livewire component controller in the mount() method or the render() method to make sure it is receiving the variable '$deal'. When I try it tells me gives me the 'Undefined variable' error again. So, either the variable is undefined, or it's a collection, which Livewire can't use.

Huh?

WallyJ's avatar

I like that idea. But by "move everything", do you mean my whole app, or just the contact view, which includes the deal view, which includes the tasks Livewire component?

bugsysha's avatar

I like that idea. But by "move everything", do you mean my whole app, or just the contact view, which includes the deal view, which includes the tasks Livewire component?

Everything from the top level foreach loop.

@livewire('deals')
WallyJ's avatar

Got it. I'll give that a try. I'll let you know how it goes. :)

bugsysha's avatar

It is pretty easy. I'm sure it will go well.

1 like
WallyJ's avatar

Ok, so now I can get the $deals to dd() properly from the Deals.php Livewire controller, and it includes the underlying tasks collection, so the data is getting to the controller, but I can't get it into the Livewire view.

I get the "Undefined variable: deals" error.

Here is my updated code:

Line calling the Livewire component:

 @livewire('deals', $deals)

Livewire Controller:

<?php

namespace App\Http\Livewire;

use Livewire\Component;

class Deals extends Component
{
    public $deals;

    public function mount($deals)
    {
        return view('livewire.tasks', [
            'deals' => $deals
        ]);
    }
}

Livewire View:

@foreach($deals as $deal)
    <div class="col-md-6">
        <div class="well">
            <div class="row">
                <div class="col-md-9"><h3><a href="/deals/{{$deal->id}}">{{$deal->dealtype}}</a></h3></div>
                <div class="col-md-3">
                    <button type="button" class="btn btn-primary btn-sm" data-toggle="modal" data-contactid="{{$contact->id}}" data-dealid="{{$deal->id}}" data-dealtype="{{$deal->dealtype}}" data-price="{{$deal->price}}" data-commissionpercentage="{{$deal->commissionpercentage}}" data-target="#editDealModal">Edit</button>
                    <a href="link_to_action('DealsController@destroy', $title, $parameters = array(), $attributes = array());">Delete</a>
                </div>
            </div>

            <div class="row">
                <div class="col-md-6"><h4>Price: {{moneyformat($deal->price)}}</h4></div>
                <!-- Calculation for Commission dollars from Price and CommissionPercentage -->
                <div class="col-md-6"><h5> Comm: {{moneyformat($deal->price * $deal->commissionpercentage * .01)}} - ({{$deal->commissionpercentage}}%)</h5></div>
            </div>
            <div class="tasks">
                <h5>Tasks</h5>
                <div class="card-block">
                    {!! Form::open(['route' => ['tasks.store']]) !!}
                    {{ csrf_field() }}
                    <div class="form-group">
                        {{Form::textarea('tasktext', null, array('placeholder' => 'Your task here', 'class' => 'form-control', 'rows' => '2'))}}
                    </div>
                    <div class="form-group">
                            {{Form::text('taskduedate', null, array('placeholder' => 'Due Date', 'class' => 'form-control', 'data-provide' => 'datepicker', 'data-date-autoclose' => 'true', 'data-date-today-highlight' => 'true'))}}
                    </div>
                    <div class="form-group">
                        {{Form::submit('Add Task', array('class' => 'btn btn-primary'))}}
                    </div>
                    <input type="hidden" name="deal_id" value="{{ $deal->id }}">
                    {{Form::close()}}
                </div>
                <div>
                    Livewire Tasks
                    <ul class="list-group">
                        @foreach($deal->tasks as $task)
                        <li class="list-group-item">
                            <input type="checkbox" class="mr-4">
                            <p>{{Carbon\Carbon::parse($task->taskduedate)->format('m/d/Y')}} - {{$task->tasktext}}</p>
                        </li>
                        @endforeach
                    </ul>
                    <ul class="list-group">
                        <li class="list-group-item d-flex justify-content-between align-items-center">
                            <div>
                                <input type="checkbox" class="mr-4">
                                Finish livewire screencast
                            </div>
                        </li>
                        <li class="list-group-item d-flex justify-content-between align-items-center">
                            <div>
                                Mow the lawn
                            </div>
                        </li>
                        <li class="list-group-item d-flex justify-content-between align-items-center">
                            <div>
                                Buy toilet paper
                            </div>
                        </li>
                    </ul>
                </div>
            </div>
        </div>
    </div>
@endforeach

So, again, if I add:

dd($deals);

to the Livewire Deals Controller, it dumps a collection of 2 arrays. A deal in each array, with that tasks showing as an array under "relations", as their own collection, as I believe it is supposed to, exactly as it should be in the DB.

However, this data is not getting to the view.

eballeste's avatar

i see where your problem is, you were doing this:

        return view('livewire.tasks', [
            'deals' => $deals
        ]);

when you should of been doing this:

        return view('livewire.tasks', [
            'deals' => $this->deals
        ]);
1 like
bugsysha's avatar

Why don't you retrieve them from Livewire Component itself and not to pass it?

WallyJ's avatar

I don't know what that means. How do I do that?

WallyJ's avatar

Unless you mean, why don't I run the queries within the Livewire component to lookup the values I want?

Because I already have ran the queries, in the previous view that calls the Livewire component.

And it defeats the DRY principle of development. The $deals collection is sitting in the Livewire controller. It should be easily passed to the view, but I have tried every syntax I can think of. Livewire is made for Laravel. It should work with collections and arrays easily.

How do I get that data of the $deals collection into the view?

bugsysha's avatar

I haven't had any issues when I tried it. Don't see your point on moving the query to Livewire component since you will remove it from Laravel's controller.

Soychester's avatar

I had the same situation, I solved the problem after 8 hours. The problem is because you got a collection so you only need to convert your collection to array and done. All of this in Mount function.

Next

Please or to participate in this conversation.