'Using Repository in edit method Repository is null
With laravel 7 /livewire app I make crud using Repository and I got listing of data ok, In mount event I assign protected var $FacilityRepository , which works ok in render method,
but it is null in edit method and I got error:
Call to a member function getById() on null
when user clicks on “edit link”
<?php
namespace App\Http\Livewire\Admin;
use App\library\CheckValueType;
use App\Settings;
use DB;
use Livewire\Component;
use App\Facility;
use Livewire\WithPagination;
use App\Repositories\Interfaces\FacilityRepositoryInterface;
class Facilities extends Component
{
use WithPagination;
public $form= [
'name'=>'',
'descr'=> '',
'created_at'=> '',
'is_reopen' => false,
];
public $current_facility_id;
public $filter_name= '';
public $updateMode = 'browse';
protected $FacilityRepository;
public function render()
{
$this->facility_rows_count = Facility
::getByName($this->filter_name, true)
->count();
$backend_per_page = Settings::getValue('backend_per_page', CheckValueType::cvtInteger, 20);
\Log::info( 'render -10 $this->FacilityRepository::' . print_r( json_encode($this->FacilityRepository), true ) );
// line above logged as : [2020-09-04 16:46:26] local.INFO: render -10 $this->FacilityRepository::{}
return view('livewire.admin.facilities.container', [
'facilityDataRows' => $this->FacilityRepository->filterWithPagination(
[
'name'=>$this->filter_name,
],
$backend_per_page
),
'facility_rows_count'=> $this->facility_rows_count
]); // this listing is rendered OK
}
public function mount( FacilityRepositoryInterface $FacilityRepository ) {
$this->FacilityRepository = $FacilityRepository;
\Log::info( '-101mount $this->FacilityRepository::' . print_r( json_encode($this->FacilityRepository), true ) );
// line above logged as : [2020-09-04 16:46:26] local.INFO: -101mount $this->FacilityRepository::{}
}
public function edit($id)
{
\Log::info( '-1 edit $id::' . print_r( json_encode( $id ), true ) );
\Log::info( '-1 edit $this->FacilityRepository::' . print_r( $this->FacilityRepository, true ) );
// line above logged as : [2020-09-04 16:46:28] local.INFO: -1 edit $this->FacilityRepository::
// AND ERROR NEXT
$this->form = $this->FacilityRepository->getById($id)->toArray();
\Log::info( '-1023 $this->form ::' . print_r( json_encode( $this->form ), true ) );
$this->current_facility_id = $id;
$this->form['created_at'] = getCFFormattedDateTime($this->form['created_at']);
$this->emit('facility_opened',[ 'mode'=>'edit', 'id'=>$id ]);
$this->updateMode = 'edit';
}
In template edit link is defined as :
@foreach($facilityDataRows as $nextFacilityDataRow)
<tr>
<td class="text-right m-0">
<a wire:click="edit({{$nextFacilityDataRow->id}})"
class="p-1 a_edit_item_{{$nextFacilityDataRow->id}} a_link">
{{$nextFacilityDataRow->id}}
</a>
</td>
...
Why error and how to fix it ?
Modified # 2:
If I make
class Facilities extends Component { ... public $FacilityRepository; }
I got error :
Livewire component's [admin.facilities] public property [FacilityRepository] 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.
I tried to declare method edit as :
public function edit( FacilityRepositoryInterface $facilityRepository, int $id) { // Did you mean this ? ... }
I got error :
Call to a member function filterWithPagination() on null
on method filterWithPagination, which is used in render method, when I show listing of data. Which way is correct ?
Modified # 3: If to modify :
public function render(FacilityRepositoryInterface $facilityRepository)
{
I got error :
Declaration of App\Http\Livewire\Admin\Facilities::render(App\Repositories\Interfaces\FacilityRepositoryInterface $facilityRepository) should be compatible with Livewire\Component::render()
?
Modified # 4: Opening page in mode I have 2 inputs with lazy defined, like
<dd class="horiz_divider_right_23" wire:model="form.title.lazy" x-data="{ name: '{{$form['name']}}'}">
<input
x-model="name"
x-on:blur="$dispatch('name', name)"
id="name"
class="form-control editable_field admin_control_input"
placeholder="Enter descriptive name"
autocomplete=off
>
@error('form.name')
<div class="validation_error">{{ clearValidationError($message,['form.'=>'']) }}</div> @enderror
</dd>
and when I edit some of fields on blur ervent I got the same error :
Call to a member function filterWithPagination() on null
with url in error description :
VM5783:1 POST http://local-hostels3.com/livewire/message/admin.facilities 500 (Internal Server Error)
where http://local-hostels3.com is my local hosting
Have I in some way to overrride message method ?
"laravel/framework": "^7.0",
"livewire/livewire": "^1.3",
Thanks!
Solution 1:[1]
protected and private properties DO NOT persist between Livewire updates. In general, you should avoid using them for storing state.
https://laravel-livewire.com/docs/properties/#important-notes
That being said, you can use dependency injection again, just pass whatever you need (FacilityRepositoryInterface
in this case) as the first argument(s) of the edit
method.
Same applies to the render
method, so you can skip mount
altogether.
Correction
The last bit in my original answer is wrong, you cannot use DI in the render method.
So for use in render, use the mount method and for use in edit, bring it via the first parameter. If render complains about not having it after usage of edit, save to the protected property inside edit as well.
Final code, that should work
class Facilities extends Component
{
protected $FacilityRepository;
public function mount(FacilityRepositoryInterface $FacilityRepository)
{
$this->FacilityRepository = $FacilityRepository;
}
public function render()
{
// use $this->FacilityRepository->...
}
public function edit(FacilityRepositoryInterface $FacilityRepository, $id)
{
$this->FacilityRepository = $FacilityRepository;
// rest of the edit method from your code
}
}
Solution 2:[2]
add boot method
public function boot(FacilityRepositoryInterface $FacilityRepository)
{
$this->FacilityRepository = $FacilityRepository;
}
Sources
This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.
Source: Stack Overflow
Solution | Source |
---|---|
Solution 1 | |
Solution 2 | Mohammadmahdi Khakdaman |