Skip to main content

Black Friday 2025! Only until December 1st: coupon FRIDAY25 for 40% off Yearly/Lifetime membership!

Read more here

Register Password Show/Hide/Strength

Lesson 02/17 7 min read
Autoplay

We will start this course, by making the register page better. Here we will add a button to show/hide the password, generate a random password, and will show the password strength bar.

finished passwords component


New Livewire Component

First, we will create a Livewire component.

php artisan make:livewire RegisterPasswords

Now, we need to move password fields to the newly created component, and instead call our created Livewire component.

resources/views/livewire/register-passwords.blade.php:

<div>
<!-- Password -->
<div class="mt-4">
<x-input-label for="password" :value="__('Password')" />
 
<x-text-input id="password" class="block mt-1 w-full"
type="password"
name="password"
required autocomplete="new-password" />
 
<x-input-error :messages="$errors->get('password')" class="mt-2" />
</div>
 
<!-- Confirm Password -->
<div class="mt-4">
<x-input-label for="password_confirmation" :value="__('Confirm Password')" />
 
<x-text-input id="password_confirmation" class="block mt-1 w-full"
type="password"
name="password_confirmation" required />
 
<x-input-error :messages="$errors->get('password_confirmation')" class="mt-2" />
</div>
</div>

resources/views/auth/register.blade.php:

@livewire('register-passwords')

Show/Hide Password with Alpine.js

First, let's make a password show/hide feature. For this, we only will use Alpine.js, no Livewire needed, as we interact with the browser only, no need to send the data to the server.

If you're new to Alpine.js, you can watch this free 7-minute quick introduction video and it will be enough for you to understand, for the purpose of this tutorial.

resources/views/livewire/register-passwords.blade.php:

<x-text-input id="password" class="block mt-1 w-full"
type="password"
name="password"
required autocomplete="new-password" />
 
<div class="flex mt-1 mb-2">
<div class="relative flex-1 col-span-4" x-data="{ show: true }">
<input class="w-full rounded-md border-gray-300 shadow-sm focus:border-indigo-300 focus:ring focus:ring-indigo-200 focus:ring-opacity-50"
id="password"
:type="show ? 'password' : 'text'"
name="password"
required autocomplete="new-password" />
 
<button type="button" class="flex absolute inset-y-0 right-0 items-center pr-3" @click="show = !show" :class="{'hidden': !show, 'block': show }">
<!-- Heroicon name: eye -->
<svg xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 24 24" stroke-width="1.5" stroke="currentColor" class="w-6 h-6">
<path stroke-linecap="round" stroke-linejoin="round" d="M2.036 12.322a1.012 1.012 0 010-.639C3.423 7.51 7.36 4.5 12 4.5c4.638 0 8.573 3.007 9.963 7.178.07.207.07.431 0 .639C20.577 16.49 16.64 19.5 12 19.5c-4.638 0-8.573-3.007-9.963-7.178z" />
<path stroke-linecap="round" stroke-linejoin="round" d="M15 12a3 3 0 11-6 0 3 3 0 016 0z" />
</svg>
</button>
<button type="button" class="flex absolute inset-y-0 right-0 items-center pr-3" @click="show = !show" :class="{'block': !show, 'hidden': show }">
<!-- Heroicon name: eye-slash -->
<svg xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 24 24" stroke-width="1.5" stroke="currentColor" class="w-6 h-6">
<path stroke-linecap="round" stroke-linejoin="round" d="M3.98 8.223A10.477 10.477 0 001.934 12C3.226 16.338 7.244 19.5 12 19.5c.993 0 1.953-.138 2.863-.395M6.228 6.228A10.45 10.45 0 0112 4.5c4.756 0 8.773 3.162 10.065 7.498a10.523 10.523 0 01-4.293 5.774M6.228 6.228L3 3m3.228 3.228l3.65 3.65m7.894 7.894L21 21m-3.228-3.228l-3.65-3.65m0 0a3 3 0 10-4.243-4.243m4.242 4.242L9.88 9.88" />
</svg>
</button>
</div>
</div>

Here are a few things to explain.

Everything in Alpine starts with the x-data directive, so we add reactive data called show and by default, we set it to true. Next, for the input, we bind the type attribute to change its type to password or text.

We have two buttons for which we use heroicons to show icons. For those buttons, we use the shorthand syntax @click to change the show status. And the last thing for buttons: we bind class to change whether show them or not.

password show hide


Generate Random Password

Now, let's add a button to generate a random password. For this, we need two public properties on the Livewire component, to bind both password fields.

app/Livewire/RegisterPasswords.php:

class RegisterPasswords extends Component
{
public string $password = '';
 
public string $passwordConfirmation = '';
}

resources/views/livewire/register-passwords.blade.php:

