Passing Hidden Field value back to Livewire component is Null

From my old PHP form days, I have a form within a @foreach loop that has a hidden field to capture the deal id, so I can send that on to be used by the controller.

However, if I add

wire:model="deal_id"

to the input field, the deal id no longer shows in the field and the dd($this->deal_id) shows null. I tested this with a text field instead of a hidden field so I could see the value.

How do I get the deal is from each @foreach loop sent back to the component? Because of the @foreach loop I have multiple forms on the page, but the “Add Task” button needs to add the task via the correct deal id.

For reference:

Foreach section in my component view:

@foreach($this->contacts['deals'] as $deal)
<div class="col-md-6">
        <div class="row">
            <div class="col-md-9"><h3><a href="/deals/{{$deal['id']}}">{{$deal['dealtype']}}</a></h3></div>
            <h1>DealID: {{ $deal['id'] }}</h1>
            <div class="col-md-3">
                <a href="link_to_action('DealsController@destroy', $title, $parameters = array(), $attributes = array());">Delete</a>
            </div>
        </div>
        <div class="tasks">
            <h5>Tasks</h5>
            <div class="card-block">
            <div class="form-row">
                <div class="input-group form-group col-md-9">
                    <input type="text" name="tasktext" class="form-control" id="tasktext" placeholder="New Task" wire:model="tasktext">
                </div>
                <div>
                    <input type="text" value="{{ $deal['id'] }}" wire:model="deal_id">
                </div>
                <div class="form-group col-md-3" id="datepickerfield">
                    <div class="input-group date taskduedatepicker">
                    <input type="text" name="taskduedate" class="form-control" id="taskduedate" placeholder="Due Date" data-provide="datepicker" data-date-autoclose="true" data-date-today-highlight="true" autocomplete="off">
                    </div>
                </div>
            </div>
            <div class="form-row">
                <div class="form-group col-md-12">
                    <input type="hidden" name="deal_id" id="deal_id" value="{{ $deal['id'] }}" wire:model="dealid">
                    <button class="btn btn-primary" wire:click="addTask" type="submit">Add</button>
                </div>
            </div>
            </div>
            <div>
                <ul class="list-group">
                    @foreach($deal['tasks'] as $task)
                    <li class="list-group-item d-flex justify-content-between align-items-center">
                        <div>
                            <input type="checkbox" class="mr-4">
                            {{Carbon\Carbon::parse($task['taskduedate'])->format('m/d/Y')}} - {{$task['tasktext']}}
                        </div>
                        <div>
                            <form class=".mb-0" action="#" method="POST">
                                @csrf
                                <button class="btn btn-sm btn-danger">&times;</button>
                            </form>
                        </div>
                    </li>
                    @endforeach
                </ul>
            </div>
        </div>
</div>
@endforeach

And my controller:

<?php

namespace App\Http\Livewire;

use Livewire\Component;
use App\Task;

class Contactshow extends Component
{

    public $contacts;
    public $tasktext;
    public $deal_id;
    public $taskduedate;

    public function mount($contacts)
    {
        $this->contacts = $contacts;
    }

    public function render()
    {
        return view('livewire.contactshow');
    }

    public function addTask()
    {
        dd($this->deal_id);
        Task::create([
            'deal_id' => $this->deal_id,
            'tasktext' => $this->tasktext,
            'taskduedate' => $this->taskduedate,
        ]);
    }
}

Isn’t it easier to

@foreach($this->contacts['deals'] as $deal)
     @livewire('deal_task', $deal, key($deal['id']))
@endforeach

And make a new “deal_task” component?

Maybe. It might be easier. That’s why I asked. I will separate the deals into their own component using this method and let you know if that helps.

I am having to do a lot of converting my Laravel logical thinking into Livewire. In straight Laravel, I would never have to add the complexity of separate components, so in a way, it doesn’t sound more “simple”, but it may indeed be “easier”. I appreciate your suggestion.

1 Like

I added the “deals” component and the @livewire code loads the component, but within the view, I get an error on this line:

<div class="col-md-9"><h3><a href="/deals/{{$deal['id']}}">{{$deal['dealtype']}}</a></h3></div>

The error says:
Undefined variable: deal (View…

I thought I just passed the variable $deal to the component with the code you suggested. Why am I receiving this error?

Here is my Livewire controller:

<?php

namespace App\Http\Livewire;

use Livewire\Component;

class Deals extends Component
{
    public $deal;

    public function mount($deal)
    {
        $this->deal = $deal;
    }

    public function render()
    {
        return view('livewire.deals');
    }
}

And if you use $this->deal?

<div class="col-md-9"><h3><a href="/deals/{{$this->deal['id']}}">{{$this->deal['dealtype']}}</a></h3></div

Yes. That worked. Thanks!

However, all of this coding, which requires so much $this-> everywhere goes against the advance of Laravel, and the use of Eloquent Relationships.

As I convert my blade views to Livewire Components, I keep having to pass variables everywhere, and then my code can’t find the relationships it is expecting, so I have to pass more variables. Maybe this is necessary because Livewire is ultimately translating to Javascript, but if Laravel can put relationships into PHP, why can’t Livewire put them into Javascript?

One day we will all look back and laugh at the hoops we used to go through in order to simply get our data to post to the DB, and to the page, without a refresh of that page. I know there is a lot more Javascript can do, but that is the basics of what I’m trying to accomplish and why I am using Livewire.

So I have this basic relationship chain:
Users->Contacts->Deals->Tasks

When just using blade, I can use $users, $contacts, $deals, and $tasks, and then use $contacts->deal, $deals->task->tasktext, etc… all over the place, inside and outside of @foreach statements, etc.

I know I’m new at Livewire, and that it is also “new” and growing, but I hope it grows back into the beautiful things I love about Laravel, rather than looking so much like VueJS.

Laravel exists because PHP was too cumbersome. In my opinion, all Javascript, and it’s frameworks are cumbersome. Which is why starting and intermediate developers loved JQuery when it came out. I know it has it’s problems, but it was simple, and was similar to Laravel in the fact that with a few lines of code (which made sense), you got great functionality.

In my opinion Livewire is getting there, but has a long way to go.

Pardon the rant, but the fact that you are listening to me, and any feedback you provide helps me become a better developer. Thanks again!

Ok. This works for links, but not for input fields to be used by Livewire.

If I have this line of code:

<input type="text" value="{{ $this->deal['id'] }}" wire:model="dealId">

It will show the value in the field, UNTIL I added the correct line:

public $dealId;

to the controller. Then the field shows blank again.

Why is that?

Cannot look into you code, but I think dealId overwrites the value when you make it a public property. And I think that dealId is empty or not set. Can you see it when you put it somewhere as variable in your html:

{{ $dealId }}