laravel / nova-issues

557 stars 34 forks source link

DependsOn BelongsTo field not working when creating viaRelationship #4469

Closed rasmuscnielsen closed 2 years ago

rasmuscnielsen commented 2 years ago

Description:

When field dependsOn a BelongsTo field, it doesn't invoke dependencies when creating viaRelationship. Possible because the dropdown is disabled / readonly.

Detailed steps to reproduce the issue on a fresh Nova installation:

  1. Create a Category model that has a parent_id field that links to its own id. Add relationships as follows:
    public function parentCategory(): BelongsTo
    {
        return  $this->belongsTo(static::class, 'parent_id');
    }

    public function subCategories(): HasMany
    {
        return $this->hasMany(static::class, 'parent_id');
    }
  1. Create a Category Nova resource with the following fields
    public function fields(Request $request)
    {
            ID::make(),

            BelongsTo::make('Parent category', 'parentCategory', static::class)
                ->nullable(),

            Boolean::make('Allow subcategories')
                ->dependsOn(['parentCategory'], function (Field $field, NovaRequest $request, FormData $data) {
                    if ($data->parentCategory !== null) {
                        $field->hide();
                    }
                }),

            HasMany::make('Subcategories', 'subCategories', static::class)
    }
  1. Create an initial category which will be the parent. It should show the boolean field.

  2. Go to the created category and press "Create subcategory". Now the boolean field is still visible, even though it should be hidden as the parent category is set.

crynobone commented 2 years ago

You can access parentCategory using the following:

$parentCategory = $data->resource('parentCategory', $data->parentCategory);

PR has been made to improve the documentation: https://github.com/laravel/nova-docs/pull/434

crynobone commented 2 years ago

https://nova.laravel.com/docs/4.0/resources/fields.html#accessing-request-resource-ids

The documentation has been updated.

rasmuscnielsen commented 2 years ago

Hi @crynobone - thanks for your feedback.

I've just tested out your solution but unfortunately it does not seem to solve the problem.

When debugging with Xdebug I can see that the dependsOn closure only executes once, and that FormData.attributes.parentCategory is NULL. Again my theory is that because the "Parent Category" select input in the create-form is readonly / disabled, it doesn't broadcast the update when it is set. At least the result is that the dependsOn callback is never invoked with the parent category set.

I hope you can reproduce the issue on your end too.

crynobone commented 2 years ago

Can you provide a reproducing repository to this issue, similar to https://github.com/nova-issues

I hope you can reproduce the issue on your end too.

No, and we already have the feature tested using the example app from https://github.com/laravel/nova-dusk-suite

rasmuscnielsen commented 2 years ago

@crynobone Reproducing repo: https://github.com/rasmuscnielsen/nova-issue-4569

Also a video showing the behavior:

https://user-images.githubusercontent.com/8465957/179232549-28e0ef8b-0380-4e32-8739-7a81d60ca524.mov

rasmuscnielsen commented 2 years ago

@crynobone Any chance to re-open this given my above reproduction repo?

I believe I'm experiencing the same issue in another project at the moment as well, which really impacts the functionality of the dashboard.

crynobone commented 2 years ago

It should have been:

if ($data->resource(User::uriKey(), $data->author) !== null) {

Will update the documentation on this details.

rasmuscnielsen commented 2 years ago

It should have been:

if ($data->resource(User::uriKey(), $data->author) !== null) {

Will update the documentation on this details.

Unfortunately this still doesn't solve the described issue on my machine.

crynobone commented 2 years ago

Sorry, viaResource and viaResourceId is not yet available via $formData->resource(), will PR this.

In the meantime you can do the following:

Boolean::make('No author')
                ->help('This field may only be checked when no author is selected.')
                ->dependsOn(['author'], function (Field $field, NovaRequest $request, FormData $data) {
                    $authorId = ($request->viaResource === User::uriKey() ? $request->viaResourceId : null) ?? $data->author;

                    if (! is_null($authorId)) {
                        $field->hide();
                    }
                })
rasmuscnielsen commented 2 years ago

Thanks @crynobone !

Just tested your solution, and that indeed seems to work! 🎉 Look forward to the PR'ed version that hopefully makes it a bit easier.


Since we're here I just wanted to mention an additional quirk that I've stumbled across. I found that when using a MorphTo field, there is no easy way to get the selected model class. Is that correct, or just me not finding it in docs or when source diving?

Ie

$source = MorphTo::make('Source')
    ->required()
    ->readonly(fn (NovaRequest $request) => $request->isUpdateOrUpdateAttachedRequest())
    ->types([
        GitCommit::class,
        GitTag::class,
    ]),

Text::make('Version')
    ->onlyOnForms()
    ->hideWhenUpdating()
    ->readonly()
    ->dependsOn([$source], function (Text $version, NovaRequest $request, FormData $form) {
        if ($form->source) {
            // How to figure out what model was selected?
        }
    }),

Let me know if you'd rather me creating a separate issue on this. I just thought maybe I'm missing something obvious here 🤔

crynobone commented 2 years ago

This has been fixed and is pending next release.

As for you other question, see the following for example: https://github.com/laravel/nova-dusk-suite/blob/9ccd20ec5f4049d003b228b22eb5ba73359ce3d4/app/Nova/Comment.php#L50-L62

github-actions[bot] commented 2 years ago

This thread has been automatically locked since there has not been any recent activity after it was closed. Please open a new issue for related bugs.