Weave Code
Weaver
Helps Laravel developers discover, compare, and choose open-source packages. See popularity, security, maintainers, and scores at a glance to make better decisions.
Feedback
Share your thoughts, report bugs, or suggest improvements.
Subject
Message

Nova Visible Password Laravel Package

magdicom/nova-visible-password

A Laravel Nova field that adds a password input with a show/hide visibility toggle, making password editing in Nova resources clearer and more user-friendly with minimal setup.

View on GitHub
Deep Wiki
Context7

Getting Started

What it actually does. One job: renders a Nova input as type="password" with an eye / eye-off control that flips it to type="text" on the client. No migrations, no config file, no service layer — just a Nova\Fields\Password-shaped field class plus a small Vue component.

Prerequisites. Laravel Nova 3.x or 4.x (the last tag is 2022-11-17, pre-Nova 5 — see Gotchas). PHP 7.4+.

Install.

composer require magdicom/nova-visible-password

If Packagist resolution fails (plausible for a 3-star package), pin the VCS repo:

"repositories": [
    { "type": "vcs", "url": "https://github.com/magdicom/nova-visible-password" }
]

then composer require magdicom/nova-visible-password:dev-master.

Where to look first. Three files tell you everything:

  • vendor/magdicom/nova-visible-password/src/ — the field class (likely Magdicom\NovaVisiblePassword\VisiblePassword) and its FieldServiceProvider. The provider is auto-discovered via extra.laravel.providers and typically calls Nova::script('nova-visible-password', __DIR__.'/../dist/js/field.js').
  • resources/js/components/Field.vue — the toggle itself. Expect roughly: data() { return { show: false } } and :type="show ? 'text' : 'password'".
  • dist/js/field.js — the compiled asset Nova actually loads. If this is missing or stale, you get a plain password input and no toggle.

Confirm the class name before writing any code:

grep -rn "class .*extends" vendor/magdicom/nova-visible-password/src

First use case. Swap Nova\Fields\Password for this field in your User resource so an admin can verify the temp password they just typed before saving.

use Magdicom\NovaVisiblePassword\VisiblePassword;

public function fields(NovaRequest $request)
{
    return [
        VisiblePassword::make('Password')
            ->onlyOnForms()
            ->creationRules('required', 'string', 'min:12')
            ->updateRules('nullable', 'string', 'min:12'),
    ];
}

If the toggle renders and you can read what you typed, the integration is done. Everything below is about not breaking it.

Implementation Patterns

Hash on write, never in the field. Pick one of these, not both:

  • Laravel 10+ cast: protected $casts = ['password' => 'hashed']; — Nova hands over plaintext, Eloquent hashes on save.
  • Explicit fillUsing when you need to skip empty submissions and have no cast available:
VisiblePassword::make('Password')
    ->onlyOnForms()
    ->fillUsing(function ($request, $model, $attribute, $requestAttribute) {
        if (filled($request->input($requestAttribute))) {
            $model->{$attribute} = Hash::make($request->input($requestAttribute));
        }
    });

fillUsing replaces Nova's normal fill for that attribute, so don't stack a hashed cast on the same model column.

Create vs. update is the whole game. creationRules('required|min:12') + updateRules('nullable|min:12') is the standard pair for "leave blank to keep the current password." Always pair it with ->onlyOnForms() so the field never renders on index or detail — on detail it would print the bcrypt hash.

Confirmation field. If you want the type-twice UX, add a second instance against password_confirmation and validate with confirmed:

use Illuminate\Validation\Rules\Password;

VisiblePassword::make('Password')
    ->rules('required', 'confirmed', Password::min(12)),
VisiblePassword::make('Password Confirmation')
    ->onlyOnForms(),

Submit the form once to confirm the package doesn't mangle the _confirmation attribute — it shouldn't, since it's just a text input, but it's a one-minute check.

Wrap it once and reuse. The package adds nothing but a Vue component, so subclass it and centralize your rules:

class UserPassword extends VisiblePassword
{
    public function __construct($name = 'Password', $attribute = 'password')
    {
        parent::__construct($name, $attribute);

        $this->onlyOnForms()
             ->creationRules('required', 'string', 'min:12')
             ->updateRules('nullable', 'string', 'min:12')
             ->hideFromIndex();
    }
}

