Unable to use nested objects in Livewire v.2

I am using Laravel 10, Livewire 2. I am using a Livewire component to create a DistributionGroup. Each of the DistributionGroup's will have 1 or more DistributionGroupGroup's, and each of those, in turn, will have 2 or more DistributionGroupAccount's. Livewire seems to be losing track of my DistributionGroupGroup's; when I try to add a new one, it will overwrite however many DistributionGroupGroup's are present. Am I fundamentally mis-using objects in Livewire, or models in Laravel?

Relevant code:

DistributionGroup.php (model)

use App\Models\Ledger\DistributionGroupGroup;

class DistributionGroup extends Model
{
    public $groups = [];

    public function __construct(array $attributes = []) {
        parent::__construct($attributes);
        $this->name = rand();
    }

    public function groups()
    {
        return $this->hasMany(DistributionGroupGroup::class);
    }

    public function addGroupGroup()
    {
        $groupGroup = new DistributionGroupGroup();
        $groupGroup->addAccounts();
        $this->groups[] = $groupGroup;
    }
}

DistributionGroupGroup.php (model)

use App\Models\Ledger\DistributionGroupAccount;

class DistributionGroupGroup extends Model
{
    public $accounts = [];

    public function distributionGroup()
    {
        return $this->belongsTo(DistributionGroup::class, 'distribution_group_id');
    }

    public function distributionGroupAccount()
    {
        return $this->hasMany(DistributionGroupAccount::class, 'distribution_group_account_id');
    }

    public function addAccounts()
    {
        for ($i = 0; $i < 2; $i++) {
            $account = new DistributionGroupAccount();
            $account->credit_or_debit = ($i? 'Credit' : 'Debit').rand();//temporary name
            $this->accounts[] = $account;
        }
    }
}

DistributionGroupAccount.php (model)

class DistributionGroupAccount extends Model
{
    public function distributionGroup()
    {
        return $this->belongsTo('App\Models\Ledger\DistributionGroup', 'distribution_group_id');
    }

    public function distributionGroupGroup()
    {
        return $this->belongsTo('App\Models\Ledger\DistributionGroupGroup', 'distribution_group_group_id');
    }
}

DistributionModal.php (Livewire component)

class DistributionModal extends Modal
{
    public $distributionGroup;

    //Out of desperation, I added all properties of the nested objects to my rules
    protected function rules() {
        return [
            'distributionGroup.name' => ['required', 'max:250', new CaseInsensitiveUnique('cl_distribution_groups', 'name', $this->distributionGroup->id ?? null)],
            'distributionGroup.code' => ['nullable', 'max:50', new CaseInsensitiveUnique('cl_distribution_groups', 'code', $this->distributionGroup->id ?? null, true)],
            'distributionGroup.remarks' => 'nullable|string|max:250',
            'distributionGroup.archived' => 'boolean',
            'distributionGroup.groups.*.distribution_group_id' => 'nullable',
            'distributionGroup.groups.*.distribution_group_account_id' => 'nullable',
            'distributionGroup.groups.*.accounts.*.distribution_group_id' => 'nullable',
            'distributionGroup.groups.*.accounts.*.distribution_group_group_id' => 'nullable',
            'distributionGroup.groups.*.accounts.*.distribution_group_group_id' => 'account_id',
            'distributionGroup.groups.*.accounts.*.credit_or_debit' => 'string|max:250',
        ];
    }

    public function render()
    {
        return view('livewire.ledger.distribution-modal');
    }

    public function openNewDistributionGroup()
    {
        $this->resetErrorBag();
        $this->distributionGroup = new DistributionGroup();
        $this->addGroupGroup();

        $this->show = true;//shows the modal
    }

    public function addGroupGroup() {
        $this->distributionGroup->addGroupGroup();
    }
}

distribution-modal.blade.php (Livewire component)

<div>
    {{$distributionGroup->name}}

    @if (isset($distributionGroup->groups))
        @foreach ($distributionGroup->groups as $group)
            <div class="w-full flex gap-2" wire:key="clDistGrp-{{$group->id}}-{{rand()}}">
                @if (isset($group->accounts))
                    @foreach ($group->accounts as $account)
                        <p wire:key="clacct-{{$account->credit_or_debit.rand()}}">{{$account->credit_or_debit}}</p>
                    @endforeach
                @endif
            </div>
        @endforeach
    @endif
</div>

As I am giving the initial DistributionGroup a name, I can tell the DistributionGroup object isn't being re-instantiated. It's just the nested objects who are not being tracked correctly; as I try to add an Account, it seems like Livewire forgets there are already Accounts attached to the Group, and overwrites them.

Using dd(), I can tell that when I try addGroupGroup() in DistributionModal.php, the group object(s) nested in $this->distributionGroup are just gone. Livewire is somehow forgetting these nested objects exist.

Thank you for any help or insights.

Upvotes: 0

Views: 15

Answers (0)

Related Questions