I have a little problem with the data validation with livewire ( laravel ).
I noticed that when I set up the validation in real time ( validateOnly() ), the information entered in the form is validated in real time. At this level everything is fine.
But when I click on the button to submit the form (even though the form contains errors), the form is unfortunately sent to my function defined in the wire:submit.
So my question is : is it possible to revalidate the information in the wire:submit method that receives the data after the form is submitted ? If so, how can I do that?
PS: I tried to set the validate method in my wire:submit function but nothing happens. It blocks the form from being submitted but it doesn't give me an error .
My source code :
<?php
class UserProfile extends Component
{
use WithFileUploads;
public $countries = [];
public $profile = [];
protected function rules() {
if ( !LivewireUpdateProfileRequest::authorize() ) {
return abort(403, "Your are not authorized to make this request !");
}
$rules = LivewireUpdateProfileRequest::rules();
if ( !empty($this->profile['phone']) ) {
$rules['profile.phone'] = [ 'required', 'phone_number:' . $this->profile['phone'] ];
}
return $rules;
}
public function mount()
{
$this->countries = Countries::all();
$this->profile = Auth::user()->toArray();
}
public function updateUserProfile()
{
$validatedData = $this->validate();
dd( $validatedData );
}
public function updated($key, $value)
{
$this->validateOnly($key);
}
public function render()
{
return view('livewire.user-profile');
}
}
Html source :
<form action="" method="POST" wire:submit.prevent="updateUserProfile">
<input name="profile.email" type="email" wire:model="profile.email" />
#error('profile.email') {{ $message }} #enderror
<input name="profile.phone" type="tel" wire:model="profile.phone" />
#error('profile.phone') {{ $message }} #enderror
</form>
Here is LivewireUpdateProfileRequest content :
<?php
namespace App\Http\Requests\Web;
use Illuminate\Foundation\Http\FormRequest;
class LivewireUpdateProfileRequest extends FormRequest
{
/**
* Determine if the user is authorized to make this request.
*
* #return bool
*/
public static function authorize()
{
return true;
}
/**
* Get the validation rules that apply to the request.
*
* #return array
*/
public static function rules()
{
return [
'profile' => ['required', 'array', 'size:10'],
'profile.firstname' => ['required', 'string'],
'profile.lastname' => ['required', 'string'],
'profile.email' => ['required', 'email'],
'profile.phone' => ['required', 'phone_number:33'],
'profile.gender' => ['required', 'gender'],
'profile.image' => ['sometimes', 'image', 'mimes:png,jpg,jpeg'],
'profile.address' => ['required', 'string'],
'profile.city' => ['required', 'string'],
'profile.country_id' => ['required', 'exists:countries,id'],
'profile.birth_at' => ['required', 'date', 'min_age:18'],
];
}
}
Usually in your saving method you would run validation once more for all fields. The livewire docs share this example:
Livewire Component:
class ContactForm extends Component
{
public $name;
public $email;
protected $rules = [
'name' => 'required|min:6',
'email' => 'required|email',
];
public function updated($propertyName)
{
$this->validateOnly($propertyName);
}
public function saveContact()
{
$validatedData = $this->validate();
Contact::create($validatedData);
}
}
With this HTML:
<form wire:submit.prevent="saveContact">
<input type="text" wire:model="name">
#error('name') <span class="error">{{ $message }}</span> #enderror
<input type="text" wire:model="email">
#error('email') <span class="error">{{ $message }}</span> #enderror
<button type="submit">Save Contact</button>
</form>
This should validate the inputs near-realtime using the updated-method and on submit using the saveContact-method.
If you could share your code, we could debug it easier.
Source: https://laravel-livewire.com/docs/2.x/input-validation#real-time-validation
Related
I would like to create a multi step form with validations, but the values are not stored in the inputs through the sessions.
In the controller I have:
use Illuminate\Support\Facades\Session;
My code at the moment is this:
public function addItemStep1(Request $request)
{
$product = $request->session()->get('product');
return view('admin.items.add', compact('product'))->with([
'page_name' => __('Add Item')
]);
}
public function storeNewItemStep1(Request $request)
{
$validatedData = $request->validate([
'title' => 'required',
'body' => 'required'
]);
if(empty($request->session()->get('product')))
{
$product = new Items();
$product->fill($validatedData);
$request->session()->put('product', $product);
} else {
$product = $request->session()->get('product');
$product->fill($validatedData);
$request->session()->put('product', $product);
}
return redirect('/');
}
The validations work, everything is ok, but unfortunately after sending the form the data just entered does not appear.
<input type="text" class="form-control #error('title') is-invalid #enderror" value="{{ Session::get('title') }}" name="title">
I get this error when I want to insert data into the table and return a message.
Here is my code.
When I entered the form and submitted, an error occurred: Method App\Http\Requests\AddUserRequest::fails does not exist.
Code In Router:
/**************Quản lý user*****************/
Route::get('admin/manage-user', 'UserController#getList')->middleware('admin');
Route::get('admin/manage-user/add', 'UserController#indexAdd')->middleware('admin');
Route::post('admin/manage-user/add', 'UserController#getAdd')->middleware('admin');
Code In UserController:
<?php
namespace App\Http\Controllers;
use Illuminate\Http\Request;
use App\User;
use App\Http\Requests\AddUserRequest;
class UserController extends Controller
{
//
public function getList()
{
$data = User::paginate(10);
return view('admin.manage-user',['data' => $data]);
}
public function indexAdd()
{
return view('admin.add-user');
}
public function getAdd(AddUserRequest $request)
{
if($request->fails())
{
return redirect('admin.add-user')
-> withInput()
-> withErrors($request);
}else
{
User::create([
'name' => $request->username,
'email' => $request->email,
'password' => Hash::make($request->pass1),
'level' => 0,
]);
return redirect('admin.add-user')->with('success',"Done!!");
}
}
}
Code In view:
#extends('layouts.admin')
#section('title','Add User')
#section('content')
<div class="row">
<div class="col-md-3"></div>
<div class="col-md-6">
<div class="box box-primary">
<div class="box-header with-border">
<h3 class="box-title">Add User</h3>
</div>
<!-- /.box-header -->
<!-- form start -->
<form role="form" action="{{url('admin/manage-user/add')}}" method="post">
<div class="box-body">
#csrf
<div class="form-group">
#if (session('success'))
<div class="alert alert-success">
<p>{{ session('success') }}</p>
</div>
#endif
#if ($errors->any())
<div class="alert alert-danger">
<b>Lỗi!! Bạn vui vòng kiểm tra lại:</b>
<ul>
#foreach ($errors->all() as $error)
<li>{{ $error }}</li>
#endforeach
</ul>
</div>
#endif
</div>
In AddUserRequest:
<?php
namespace App\Http\Requests;
use Illuminate\Foundation\Http\FormRequest;
use Illuminate\Http\Request;
class AddUserRequest extends FormRequest
{
/**
* Determine if the user is authorized to make this request.
*
* #return bool
*/
public function authorize()
{
return true;
}
/**
* Get the validation rules that apply to the request.
*
* #return array
*/
public function rules()
{
return [
'username' => 'required|max:200',
'email' => 'required|email|unique:users',
'pass1' => 'required|min:6',
'pass2' => 'same:pass1',
];
}
}
Thank you for your help!
you don't need to put that check, because data is already validated through your request
public function getAdd(AddUserRequest $request)
{
User::create([
'name' => $request->username,
'email' => $request->email,
'password' => Hash::make($request->pass1),
'level' => 0,
]);
return redirect('admin.add-user')->with('success',"Done!!");
}
AddUserRequest is a FormRequest it doesn't have fails method. For FormRequest you don't need to check fails, it automatically validate your request data using rules provided in that class and throw validation error, for details check here.
For FormRequest validation you use it like this
public function getAdd(AddUserRequest $request)
{
//all code here executed after validation
User::create([
'name' => $request->username,
'email' => $request->email,
'password' => Hash::make($request->pass1),
'level' => 0,
]);
return redirect('admin.add-user')->with('success',"Done!!");
}
If you need to check validation in you controller then use manual validation like this.
public function getAdd(Request $request)
{
$validator = Validator::make($request->all(), [
'username' => 'required|max:200',
'email' => 'required|email|unique:users',
'pass1' => 'required|min:6',
'pass2' => 'same:pass1',
]);
if($validator->fails())
{
return redirect('admin.add-user')
-> withInput()
-> withErrors($request);
}else
{
User::create([
'name' => $request->username,
'email' => $request->email,
'password' => Hash::make($request->pass1),
'level' => 0,
]);
return redirect('admin.add-user')->with('success',"Done!!");
}
}
I have a form to edit the administrators of a post.
This form has some radio buttons. Each radio button corresponds to a administrator of a a post, so the id of each radio button
is the id of the admin in the administrators table.
When the submit button is clicked I want to update just the administrator with the id of the checked administrator/radio button.
For that it should be necessary to pass to the update method the id of the post and the id of the checked radio button (administrator) and then update only that administrator id.
Im passing the id of the post with success but the admin id not. It appears syntax error, unexpected '{'.
Edit admins form:
<form method="post" class="clearfix" action="{{route('admins.update', ['id' => $post->id], ['adminID' => $admin->id])}}" enctype="multipart/form-data">
{{csrf_field()}}
#foreach($administrators $admin)
<div class="form-check">
<input class="form-check-input" type="radio" name="radiobutton" id="{{$admin->id}}" value="">
<label class="form-check-label" for="">
{{$admin->first_name}}
</label>
</div>
#endforeach
<!-- below I have form fields like administrator name, email, etc -->
</form>
// update admins routes
Route::get('post/edit/{id}/admins', [ 'uses' => 'AdminController#edit', 'as'=>'admins.edit']);
Route::post('post/update/{id}/admins', [ 'uses' => 'AdminController#update', 'as'=>'admins.update']);
// Admin controller
class AdministratorController extends Controller
{
public function edit($id)
{
$post = Post::find($id);
$administrators = Administrator::where('post_id', $id)->get();
return view('administrators.edit')
->with('post', $post)
->with('administrators', $administrators));
}
public function update(Request $request, $id, $adminID){
$this->validate($request, [
'name' => 'required|string',
'email' => 'required|integer',
'...' => '...',
]);
$post = Post::find($id);
$admin = Administrator::find($post->id);
$administratorToUpdate = Administrator::find($adminID);
$administratorToUpdate->name = $request->name;
$administratorToUpdate->email = $request->email;
....
$administratorToUpdate->save();
}
// Admin model
class Administrator extends Model
{
protected $fillable = [
'first_name', 'email', 'password', 'description', 'post_id'
];
public function post(){
return $this->belongsTo('App\Post');
}
}
Edit the route from :
{{route('admins.update', ['id' => $post->id], ['adminID' => $admin->id])}}
to:
{{route('admins.update', ['id' => $post->id, 'adminID' => $admin->id])}}
Edit: make sure to iterate over the administrators before defining the route.
There are some other mistakes on the form like foreach($administrators as $admin) $admin will be not be available for the route above so tweak that.
I use Laravel 5.4 on hosting. My validation method is working, but it doesn't show messages. I do all the needed operations for displaying errors but it doesn't work.
#if($errors->has('recipient'))
<div class="form-group">
<label class="col-lg-2 control-label"></label>
<div class="col-lg-10">
<div class="alert alert-danger">
<ul>
#foreach ($errors->get('recipient') as $error)
<li>{{ $error }}</li>
#endforeach
</ul>
</div>
</div>
</div>
#endif
I use {{ csrf_field() }} tokens. Validation rules work if wrong user types are used, but messages are not displayed.
My send method:
public function send(Request $request)
{
$this->validator($request->all())->validate();
$this->create($request->all());
return redirect($this->redirectToAfterSendMessage);
}
My validator code:
protected function validator(array $data)
{
return Validator::make($data, [
"$this->recipient" => [
'sometimes',
'required',
'email',
'exists:users,email',
Rule::notIn([auth()->user()->email])
],
"$this->subject" => 'sometimes|required|min:10',
"$this->message" => 'sometimes|required|min:50',
], $this->validator_messages());
}
My routes:
Route::get('/compose', 'InboxController#compose') ->name('compose');
Route::post('/compose', 'InboxController#send');
Result of dump($errors):
ViewErrorBag {#244 ▼
#bags: []
}
EDITED
To fix your current problem, change $errors->get('recipient') to $errors->all().
It should look like this:
#foreach ($errors->all() as $error)
<li>{{ $error }}</li>
#endforeach
--
This isn't a direct solution for your question. However an even better approach (imo) than yours are custom requests. You can quickly generate custom requests by using the following command:
php artisan make:request CustomRequest
After that you can change type from Request to CustomRequest
public function send(CustomRequest $request)
{
$this->create($request->all());
return redirect($this->redirectToAfterSendMessage);
}
And in CustomRequest.php your extract your validation logic like so:
<?php
namespace App\Http\Requests;
use Illuminate\Foundation\Http\FormRequest;
class CustomRequest extends FormRequest
{
/**
* Determine if the user is authorized to make this request.
*
* #return bool
*/
public function authorize()
{
return true;
}
/**
* Get the validation rules that apply to the request.
*
* #return array
*/
public function rules()
{
return [
'name' => 'required',
'email' => 'required',
'message' => 'required',
];
}
public function messages()
{
return [
'name.required' => 'Name is required.',
'email.required' => 'Email is required.',
'message.required' => 'Message is required.',
];
}
}
Hope this helps.
You need to change:
"$this->recipient"
"$this->subject"
"$this->message"
To:
'recipient'
'subject'
'message'
Hi I am trying to add a custom admin panel to my laravel project. I have a login page. After entering valid email and password user can login to dashboard. But Problem is when i enter valid email and password it always stay in the login screen.
Here is my login form
<form class="form-horizontal" action="{{ route('admin.login') }}" method="post">
{!! csrf_field() !!}
<fieldset>
<div class="input-prepend" title="Email">
<span class="add-on"><i class="halflings-icon user"></i></span>
<input class="input-large span10" name="email" required maxlength="100" id="email" type="text" placeholder="type useremail"/>
</div>
<div class="clearfix"></div>
<div class="input-prepend" title="Password">
<span class="add-on"><i class="halflings-icon lock"></i></span>
<input class="input-large span10" name="password" required id="password" type="password" placeholder="type password"/>
</div>
<div class="clearfix"></div>
<label class="remember" for="remember"><input type="checkbox" id="remember" />Remember me</label>
<div class="button-login">
<button type="submit" class="btn btn-primary">Login</button>
</div>
<div class="clearfix"></div>
</fieldset>
</form>
Here is my route
Route::get('/admin/login', [
'as' => 'admin.login',
'uses' => 'AdminController#getLogin'
]);
Route::post('/admin/login', [
'as' => 'admin.login',
'uses' => 'AdminController#postLogin'
]);
Route::group(['middleware' => 'auth'
], function () {
Route::get('/admin', [
'as' => 'dashboard',
'uses' => 'AdminController#index']);
Route::get('/logout', [
'as' => 'logout',
'uses' => 'AdminController#getLogout'
]);
});
Here is my admin Controller
<?php
namespace App\Http\Controllers;
use Illuminate\Http\Request;
use App\Http\Requests;
use Auth;
class AdminController extends Controller
{
public function index()
{
return view('admin.admin_master');
}
public function getLogin()
{
return view('admin.admin_login');
}
public function postLogin(Request $request)
{
$this->validate($request, [
'email' => 'required|email',
'password' => 'required'
]);
if (Auth::attempt(['email' => $request['email'], 'password' => $request['password']])) {
// Authentication passed...
return redirect()->route('dashboard');
}
return redirect()->back()->with(['fail' => 'Could not Login']);
}
public function getLogout()
{
Auth::logout();
return redirect()->route('admin.login');
}
}
Here is Authenticate.php
use Closure;
use Illuminate\Support\Facades\Auth;
class Authenticate
{
/**
* Handle an incoming request.
*
* #param \Illuminate\Http\Request $request
* #param \Closure $next
* #param string|null $guard
* #return mixed
*/
public function handle($request, Closure $next, $guard = null)
{
if (Auth::guard($guard)->guest()) {
if ($request->ajax()) {
return response('Unauthorized.', 401);
} else {
return redirect()->guest(route('admin.login'))->
withError('You must be logged in !');
}
}
return $next($request);
}
}
Try this middleware
public function __construct(Guard $auth)
{
$this->auth = $auth;
}
/**
* Handle an incoming request.
*
* #param \Illuminate\Http\Request $request
* #param \Closure $next
* #return mixed
*/
public function handle($request, Closure $next)
{
if ($this->auth->guest()) {
if ($request->ajax()) {
return response('Unauthorized.', 401);
} else {
return redirect('/admin/login'); //edited line
}
}
return $next($request);
}
Try using absolute route instead of using it's alias.
May be it's redirect to login page, because both of your route are same for view getLogin and postLogin. Try to use action() method instead of route() in form action. Ex:
<form class="form-horizontal" action="{{ action('AdminController#postLogin') }}" method="post">
// other codes....
</form>
Tips: If you are using Laravel 5.2 put all of your route inside 'middleware'=>'web'. Ex:
Route::group(['middleware' => ['web']], function () {
// put your routes here.......
}
I had the same problem. I solved it using Auth:login($array). Change your code to
public function postLogin(Request $request)
{
$this->validate($request, [
'email' => 'required|email',
'password' => 'required'
]);
$data = $request->input();
if(Auth::login($data)){
return redirect('/dashboard');
}
return redirect()->back()->with(['fail' => 'Could not Login']);
}