Fields

HasOne

Basics

The HasOne field is designed to work with the same-name relationship in Laravel and includes all Basic methods.

HasOne::make(
Closure|string $label,
?string $relationName = null,
Closure|string|null $formatted = null,
ModelResource|string|null $resource = null,
)
  • $label - the label, title of the field,
  • $relationName - the name of the relationship,
  • $resource - ModelResource that the relationship refers to.

The $formatted parameter is not used in the HasOne field!

Having a ModelResource that the relationship refers to is mandatory. The resource must also be registered in the MoonShineServiceProvider service provider in the $core->resources() method. Otherwise, there will be a 500 error.

 namespaces
use App\MoonShine\Resources\ProfileResource;
use MoonShine\Laravel\Fields\Relationships\HasOne;
 
HasOne::make(
'Profile',
'profile',
resource: ProfileResource::class
)

has_one has_one_dark

If you do not specify $relationName, the relationship name will be automatically determined based on $label (following camelCase rules).

use MoonShine\Laravel\Fields\Relationships\HasOne;
 
HasOne::make('Profile', 'profile')

You can omit $resource if the ModelResource matches the name of the relationship.

use MoonShine\Laravel\Fields\Relationships\HasOne;
 
HasOne::make('Profile')

Fields

The fields() method allows you to specify which fields will be involved in the preview or in the form building.

fields(FieldsContract|Closure|iterable $fields)
 namespaces
use App\MoonShine\Resources\ProfileResource;
use MoonShine\UI\Fields\Relationships\HasOne;
use MoonShine\UI\Fields\Phone;
use MoonShine\UI\Fields\Text;
 
HasOne::make('Profile', resource: ProfileResource::class)
->fields([
Phone::make('Phone'),
Text::make('Address'),
])

has_one_preview has_one_preview_dark

Parent ID

If the relationship has a resource, and you want to get the parent item's ID, you can use the ResourceWithParent trait.

 namespaces
use MoonShine\Laravel\Resources\ModelResource;
use MoonShine\Traits\Resource\ResourceWithParent;
 
class PostImageResource extends ModelResource
{
use ResourceWithParent;
 
// ...
}

When using the trait, you need to define the following methods:

protected function getParentResourceClassName(): string
{
return PostResource::class;
}
 
protected function getParentRelationName(): string
{
return 'post';
}

To get the parent ID, use the getParentId() method.

$this->getParentId();

Modification

Preview

The modifyTable() method allows you to change the TableBuilder for the preview.

 namespaces
use App\MoonShine\Resources\CommentResource;
use MoonShine\Laravel\Fields\Relationships\HasOne;
use MoonShine\UI\Components\Table\TableBuilder;
 
HasOne::make('Comment', resource: CommentResource::class)
->modifyTable(
fn(TableBuilder $table) => $table
)

Form

The modifyForm() method allows you to change the FormBuilder for editing.

 namespaces
use App\MoonShine\Resources\CommentResource;
use MoonShine\UI\Components\FormBuilder;
use MoonShine\Laravel\Fields\Relationships\HasOne;
 
HasOne::make('Comment', resource: CommentResource::class)
->modifyForm(
fn(FormBuilder $form) => $form->submit('Custom title')
)

Redirect after modification

The redirectAfter() method allows for redirection after saving/adding/deleting.

 namespaces
use App\MoonShine\Resources\CommentResource;
use MoonShine\Laravel\Fields\Relationships\HasOne;
 
HasOne::make('Comment', resource: CommentResource::class)
->redirectAfter(fn(int $parentId) => route('home'))

Display

Display within Tabs

By default, relationship fields in MoonShine are displayed at the bottom, separately from the form, and follow one after another. To change the display of the field and add it to Tabs, you can use the tabMode() method.

tabMode(Closure|bool|null $condition = null)

In the following example, a Tabs component with two tabs, Comment and Cover, will be created.

use MoonShine\Laravel\Fields\Relationships\HasOne;
 
HasOne::make('Comment', 'comment', resource: CommentResource::class)
->tabMode(),
HasOne::make('Cover', 'cover', resource: CoverResource::class)
->tabMode()

tabMode will not work when using the disableOutside() method

Display within a Modal Window

To display a HasOne field in a modal window that is called by a button, you can use the modalMode() method.

public function modalMode(
Closure|bool|null $condition = null,
?Closure $modifyButton = null,
?Closure $modifyModal = null
)

In this example, instead of a form, there will now be an ActionButton that calls a Modal.

use MoonShine\Laravel\Fields\Relationships\HasOne;
 
HasOne::make('Comment', 'comment', resource: CommentResource::class)
->modalMode(),

To modify the ActionButton and Modal, you can use the method parameters $modifyButton and $modifyModal, into which you can pass a closure.

use MoonShine\Laravel\Fields\Relationships\HasOne;
 
HasOne::make('Comment', 'comment', resource: CommentResource::class)
->modalMode(
modifyButton: function (ActionButtonContract $button, HasOne $ctx) {
$button->warning();
return $button;
},
modifyModal: function (Modal $modal, ActionButtonContract $ctx) {
$modal->autoClose(false);
return $modal;
}
)

Display within the Main Resource Form

For HasOne, the disableOutside() method is available, which allows it to be displayed inside the form at the designated field location. disableOutside for HasOne only works in modalMode.

use MoonShine\Laravel\Fields\Relationships\HasOne;
 
HasOne::make('Comment', 'comment', resource: CommentResource::class)
->disableOutside(),