How to set a Laravel Nova field to display as readonly or protected?
Asked Answered
C

8

16

Within Laravel Nova (v1.0.3), there are several methods that grant fine-grained control of the visibility of a resource field (canSee, showOnDetail, etc.). I can't find any methods that control if a field is editable. How can I display a field, but prevent the user from being able to edit it (make it readonly)?

For example, I'd like to display the "Created At" field, but I don't want the user to be able to change it.

Cyclograph answered 22/8, 2018 at 21:20 Comment(3)
Do you want to display the Created At in the update form or only in the detail view?Marysa
I'd like to display a non-editable field in an update form. (You can't edit any field from a detail view, right?) The "Created At" field was just an example, but I have several fields where this would be very helpful. Since Nova was released 24 hours ago, there have been 5 version releases, so I'm thinking this "feature" will show up shortly.Cyclograph
My question is, do you want to show it in the form or in the detail view only? If it's only in the detail view, you can use computed fields to achieve it.Marysa
C
19

This capability was added in v1.1.4 (October 1, 2018).

  • Allow setting any attribute on text and textarea fields

Example usage:

Text:: make('SomethingImportant')
    ->withMeta(['extraAttributes' => [
          'readonly' => true
    ]]),
Cyclograph answered 2/10, 2018 at 18:32 Comment(3)
I want to set readonly only on update. The above code is setting readonly on creation also. Is that possible?Labio
Please be aware that when using this solution the only thing it is doing is setting that input as readonly, but it doesnt touch the user permissions at all. So if you cut out the readonly property in browser dev tools and set different value to input, it will save the new value just fine. So it is possibly dangerous if you are exposing this form to users you cant trust. You can however protect the input in User observer in Laravel.Jermainejerman
This only work with a few of the normal field types, for example text fields. It doesn't work with for example DateTime fields.Precarious
G
17

As of Nova >2.0 you can use the readonly method with a callback and checking for the resource:

Text::make("Read Only on Update")
    ->readonly(function() {
        return $this->resource->id ? true : false;
    }),

or even better:

Text::make("Read Only on Update")
    ->readonly(function() {
        return $this->resource->exists;
    }),
Germanous answered 11/12, 2019 at 10:20 Comment(1)
the better solutions works for me. saving me from lot of coding conditionsBakehouse
L
13

As of v2.0.1, readonly() is native and accepts a callback, closure or boolean and can simply be called as:

Text::make('Name')->readonly(true)

This may have been added prior to this version but the changelog does not specify if this is the case.

Nova v2.0 documentation

Licentious answered 16/4, 2019 at 22:57 Comment(0)
P
3

Since App\Laravel\Nova\Fields\Field is macroable you can easily add your own method to make it read-only, e.x.

in App\Providers\NovaServiceProvider you can add this function after the parent::boot() call

\Laravel\Nova\Fields\Field::macro('readOnly', function(){
    $this->withMeta(['extraAttributes' => [
        'readonly' => true
    ]]);

    return $this;
});

and then you can chain it like this

Text::make("UUID")->readOnly()->help('you can not edit this field');
Pitzer answered 6/12, 2018 at 8:53 Comment(0)
P
1

July 2021, For Nova version 3.0, the readonly method can accept different types of arguments

Default:

Text::make('Email')->readonly()

Direct boolean:

Text::make('Email')->readonly(true/false)

Closure:

Text::make('Email')->readonly(function ($request) {
    return !$request->user()->isNiceDude();
}

Read more here https://nova.laravel.com/docs/3.0/resources/fields.html#readonly-fields

Publicly answered 7/7, 2021 at 7:33 Comment(0)
S
0

As of 1.0.3 I don't believe there is a way to do this (can't see anything in the source file).

However you could quickly make your own "ReadOnly" field as Nova makes it pretty easy to add more field types.

I would probably just be patient though - ability to add attributes to fields will likely be a feature in future releases.

Something like this would be cool:

Text::make('date_created')
    ->sortable()
    ->isReadOnly()

or

Text::make('date_created')
    ->sortable()
    ->attributes(['readonly'])
Seline answered 23/8, 2018 at 2:44 Comment(1)
Thanks - I didn't immediately think about making my own field, but that does look pretty easy. Probably only a matter of time before it's native though. It's now been added as a feature request to the new laravel-issues GitHub repository.Cyclograph
T
0

You can also make use of the canSee function. In my case I couldn't make use of the withMeta solution because I need some of my users (Admins) to be able to edit the field, but not a regular user.

Example:

     Number::make('Max Business Locations')
        ->canSee(function ($request) {
            //checks if the request url ends in 'update-fields', the API 
            //request used to get fields for the "/edit" page
            if ($request->is('*update-fields')) {
                return $request->user()->can('edit-subscription');
            } else {
                return true;
            }
        }),
Transoceanic answered 25/1, 2019 at 21:46 Comment(0)
J
0

In addition to MohKoma's answer, there is a neat way to make a field readonly when editing it but not on creation:

Text::make('Handle')
    ->readonly(fn ($request) => $request->isUpdateOrUpdateAttachedRequest()),

This approach was based on Laravel\Nova\Fields\Field@isRequired, using that same validation to fetch the required rule specific to each action.

Junk answered 26/1, 2022 at 16:2 Comment(0)

© 2022 - 2025 — McMap. All rights reserved.