<input class="w-full rounded-md border-gray-300 shadow-sm focus:border-indigo-300 focus:ring focus:ring-indigo-200 focus:ring-opacity-50"
id="password"
:type="show ? 'password' : 'text'"
name="password"
wire:model="password"
required autocomplete="new-password" />
 
<x-text-input id="password_confirmation" class="block mt-1 w-full"
type="password"
wire:model="passwordConfirmation"
name="password_confirmation" required />

Next, let's add the Generate button itself.

resources/views/livewire/register-passwords.blade.php:

<div class="flex mt-1 mb-2">
<div class="relative flex-1 col-span-4" x-data="{ show: true }">
...
</div>
<div class="flex items-center place-content-end ml-1">
<x-primary-button wire:click="generatePassword" type="button">Generate</x-primary-button>
</div>
</div>

generate password button

This new button has a Livewire action called generatePassword.

app/Livewire/RegisterPasswords.php:

use Illuminate\Support\Str;
 
class RegisterPasswords extends Component
{
public string $password = '';
 
public string $passwordConfirmation = '';
 
public function generatePassword(): void
{
$password = Str::password(12);
 
$this->setPasswords($password);
}
 
protected function setPasswords($value): void
{
$this->password = $value;
$this->passwordConfirmation = $value;
$this->updatedPassword($value);
}
 
public function render()
{
return view('livewire.register-passwords');
}
}

generated password


Show Password Strength

The last feature we will add to the registration form is to show password strength. To determine strength we will use bjeavons/zxcvbn-php package.

composer require bjeavons/zxcvbn-php

To update the strength value we will use Livewire Lifecycle Hook and will set the $strengthScore public property. Also, we need to update the strength score when generating passwords.

app/Http/Livewire/RegisterPasswords.php:

use ZxcvbnPhp\Zxcvbn;
 
class RegisterPasswords extends Component
{
public string $password = '';
 
public string $passwordConfirmation = '';
 
public int $strengthScore = 0;
 
public function updatedPassword($value)
{
$this->strengthScore = (new Zxcvbn())->passwordStrength($value)['score'];
}
 
// ...
 
protected function setPasswords($value): void
{
$this->password = $value;
$this->passwordConfirmation = $value;
$this->updatedPassword($value);
}

Now we can show the strength value in the blade file. Besides the progress bar, we will write in words what's the password strength, for example, "weak" or "strong".

Because we only have an integer value of the score, we will add a public property as array of which score value corresponds to which strength in words.

app/Http/Livewire/RegisterPasswords.php:

class RegisterPasswords extends Component
{
public string $password = '';
 
public string $passwordConfirmation = '';
 
public int $strengthScore = 0;
 
public array $strengthLevels = [
1 => 'Weak',
2 => 'Fair',
3 => 'Good',
4 => 'Strong',
];
 
// ...

And just before password validation, let's show the strength:

resources/views/livewire/register-passwords.blade.php:

</div>
<span class="text-sm">
<span class="font-semibold">Password strength:</span> {{ $strengthLevels[$strengthScore] ?? 'Weak' }}
</span>
 
<progress value="{{ $strengthScore }}" max="4" class="w-full"></progress>
 
<x-input-error :messages="$errors->get('password')" class="mt-2" />
</div>

show password strength

And that's it for this part, now we enhanced the registration form.

Comments & Discussion

A
AlbertLens ✓ Link copied!

For the heroicon of the eye, the class did not adjust the position correctly. <button type="button" class="flex absolute inset-y-0 right-0 items-center pr-3"

			I changed inset-y-0 to top-0 and also adjusted padding a bit.
			