This also insulates resource files if you later drop the package for a hand-rolled field.

Permission-gate the field. Wherever the password field isn't universally trusted:

->canSee(fn ($request) => $request->user()->can('updatePassword', $this->resource))

The toggle itself is cosmetic, but hiding the field keeps the input out of the DOM for users who shouldn't be resetting passwords.

Nova actions / custom tools. If you have a "Change Password" action, don't try to reuse the resource field's fillUsing — actions have their own field pipeline and handle(). Reuse the component pattern (form-only field + hashing in the action) instead.

Local dev loop. To iterate on the component: cd vendor/magdicom/nova-visible-password && npm install && npm run dev, then hard-refresh. Better: copy the package into nova-components/VisiblePassword so npm run watch runs from your own tree.

Gotchas and Tips

  • Maturity is the headline risk. 3 stars, 0 dependents, last tag 2022-11-17. Assume no upstream fixes. The entire feature is ~20 lines of Vue plus a thin field class — budget the hour to vendor it into nova-components/ and you remove the Composer dependency from your risk register.
  • Nova 5. The package predates it. The Vue component probably still works (Nova 4 and 5 both use Vue 3), but the service provider's Nova::script(...) registration and asset paths are the fragile bits. Test one form before rolling out across resources.
  • Missing or stale dist/. Nova loads dist/js/field.js, not resources/js/. If you see a password input with no eye icon, the script isn't registered or is 404ing. Check the Network tab on the form route before touching PHP.
  • Asset caching. Run php artisan nova:publish after any change, and hard-refresh. A cached field.js is the classic "it worked yesterday" cause. If you rebuild, npm run prod — a dev build in production will be obvious.
  • Blank password on update. The most common bug with any Nova password field: saving the profile with an empty password wipes the column or hashes ''. Use updateRules('nullable') plus either fillUsing or a mutator that ignores blanks. Test the "edit user, change only the name" path explicitly.
  • Never render on index/detail. ->hideFromIndex()->hideFromDetail() or just ->onlyOnForms(). The field resolves the stored hash when displayed outside a form.
  • Password managers and autofill. Chrome and 1Password will fill both password inputs, and can fight the toggle mid-interaction. The name/autocomplete attributes come from the Vue component — if you see doubled values, that's the cause. Verify in a real browser, not just Dusk.
  • The toggle is not a permission. Revealing is entirely client-side; the plaintext is already in the input's value before you click. If "who may reveal" is part of your threat model, this adds no control — gate the field instead.
  • No config to publish. Nothing to vendor:publish. If you want a default icon or reveal-on-focus behavior, you're editing the Vue component, which means you own the fork. Treat that as the extension point.
  • Field-to-component wiring. If the toggle silently doesn't appear, the usual mismatch is the component name registered in Nova.booting((app) => app.component('visible-password', ...)) vs. the $component set on the PHP field class. Grep both.
  • Debugging order: (1) composer dump-autoload sees the class; (2) field.js loads on the form route; (3) component name matches; (4) the field is actually rendered by this form (not onlyOnForms on a detail view); (5) input type flips in the DOM inspector when you click the icon.
Weaver

How can I help you explore Laravel packages today?

Conversation history is not saved when not logged in.
Prompt
Add packages to context
No packages found.
middlewares/firewall
qubiqx/montapacking
nyoncode/laravel-package-console
pnscripts/filament-broadquill-lite
pnscripts/laravel-sentfold-lite
vleap/mx-sdk-laravel-internal
twidpay/utils
htetmyathlaing/scout-elasticsearch-driver
artisan-toolbox/front-awesome
ls/client-assistant
users-au/laravel-client
robertmarney/lara-hierarchial-collections
simonschaufi/rule-doc-generator
emissaoja/emissaoja
blackbricksoftware/gravityforms-civicrm-form-processor
al-rahabi/fancy-crud
jinas/dhivatar-component
mltstephane/laravel-quality
bernskiold/laravel-talentlms
bernskioldmedia/laravel-form-architect