14

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.

Matt
  • 795
  • 1
  • 6
  • 20
  • Do you want to display the `Created At` in the update form or only in the detail view? – Chin Leung Aug 22 '18 at 23:01
  • 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. – Matt Aug 23 '18 at 14:57
  • 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. – Chin Leung Aug 23 '18 at 18:17

8 Answers8

17

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
    ]]),
Matt
  • 795
  • 1
  • 6
  • 20
  • 1
    I want to set readonly only on update. The above code is setting readonly on creation also. Is that possible? – Saumini Navaratnam Oct 10 '18 at 04:38
  • 5
    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. – Miloslav Milo Janoušek Oct 10 '18 at 15:24
  • This only work with a few of the normal field types, for example text fields. It doesn't work with for example DateTime fields. – Pelmered Feb 23 '19 at 11:27
15

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;
    }),
bernhardh
  • 3,137
  • 10
  • 42
  • 77
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

neil
  • 429
  • 3
  • 10
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');
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

MohKoma
  • 964
  • 9
  • 9
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'])
mylesthe.dev
  • 9,565
  • 4
  • 23
  • 34
  • 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. – Matt Aug 24 '18 at 18:50
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;
            }
        }),
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.

Eduardo Pacheco
  • 504
  • 4
  • 14