AFS
AFS

Reputation: 348

Laravel Nova show computed field in BelongsToMany sub table

Using Laravel Nova, I want to show a computed field in a BelongsToMany subview. In the intermediate model I have setup a virtual attribute field which computes a value using connected tables. However this field is not getting shown probably because Nova checks the withPivot fields (to which it cannot be added as it's not a real field). Is there an alternative method to get this to work?

The database model behind this is:

[GameVariation] has BelongsToMany using [GameVariationMatch] with [GameMatch]

[GameMatch] HasOne [Match]

In the GameVariation resource I've setup a BelongsToMany field which should display the computed field:

BelongsToMany::make( 'Game Matches', 'game_matches', GameMatch::class )
    ->fields( function () {
        return [
            Text::make( 'Match Data' )->displayUsing(function() {
                return $this->match_data;
            })
        ];
    } ),

In the GameVariation model the tables are connected with BelongsToMany:

final public function game_matches(): BelongsToMany {
    return $this->belongsToMany(
        GameMatch::class
    )
    ->using( GameVariationMatch::class );
}

In the pivot tabel model GameVariationMatch the computed field is setup like this:

final public function getMatchDataAttribute(): string {
    return $this
        ->game_match
        ->match
        ->match_data;
}

Upvotes: 1

Views: 3478

Answers (1)

AFS
AFS

Reputation: 348

As it turns out, on the GameVariation resource the index view of the BelongsToMany to GameMatch is served from the GameMatch resource. When only setting up ->fields() on the GameVariation BelongsToMany field, it won't show up. The recommended way is to set up ->fields() using a field class like this:

<?php


namespace App\Nova\Fields;


use App\Models\GameVariationMatch;
use Illuminate\Http\Request;
use Laravel\Nova\Fields\Text;

class GameVariationMatchFields {

    /**
     * Get the pivot fields for the relationship.
     *
     * @param Request $request
     *
     * @return array
     */
    final public function __invoke( Request $request ): array {
        return [
            Text::make( 'Match Data', function ( GameVariationMatch $GameVariationMatch ) {
                return $GameVariationMatch->match_data;
            } ),
        ];
    }
}

In the above, the computed Text field receives the intermediate pivot model and can therefore access all computed attributes.

The field class is used in the GameVariation resource as:

BelongsToMany::make( 'Game Matches', 'game_matches', GameMatch::class )
    ->fields( new RoundMatchVariationFields ),

And in the GameMatch resource as:

BelongsToMany::make( 'Game Variations', 'game_variations', GameVariation::class )
    ->fields( new GameVariationMatchFields ),

As described in official Nova docs on pivot fields https://nova.laravel.com/docs/2.0/resources/relationships.html#belongstomany

Upvotes: 3

Related Questions