I'm using Livewire to build my Laravel project, and I'm also implementing the security/authentication layer with Fortify.
For various reasons though, I'm not using Jetstream. With that said, there are clearly some very useful features and techniques which Jetstream employs to do its stuff, and so in the true spirit of creativity, I've "borrowed" the following "update-password" form as an example of how Jetstream uses Livewire to interface with Fortify.
This HTML template is a simplified version of the actual HTML code that goes into building my form, but I've taken out all the styling and labelling complexities etc. so that we can focus only on what's important:
<!-- update-password-form.blade.php (Livewire Template) -->
<form wire:submit.prevent="updatePassword">
<input id="current_password" type="password" name="current_password" required="true" />
<input id="password" type="password" name="password" required="true" />
<input id="password_confirmation" type="password" name="password_confirmation" required="true" />
<button type="submit">Change Password</button>
</form>
As we see, Livewire prevents the default submission of the form, and redirects it to the function updatePassword() in the Livewire class. The function as you can see here looks like this:
/**
* Update the user's password.
*
* #param \Laravel\Fortify\Contracts\UpdatesUserPasswords $updater
* #return void
*/
public function updatePassword(UpdatesUserPasswords $updater)
{
$this->resetErrorBag();
$updater->update(Auth::user(), $this->state);
$this->state = [
'current_password' => '',
'password' => '',
'password_confirmation' => '',
];
$this->emit('saved');
}
This all appears to work fine-ish. When I (the user) press [Change Password] Livewire sets the form inactive (to prevent the user from double-submitting the form), and when the response from Laravel/Livewire is received, the form is enabled again. And... well that's it.
The problem is that it doesn't matter what data I submit. If I enter all correct values, the password doesn't update! If I enter incorrect current_password, it doesn't error. If I submit the correct current_password with mismatching password and password_confirmation, I get the same "nothing happened" experience (as an end user). When I check the "network" tab on the browser's dev-tools, I get valid 200 responses each time without any obvious errors being reported in the detail. I know the PHP function is being invoked because if I put a dd($this) style debug in it, the JSON response throws back the Livewire object.
So the question I therefore have is the following...
How does the Fortify framework manage errors, and how am I supposed to catch them (in Livewire) to give the user some useful feedback?
Does the ErrorBag (which is reset in the first line of code) somehow get populated in the $updater->update() function?
Moreover, I copied (sorry, borrowed) this solution from Jetstream project. Does this also mean that the Jetstream interface is equally as unintuitive (from an end-user point of view)? Is there some higher-level concept that I've missed from the Jetstream project?
I was being stupid. The error bag is returned to the view, there just wasn't an outlet in the template to display the response. All I needed was a conditional label (or a span or a div) to display the field if the error exists.
<form wire:submit.prevent="updatePassword">
<input id="current-password" type="password" name="current_password" required="true" />
#error('current_password')
<label id="current-password-err" class="error" for="current-password">{{ $message }}</label>
#enderror
<input id="password" type="password" name="password" required="true" />
#error('password')
<label id="password-err" class="error" for="password">{{ $message }}</label>
#enderror
<input id="password-confirmation" type="password" name="password_confirmation" required="true" />
#error('password_confirmation')
<label id="password-confirmation-err" class="error" for="password-confirmation">{{ $message }}</label>
#enderror
<button type="submit">Change Password</button>
</form>
Related
I'm currently trying to add validation to an angular 2 form, but for some reason I can't get my submit button to disable when the required fields are not filled in.
Here is the code of my form template:
<h1 md-dialog-title>{{title}}</h1>
<form #formCtrl="ngForm">
<md-dialog-content>
<md-input-container>
<input #name md-input placeholder="Name" value="" name="name" focused required>
</md-input-container>
<br />
<md-select #inputtype placeholder="Input type" name="inputtype">
<md-option *ngFor="let inputtype of inputtypes" [value]="inputtype.id">
{{inputtype.name}}
</md-option>
</md-select>
</md-dialog-content>
<md-dialog-actions>
<button type="submit" md-raised-button color="primary" [disabled]="!formCtrl.form.valid">Create</button>
</md-dialog-actions>
</form>
According to several examples, this should work, however the button is never disabled. I've also tried "!formCtrl.valid", also to no avail.
I've tried using non-material design input fields thinking maybe that would be the issue, but it still won't work.
I then tried copy/pasting the following simple example into my application, and even that won't work at all:
http://blog.angular-university.io/introduction-to-angular-2-forms-template-driven-vs-model-driven/
Any ideas as to what might prevent it from working correctly?
Assuming you are using a newer release than Angular 2 final:
You need to add ngModel, which binds the form value based on the name attribute’s value. In your case one is name="inputtype" the other is name="name". So you need to add ngModel to bind the values, and your form should work as you wish! :)
So the following should work (removed a bit of noise from code):
<form #formCtrl="ngForm" (ngSubmit)="save(formCtrl.value)"> //whatever your submit method is
<md-dialog-content>
<md-input-container>
<input md-input name="name" required ngModel>
</md-input-container>
<md-select name="inputtype" required ngModel>
<md-option *ngFor="let inputtype of inputtypes" [value]="inputtype.id">
{{inputtype.name}}
</md-option>
</md-select>
</md-dialog-content>
<md-dialog-actions>
<button type="submit" md-raised-button color="primary" [disabled]="!formCtrl.form.valid">Create</button>
</md-dialog-actions>
</form>
Don't remember when this was introduced, this should be found somewhere in the changelogs which can be useful to have a look at once in a while, since Angular is constantly tweaking things almost in every release. So following that will keep you updated with changes and syntax :)
I'm using codeception to write acceptance tests for a laravel application. The application is a simple CRUD app, and my tests just test filling out and submitting the application's various forms. I have a working test which creates a new resource but then when I try to edit that same resource I get the following error:
Here's what the (working) test looks like for creating the resource:
$I = new AcceptanceTester($scenario);
$I->wantTo('Create Additional');
$I->login($I, 'username', 'password');
$I->click('Additional');
$I->seeInCurrentUrl('/admin/additional');
$I->click('Add Additional');
$I->seeInCurrentUrl('admin/additional/create');
$I->see('Add Additional');
//Fill out form fields
$I->fillField('name', 'Test Name');
$I->fillField('anchor', 'Additional Services in Cusco');
$I->selectOption('publish', '1');
$I->click('Save');
$I->click('Additional');
$I->see('Additional Test Name');
$I->cleanup($I);
The test for editing the resource is almost identical:
$I = new AcceptanceTester($scenario);
$I->wantTo('Edit Additional');
$I->login($I, 'username', 'password');
$I->click('Additional');
$I->seeInCurrentUrl('/admin/additional');
$I->click('Edit');
$I->seeInCurrentUrl('admin/additional/edit/1');
$I->see('Editing');
// Fill out form fields
$I->fillField('name', 'Additional Name Edited');
$I->fillField('anchor', 'Edited anchor');
$I->selectOption('publish', '1');
$I->click('Save');
$I->click('Additional');
$I->see('Additional Name Edited');
$I->cleanup($I);
Yet when I run the edit test I get the following error:
1) Failed to edit additional in AdditionalEditCept
Couldn't fill field "name","Additional Name Edited":
InvalidArgumentException: Unreachable field "name"
That seems straightforward enough--the "name" field must not be there. But when I look at the source name="name" is there just like it is for the additional/create view. I should point out that codeception didn't detect the field with
$I->see('name');
either. Here's what the relevant code looks like in AdditionalEditCept.fail.html
<div class="form-group">
<label for="name">Additional Name:</label>
<input class="form-control" placeholder="" autocomplete="off" name="name" type="text" value="Edited Additional Services in Cusco" id="name">
</div>
It seems really simple; codeception needs to find html elements by CSS selectors, I give them a CSS selector. What could be going on here?
A bit late on this but I've had a similar error if my html isn't valid eg
<div class="form-group">
<label for="name">Additional Name:</label>
<input name="name" type="text">
</div>
</div>
I'm building the website based on Joomla 3. I need to disable the validation of the fields: name, username, password1 (the second, because the first is password2) and email2 and use email1 as username (I installed the plugin Email for user authorization).
I have tried to remove these fields in file components/com_users/models/forms/registration.xml but the validation is still remaining. If I don't remove them but only change the rows required="true" to false for these fields the registration doesn't work at all and any user stored in the DB. How can I disable these fields?
It's not an easy workaround, and you will need some basic knowledge of Joomla and PHP, but I'll try to explain it to you as simple as i can.
>>> Creating view template override
First of all you will need to create your Registration view template override (to keep it Joomla update proof). To do so, create folder /templates/YOUT_TEMPLATE/html/com_users/registration and copy /components/com_users/views/registration/tmpl/default.php file there.
From now on you can modify registration output in your template folder.
>>> Modifying registration form output
By default Joomla takes all fields from form file /components/com_users/models/forms/registration.xml, where they are defined, and outputs them in a view. But if we don't want to use ALL the fields, we need to output fields manually.
My example code only output E-mail and Password fields for registration. Here's a sample code to do so: (default.php file)
<?php
defined('_JEXEC') or die;
JHtml::_('behavior.keepalive');
?>
<div class="grid_8" id="register_block">
<div class="content_block">
<h1>Registracija</h1>
<div class="login<?php echo $this->pageclass_sfx?>">
<form id="member-registration" action="<?php echo JRoute::_('index.php?option=com_users&task=registration2.register'); ?>" method="post" enctype="multipart/form-data">
<div>
<div class="login-fields">
<label id="jform_email1-lbl" for="jform_email1">E-mail:</label>
<input type="text" name="jform[email1]" id="jform_email1" value="" size="30">
</div>
<div class="login-fields">
<label id="jform_password1-lbl" for="jform_password1">Password:</label>
<input type="password" name="jform[password1]" id="jform_password1" value="" autocomplete="off" size="30">
</div>
<button type="submit" class="button"><?php echo JText::_('JREGISTER');?></button>
<input type="hidden" name="option" value="com_users" />
<input type="hidden" name="task" value="registration2.register" />
<?php echo JHtml::_('form.token');?>
</div>
</form>
</div>
</div>
</div>
Please note, that I've also replaced task value from registration.register to registration2.register, I did this to bypass some of validation rules using my own controller.
>>> Creating controller override
Locate file /components/com_users/controllers/registration.php and create a copy of it called registration2.php in same folder.
Open file registration2.php and change It's class name from UsersControllerRegistration to UsersControllerRegistration2
From now on Joomla registration form will use this class to create a new user.
Find a method called register and find this line:
$requestData = JRequest::getVar('jform', array(), 'post', 'array');
This is where Joomla get's registration form data. Add the following lines:
$requestData['name'] = $requestData['email1'];
$requestData['username'] = $requestData['email1'];
$requestData['email2'] = $requestData['email1'];
$requestData['password2'] = $requestData['password1'];
It will add missing registration info, and help you pass validation.
NOTE: This is a sample code, to show the main logic. If anyone has a better solution, I'd be more than happy to hear it.
Following same idea, a simpler solution might be just including hidden inputs with values in com_users\views\registration\tmpl\default.php above
<button type="submit" class="btn btn-primary validate"><?php echo JText::_('JREGISTER');?></button>
add
<input type="hidden" id="jform[username]" name="jform[username]" value="username" />
<input type="hidden" id="jform_name" name="jform[name]" value="name" />
It would pass the validation and you would no longer need to override controllers etc.
I need some help with the following issue. I am pretty new to JavaScript so this one is pretty tough for me. Any help would be greatly appreciated!
We have a form for registration that is already in use and I need to make some amends to it to enhance its usability. The form itself already contains several validation scripts and I need to add in a new one - an error message to appear next to the mobile field. I am unable to amend the form HTML itself so I have to do everything by javascript – I need to bind the new function to the submit button so that it fires AFTER all the other validations (field highlight, pop ups), but before the page turns over.
Here is the form (I have just left in the feild i need to amend) :
<form method="post" action="#" id="register_form" class="validate">
<input type="hidden" name="page" value="" />
<input type="hidden" name="unregistered" value="false" />
<fieldset>
<legend>I am a new online customer</legend>
<div class="element">
<label for="mobile_number">Mobile:**</label>
<input name="mobileNumber" type="text" id="mobile_number" title="Please enter at least one number" class="text validate {validate:{minLength:10, eitherOr:'#telephone_number', messages:{minLength:'Please enter a valid phone number (at least #NUM digits long)', eitherOr:'Please enter either your Telephone or Mobile number'}}}" />
</div>
<div class="element continue_shopping_cont submit">
<button type="submit" class="submit button small_button"><span>Register</span></button>
</div>
<input type="hidden" name="secure_from" value="" />
</fieldset>
</form>
Could someone help show me how i am supposed to do this and how is best to target this field?
I am having a problem with my client side validating. I am using DataAnnotations in my model. An this works when i am in the create form very nicely, but when i go to edit the information only some of the validation works.
i.e the Name box does have clientside val but the amount box does.
i have check the source name doesnot include the data-val="true". I don't understand why this would render this way because on the 'create' form it does and works fine?
<input class="text-box single-line" id="Name" name="Name" type="text" value="name" />
<span class="field-validation-valid" data-valmsg-for="Name" data-valmsg-replace="true"></span>
<input class="text-box single-line" data-val="true" data-val-number="The field Amount must be a number." data-val-required="The Amount field is required." id="Amount" name="Amount" type="text" value="120.00" />
<span class="field-validation-valid" data-valmsg-for="Amount" data-valmsg-replace="true"></span>
can somebody give me an idea how to make my 'edit' page validation work?
Thanks in advance
thank you for the help. but is have solved it!!
The problem was that because i was generated the edit view from the wrong class which meant that the DataAnnotations was not being read. what is have done now is to change the name of the class to that of my database then mark the class as partial and connected the DataAnnotaions by using this code below
[MetadataType(typeof(Budget_Validation))]
public partial class Budget
I put all the dataAnnotaions in the Budget_Validation class.
All now working fine!
Thanks