'How to set a Laravel Nova field to display as readonly or protected?

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.



Solution 1:[1]

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;
    }),

Solution 2:[2]

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

Solution 3:[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');

Solution 4:[4]

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

Solution 5:[5]

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'])

Solution 6:[6]

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;
            }
        }),

Solution 7:[7]

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.

Sources

This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.

Source: Stack Overflow

Solution Source
Solution 1 bernhardh
Solution 2 neil
Solution 3 Yazan Stash
Solution 4 MohKoma
Solution 5 mylesthe.dev
Solution 6 Calvin Schemanski
Solution 7 Eduardo Pacheco