			For if it helps. Fresh installation of today Feb, 9th 2023
EE
Emil Enevoldsen ✓ Link copied!

If you run "npm run build" or "dev". It will be placed where it should.

A
AlbertLens ✓ Link copied!

Tks. It worked. Sorry for the inconvenience.

N
Nouar ✓ Link copied!

Very nice

SP
Sylvain P ✓ Link copied!

in register.blade.php it not clear where to paste the code

@livewire('register-passwords')

MS
Manuel Schamroth ✓ Link copied!

The content of register-passwords represented by the @livewire('register-passwords') replaces the Password and Confirm Password sections in the register.blade.php.

In general if you are not sure, just check the repo and compare.

SP
Steve Purcell ✓ Link copied!

Any idea where the repo would be hiding? I am two steps into this "tutorial" and already lost, I can't wait for the rest.

PK
Povilas Korop ✓ Link copied!

The link to the final repo is at the end of the final lesson :)

SP
Sylvain P ✓ Link copied!

@Povilas Korop, could you kindly assign a number to each step so that I can easily reference a specific step in my comments on issue?

PK
Povilas Korop ✓ Link copied!

@Sylvain not sure what you mean by "assign a number to each step", what do you call a "step" here?

SP
Sylvain P ✓ Link copied!

in step Show/Hide Password with Alpine.js I dont see any change. maybe missing some step ?

PK
Povilas Korop ✓ Link copied!

Well it worked for me, hard to comment on what didn't work for you. Maybe check with the repository and compare the code?

SP
Sylvain P ✓ Link copied!

It seems that the current explanation is not clear enough for us to understand how it works. Perhaps some improvements are needed to make the explanation more understandable.

RB
Rajesh Budhathoki ✓ Link copied!

I got the following error while implementing Generate Random Password method:

App\Http\Middleware\RedirectIfAuthenticated::handle(): Return value must be of type Symfony\Component\HttpFoundation\Response, null returned

P.S. I am using Laravel 10 for this course.

PK
Povilas Korop ✓ Link copied!

Found that Laravel 10 return types have broken the Livewire components that work with unauthenticated users. Livewire is planning to release the update for this, in upcoming days, hopefully: https://github.com/livewire/livewire/pull/5561

SP
Sylvain P ✓ Link copied!

Dependencies make projects a bit fragile :-(

A
Artan ✓ Link copied!

run composer update, https://github.com/livewire/livewire/commit/5ab6266a12c637f645d38a2f0f61f84182f6249d

RB
Rajesh Budhathoki ✓ Link copied!

Please upgrade the repository to Laravel 10. I'm stuck there! The livewire not generating a random password. Thanks!!

PK
Povilas Korop ✓ Link copied!

I will re-check it with Laravel 10 next week, and make updates.

SI
Solomon Iroegbu ✓ Link copied!

even me, im using laravel 10

N
Nerijus ✓ Link copied!

In the repo laravel 10 is used. Saying doesn't generate doesn't help at all

RP
Rogerio Picilli ✓ Link copied!

@Povilas Korop I'm a programmer who has been using your teachings for a long time. I went back to studying livewire. Copy all files that have been modified or created so far from github up to here. I believe that some step is missing in this step by step. Could you please check if there is something wrong with this tutorial? The error I'm getting occurs when typing the first letter in the input password.

This is the error link: https://flareapp.io/share/lm2R1GAm#F51

PK
Povilas Korop ✓ Link copied!

Hard to answer without debugging. Maybe Laravel 10 changed something... Could you please put your code on GitHub and invite me (username PovilasKorop) and then I could debug next week.

RB
Rajesh Budhathoki ✓ Link copied!

@Rogerio Picilli The same issue that I am facing. Are you using Laravel 10?

PK
Povilas Korop ✓ Link copied!

Found that Laravel 10 return types have broken the Livewire components that work with unauthenticated users. Livewire is planning to release the update for this, in upcoming days, hopefully: https://github.com/livewire/livewire/pull/5561

RP
Rogerio Picilli ✓ Link copied!

@Rajesh Budhathoki yes I'm.

PK
Povilas Korop ✓ Link copied!

The issue is fixed with new Livewire release, run "composer update": https://github.com/livewire/livewire/releases/tag/v2.11.3

RB
Rajesh Budhathoki ✓ Link copied!

Now it's working, thank you so much.

RP
Rogerio Picilli ✓ Link copied!

@Povilas Korop thanks for your update. Lets wait for the livewire update.

RP
Rogerio Picilli ✓ Link copied!

@Povilas Korop it's working now.

N
Nouar ✓ Link copied!

Very nice, thanks

N
Nouar ✓ Link copied!

Thanks, i will use this topic in my application

A
andywong31 ✓ Link copied!

Povilas inside your RegisterPasswords livewire component, why did you use underscore for your variable named $password_confirmation and camelCase for your variable named $strengthScore?

PK
Povilas Korop ✓ Link copied!

Well noted, it should be consistent with camelCase, I agree. Will be more careful next time :)

RA
Richard A. Hoyle ✓ Link copied!

I only have one request as sort of an add-on When typing in a password it needs to also be simultaneously entered in to the password confirmation field. I know that this can be done because you have done it before.

RP
Rogerio Picilli ✓ Link copied!

Hi Richard dont get me wrong but I think It certainly can be done, but it totally misses the point of you having it. If you're going to auto-populate the field then you don't need it on the form, right?

PK
Povilas Korop ✓ Link copied!

In my videos, I have done it with Chrome add-on, if I understand it correctly. And I agree with Rogerio, what's the point of that field, then?

M
muuucho ✓ Link copied!

The strenght indicator works only when generating a password, not when you enter it manually. You need to add

public function updatePassword(){
    $this->updatedPassword($this->password);
}

and then add this to the password input:

wire:keydown="updatePassword"
L
laravelMan ✓ Link copied!

Thank you muuucho!

We'd Love Your Feedback

Tell us what you like or what we can improve

Feel free to share anything you like or dislike about this page or the platform in general.