I am new in livewire. i am working on registration process of user. Register form is quite big and validations also working fine to me. The problem is when user submits the form validations came but user not able to see because submit button is at bottom and form is at top.
When i manually scroll to top error message is displaying. So what i want when user submits the form its will automatically go to first error message. Here is my code:
<form wire:submit.prevent="userRegister">
<div class="row">
<div class="col-md-3">
<label>First Name *</label>
</div>
<div class="col-md-9">
<input type="text" wire:model="register.first_name" placeholder="Enter First Name" required>
#error('register.first_name') <span class="text-danger">{{ $message }}</span> #enderror
</div>
</div>
<div class="row">
<div class="col-md-3">
<label>Last Name *</label>
</div>
<div class="col-md-9">
<input type="text" wire:model="register.last_name" placeholder="Enter Last Name">
#error('register.last_name') <span class="text-danger">{{ $message }}</span> #enderror
</div>
</div>
<div class="row">
<div class="col-md-3">
<label>Test 1 Name *</label>
</div>
<div class="col-md-9">
<input type="text" wire:model="register.test1_name" placeholder="Enter Last Name">
</div>
</div>
<div class="row">
<div class="col-md-3">
<label>Test 2 Name *</label>
</div>
<div class="col-md-9">
<input type="text" wire:model="register.test2_name" placeholder="Enter Last Name">
</div>
</div>
<div class="row">
<div class="col-md-3">
<label>Test 3 Name *</label>
</div>
<div class="col-md-9">
<input type="text" wire:model="register.test3_name" placeholder="Enter Last Name">
</div>
</div>
<div class="row">
<div class="col-md-3"></div>
<div class="col-md-9">
<!--<input type="submit" value="Edit" class="edt-sb">-->
<input wire:click="userRegister" type="submit" value="Submit" class="edt-sv">
</div>
</div>
</form>
My Register.php
<?php
namespace App\Http\Livewire;
use Livewire\Component;
class Register extends Component
{
public $register;
protected $rules = [
'register.first_name' => 'bail|required|max:50',
'register.last_name' => 'bail|required|max:50',
];
protected $messages = [
'register.first_name.required' => 'Please enter first name',
];
public function userRegister(){
$this->validate();
}
I want when user submits the form it will immediately scroll to first error message. Currently my validations work perfects for me. Do i need to use alpine js? for this.
Livewire errors will be saved in $errors bag so probably you can add an id to each field in your form and use alpinejs to focus the first element with the id present in the errors bag, something like:
<div x-data="{
'errors': {{ json_encode(array_keys($errors->getMessages())) }},
focusField(input) {
fieldError = document.getElementById(input);
if (fieldError) {
fieldError.focus({preventScroll:false});
}
},
}"
x-init="() => { $watch('errors', value => focusField(value[0])) }">
<input id="register.test3_name" type="text" wire:model="register.test3_name" placeholder="Enter Last Name">
</div>
I nearly faced the same issue but with success message not error messages, for error messages I used updated(), they are shown on real time for user while filling the fields.
My Class Component :
class FormSubmissions extends Component
{
public $city;
public $fullname;
protected $rules = [
'city' => 'required',
'fullname' => 'required',
];
public $successMessage;
public function updated($propertyName)
{
$this->validateOnly($propertyName);
}
public function submitForm()
{
$submission = $this->validate();
$this->successMessage = trans('site.success');
$this->resetForm();
}
public function resetForm()
{
$this->city = '';
$this->fullname = '';
}
}
My Blade template :
<div id="formSection" class="form-wrapper">
#if ($successMessage)
<div class="alert alert-success alert-dismissible fade show" role="alert">
{{ $successMessage }}
<button wire:click="$set('successMessage', null)" type="button" class="close" data-dismiss="alert" aria-label="Close">
<span aria-hidden="true">×</span>
</button>
</div>
<script>
var elmnt = document.getElementById("formSection");
elmnt.scrollIntoView();
</script>
#endif
<form wire:submit.prevent="submitForm" action="/" method="POST">
...
</div>
So the small script added with success message allowed me to scroll back to top of my form Section #formSection.
If you are using <x-jet-input-error/> component for displaying errors, you can just modify resources/views/vendor/jetstream/components/input-error.blade.php (make sure you have published livewire views) file to below code:
#props(['for'])
<span x-data="{hasError: '{{$errors->get($for)[0] ?? ''}}' }"
x-init="()=> { $watch('hasError', (value)=> {
let errorDiv = document.getElementsByClassName('invalid-feedback')[0];
if(errorDiv){
errorDiv.scrollIntoView({behavior: 'smooth', block: 'center', inline: 'nearest'});
}
})}">
#error($for)
<span {{ $attributes->merge(['class' => 'invalid-feedback d-block']) }} role="alert" style="font-size: inherit">
<strong>{{ $message }}</strong>
</span>
#enderror
</span>
Explanation : we use alpine to watch for changes in the validation message for the "$for" field. As soon as it changes (validation message shows up or vanishes), it looks for the error block and scrolls to it
Related
I am creating a database for books. When I was testing CRUD without image upload(normal CRUD), it was working. But when I added book cover image file as part of data input I get error "
Argument #1 ($rules) must be of type array, Illuminate\Http\Request given, called in
". I didn't understand what caused it, is it because validation or path image folder will be stored in?
Here it is image of error.
Model/Buku.php
class Buku extends Model
{
use HasFactory;
protected $fillable = [
'cover',
'nama_buku',
'author',
'terbitan',
'barcode',
'ketersediaan',
];
}
I suspect the error is in controllers code but didn't know why normal CRUD succeed but image upload CRUD fails.
Controllers/BukuController.php
protected function store(Request $request)
{
$request->validate($request, [
'cover' => 'required|file|image|mimes:jpeg,png,jpg,gif,svg|max:2048',
'nama_buku' => 'required',
'author' => 'required',
'terbitan' => 'required',
'barcode' => 'required',
'ketersediaan' => 'required',
]);
$input = $request->all();
if ($cover = $request->file('cover')) {
$destinationPath = 'cover/';
$profileImage = date('YmdHis') . "." . $cover->getClientOriginalExtension();
$cover->move($destinationPath, $profileImage);
$input['cover'] = "$profileImage";
}
Buku::create($input);
return redirect()->route('buku.index')->with('success','Buku has been created successfully.');
}
I don't know if the errors is actually from input so just in case here is views create blade
Views/create.blade.php
<form action="{{ route('buku.store') }}" method="POST" enctype="multipart/form-data">
#csrf
<div class="row">
<div class="col-xs-12 col-sm-12 col-md-12">
<div class="form-group">
<strong>Cover:</strong>
<input type="file" name="cover" placeholder="Cover Buku"
class="block w-full text-sm text-gray-500 file:mr-4 file:py-2 file:px-4 file:rounded-full file:border-0 file:text-sm file:font-semibold file:bg-blue-50 file:text-blue-700 hover:file:bg-blue-100" />
#error('cover')
<div class="alert alert-danger mt-1 mb-1">{{ $message }}</div>
#enderror
</div>
</div>
<div class="col-xs-12 col-sm-12 col-md-12">
<div class="form-group">
<strong>Nama Buku:</strong>
<input type="text" name="nama_buku" class="form-control" placeholder="Nama Buku">
#error('nama_buku')
<div class="alert alert-danger mt-1 mb-1">{{ $message }}</div>
#enderror
</div>
</div>
<div class="col-xs-12 col-sm-12 col-md-12">
<div class="form-group">
<strong>Author:</strong>
<input type="text" name="author" class="form-control" placeholder="Author Buku">
#error('author')
<div class="alert alert-danger mt-1 mb-1">{{ $message }}</div>
#enderror
</div>
</div>
<div class="col-xs-12 col-sm-12 col-md-12">
<div class="form-group">
<strong>Terbitan:</strong>
<input type="text" name="terbitan" class="form-control" placeholder="Terbitan Buku">
#error('terbitan')
<div class="alert alert-danger mt-1 mb-1">{{ $message }}</div>
#enderror
</div>
</div>
<div class="col-xs-12 col-sm-12 col-md-12">
<div class="form-group">
<strong>Barcode:</strong>
<input type="text" name="barcode" placeholder="Barcode Buku" id="scanner" />
#error('barcode')
<div class="alert alert-danger mt-1 mb-1">{{ $message }}</div>
#enderror
</div>
</div>
<div class="col-xs-12 col-sm-12 col-md-12">
<div class="form-group">
<strong>Ketersediaan:</strong>
<input type="number" name="ketersediaan" class="form-control" placeholder="Ketersediaan Buku">
#error('ketersediaan')
<div class="alert alert-danger mt-1 mb-1">{{ $message }}</div>
#enderror
</div>
</div>
<button type="submit" class="btn btn-primary ml-3">Submit</button>
</div>
</form>
I also tried image upload code when I was still using Laravel 4, still get the same error. Did anyone know how to fix this?
The error states it pretty clearly. You pass a Request object where an array is expected.
Instead of using the object directly, you should use the all() method, which creates an array with all the posted fields in your request. Or in this case, you can leave the request->all() out, because the method is already called on the request object.
$request->validate($request,...)
$request->validate($request->all(),...)
$request->validate(['cover' => ....])
#########EDIT
It is also not recommended to insert all request data. You should only insert validated data.
$input = $request->all();
Buku::create($input);
You should use one of the two following approaches to only insert validated data: https://laravel.com/docs/10.x/validation#working-with-validated-input
I have a form with which I add posts. I want to integrate CKEDITOR, to manipulate the content in textarea. to initialize the editor, I use the following code :
<script src="ckeditor/ckeditor.js">
ClassicEditor
.create(document.querySelector('#post_content'))
.then(editor=>{
editor.model.document.on('change:data',(e)=>{
#this('post_content').set('post_content', e.editor.getData());
});
})
.catch(error=>{
console.error(error);
});
</script>
When I submit form, I get the following error :
> Undefined variable $_instance
here's my form, I mention that without CKEDITOR, it works
<form wire:submit.prevent="addNewPost()" method="post" id="createPostForm" enctype="multipart/form-data">
<div class="card">
<div class="card-body">
<div class="row">
<div class="col-md-9">
<div class="mb-3">
<label for="" class="form-label">
Titlu
</label>
<input type="text" wire:model="post_title" name="post_title" class="form-control" placeholder="Titlul articolului" value="{{old('post_title')}}">
<span class=" text-danger ">#error('post_title') {{$message}}#enderror</span>
</div>
<div wire:ignore class="mb-3">
<label for="" class="form-label">
Continutul articolului
</label>
<textarea wire:model="post_content"class="ckeditor form-control" id="post_content" name="post_content" cols="30" rows="10" >{{$post_content}}</textarea>
<span class="text-danger">#error('post_content'){{$message}}#enderror</span>
</div>
</div>
<div class="col-md-3">
<div class="mb-3">
<div class="form-label">
Categoria articolului
</div>
<select wire:model="post_category" name="post_category" id="" class="form-select">
<option value="">--Nu ati ales nimic--</option>
#foreach (\App\Models\SubCategory::all() as $category)
<option value="{{$category->id}}">{{$category->subcategory_name}}</option>
#endforeach
</select>
<span class="text-danger">#error('post_category'){{$message}}#enderror</span>
</div>
<div class="mb-3">
<div class="form-label">
Imaginea articolului
</div>
<input type="file" wire:model="post_image" name="post_image" class="form-control">
<span class="text-danger ">#error('post_image'){{$message}}#enderror</span>
</div>
<div class="image-holder mb-2" style="max-width: 250px;">
<img src="" alt="" class="img-thumbnail" id="image-previewer" data-ijabo-default-img=''>
</div>
<button type="submit" id="sub" class="btn btn-primary">Salveaza</button>
</div>
</div>
</div>
</div>
</form>
And this is my component Posts.php
<?php
namespace App\Http\Livewire;
use App\Models\Post;
use Livewire\Component;
Use Livewire\WithFileUploads;
use App\Traits\ShowToastrTrait;
class Posts extends Component
{
use withFileUploads;
use showToastrTrait;
public $post_title, $post_content, $post_category, $post_image;
protected $rules = [
'post_title' => 'required|unique:posts,post_title|max:255',
'post_content' => 'required',
'post_image' => 'required|mimes:jpeg,png,jpg,gif,svg|max:2048',
'post_category' => 'required'];
protected $messages = [
'post_title.required' => 'Introduceti titlul articolului',
'post_title.unique' => 'Exista deja un asemenea titlu',
'post_content.required' => 'Introduceti continutul articolului',
'post_image.required' => 'Atasati o imagine articolului',
'post_image.mimes' => 'Imaginea trebuie sa fie in format jpeg/png/jpg/gif/svg',
'post_category.required' => 'Selectati categoria articolului',
];
public function addNewPost(){
dd($this);
$this->validate();
$post = Post::addNewPost($this);
if(!$post){
$this->showToastr('Articolul nu a putut fi adaugat','error');
}
$this->showToastr('Articolul a fost adaugat cu succes','success');
$this->reset();
}
public function render()
{
return view('livewire.posts');
}
}
I assume you have the script and the component view in separate files and that's why you get an error on #this('post_content').set('post_content', e.editor.getData()); line.
According to the docs, both should be placed in the same file (component file), then #this will be available in the script (you can read more about that here)
Example: let's assume you have a form component that will look like this:
<form>
<!-- your form elements -->
</form>
#push('scripts')
<script>
// accessing #this here should work
</script>
#endpush
Hope it helps :)
I want to validate all field. But It is validating only first field. Append field is not validating
multiple fields validation using livewire? name.0.required is working but name.*.required is not working.
<?php
namespace App\Http\Livewire;
use Livewire\Component;
class Test extends Component
{
public $name;
public $inputs = [];
public $i = 1;
public function add($i)
{
$i = $i + 1;
$this->i = $i;
array_push($this->inputs ,$i);
}
public function remove($i)
{
unset($this->inputs[$i]);
}
public function store()
{
$validatedDate = $this->validate([
'name.0' => 'required',
'name.*' => 'required',
],
[
'name.0.required' => 'name field is required',
'name.*.required' => 'name field is required',
]
);
session()->flash('message', 'Name Has Been Created Successfully.');
}
public function render()
{
return view('livewire.test');
}
}
<div>
<form class="offset-md-3">
#if (session()->has('message'))
<div class="alert alert-success">
{{ session('message') }}
</div>
#endif
<div class="add-input">
<div class="row">
<div class="col-md-5">
<div class="form-group">
<input type="text" class="form-control" placeholder="Enter Name" wire:model="name.0">
#error('name.0') <span class="text-danger error">{{ $message }}</span>#enderror
</div>
</div>
<div class="col-md-2">
<button class="btn text-white btn-info btn-sm" wire:click.prevent="add({{$i}})">Add</button>
</div>
</div>
</div>
#foreach($inputs as $key => $value)
<div class=" add-input">
<div class="row">
<div class="col-md-5">
<div class="form-group">
<input type="text" class="form-control" placeholder="Enter Name" wire:model="name.{{ $value }}">
#error('name.'.$value) <span class="text-danger error">{{ $message }}</span>#enderror
</div>
</div>
<div class="col-md-2">
<button class="btn btn-danger btn-sm" wire:click.prevent="remove({{$key}})">remove</button>
</div>
</div>
</div>
#endforeach
<div class="row">
<div class="col-md-12">
<button type="button" wire:click.prevent="store()" class="btn btn-success btn-sm">Save</button>
</div>
</div>
</form>
</div>
This is my full code use to create multi field using livewire. I am not able to validate appended field so I need help to solve this problem. This validate first field name.0 other append field name.* does not validate.
You should use $key instead $value.
Like this:
wire:model="name.{{ $key }}"
I am trying to update a single field in my user profile form section in the Laravel app.
I can save fields correctly in DB but input values and placeholders are taking wrong values. In every hit Save, the values doesn' change, and they are taken from the last listed user profile details. In my case this is user#3. The problem is when I log in with the user's #1 credentials, value and placeholder are taken from user #3. When I log in with user #2, again from user #3. Only values of user#3 are correct and I can manipulate it with no issues for both fields.
When i update the profile fields with user#1 it saves the entered one filed, but because the 2nd filed inherits the user#3 input details it saves it in field 2 of user#1 which makes a wrong entry. I can't leave null in those fields by default. My mass assignment is guarded.
How can save/update just a single field in the blade template without affecting the other fields in the form?
My routes:
Route::get( '/profile', 'userController\\profileEdit#profileEdit')->name('profileEdit');
Route::post('/profile', 'userController\\profileEdit#update')->name('update');
My controller:
namespace App\Http\Controllers\userController;
use App\Model\Hause_users;
use App\Http\Controllers\Controller;
use Illuminate\Http\Request;
class profileEdit extends Controller
{
function profileEdit (Request $request){
$user = Hause_users::all();
$name = $request->session()->get('name');
$request->session()->keep([request('username', 'email')]);
return view('frontview.layouts.profile',['user'=>$user])->with('username' , $name );
}
function update (Request $request){
$user = Hause_users::where('username', $request->session()->get('name'))->first();
$user->fill(['email' => request('Email')]) ;
$user->save();
$user->phone;
//dd($user->phone->phone);
if ($user->phone === null) {
$user->phone->phone->create(['phone' => request('tel')]);
}
else{
$user->phone->update(['phone' => request('tel')]);
}
return back()->withInput();
}
Blade file: `
#extends('frontview.layouts.userView')
#extends('frontview.layouts.default')
#if ($errors->any())
<div class="alert alert-danger">
<ul>
#foreach ($errors->all() as $error)
<li>{{ $error }}</li>
#endforeach
</ul>
</div>
#endif
#section('title')
#endsection
#section('content')
#foreach($user as $v )
#endforeach
<h2 class="form-group col-md-6">Здравей, {{$username }} </h2>
<form class = "pb2" method="POST" name = 'profile' action='profile' >
{{ csrf_field()}}
<div class="form-row">
<div class="form-group col-md-6">
<label for="inputEmail4">Поща</label>
<input type="email" class="form-control" name = "Email" id="inputEmail4"
value="{{$v['Email']}}"
placeholder="{{$v->Email}}">
</div>
<div class="form-group col-md-6">
<label for="inputPassword4">Промени Парола</label>
<input type="password" class="form-control" id="inputPassword4" placeholder="Парола">
</div>
</div>
<div class="form-group">
<label for="inputAddress">Address</label>
<input type="text" class="form-control" name = "Adress" id="inputAddress" placeholder="Снежанка 2">
</div>
<div class="form-row">
<div class="form-group col-md-6">
<label for="inputAddress">Телефон</label>
<input class="form-control" type="text" name = 'tel' value="{{$v->phone['phone']}}"
placeholder="{{$v->phone['phone']}}"
id="example-tel-input" >
</div>
</div>
<div class="form-row">
<div class="form-group col-md-6">
<label for="inputCity">Град</label><input type="text" class="form-control" id="inputCity">
<label for="inputCity">Квартал</label><input type="text" class="form-control" id="inputCity">
</div>
{{--<div class="col-md-6" >--}}
{{--<label for="image">Качи снимка</label>--}}
{{--<input type="file" name = "image">--}}
{{--<div>{{$errors->first('image') }}</div>--}}
{{--</div>--}}
</div>
{{--<div ><img src="https://mdbootstrap.com/img/Photos/Others/placeholder-avatar.jpg"--}}
{{--class="rounded-circle z-depth-1-half avatar-pic" alt="example placeholder avatar">--}}
{{--</div>--}}
{{--<div class="d-flex justify-content-center">--}}
{{--<div class="btn btn-mdb-color btn-rounded float-left">--}}
{{--<span>Add photo</span>--}}
{{--<input type="file">--}}
{{--</div>--}}
{{--</div>--}}
{{--</div>--}}
<div class="form-group">
<div class="form-check">
<input class="form-check-input" type="checkbox" id="gridCheck">
<label class="form-check-label" for="gridCheck">
Запомни ме!
</label>
</div>
</div>
<button type="submit" class="btn btn-primary">Запази</button>
</form>
#endsection
#section('name')
{{ $username }}
#endsection
Output summary:
On img#1 are the correct entry details . This is other section not the Profile edit one. Currently loged user is U#1 but as you can see on image 2, values and placeholder of both fields are for the U#3. When i hit the blue button U#1 saves the untouched filed input of U#3. Same is when i log in with U#2.
Actually the answer here is quite simple. What i am doing wrong is that i am not passing the value of the currently logged user to the view correctly. On my profileEdit method i was using $user = Hause_users::all(); and then looping trough all id's into the view and then fetching every field. But because the view doesn know which user passes the data, the foreach always returns the last user id from the array with its input, no matter which user is currently logged in. Then the data was overridden with wrong inputs.
The solution is also simple.
Instead of $user = Hause_users::all();
i have used
$user = Hause_users::where('username', $request->session()->get('name'))->first();
and then into view i was objecting the $user variable without any loops like this:
<form class = "pb2" method="POST" name = 'profile' action='profile' >
<input type="hidden" name="_token" value="{{ csrf_token() }}">
{{--<input type="hidden" name="_method" value="PATCH">--}}
<div class="form-row">
<div class="form-group col-md-6">
<label for="inputEmail4">Поща</label>
<input type="Email" class="form-control" name = "Email" id="inputEmail4"
value="{{$user->Email}}"
placeholder="{{$user->Email}}">
</div>
<div class="form-group col-md-6">
<label for="inputPassword4">Промени Парола</label>
<input type="password" class="form-control" id="inputPassword4" placeholder="Парола">
</div>
</div>
<div class="form-group">
<label for="inputAddress">Address</label>
<input type="text" class="form-control" name = "Adress" id="inputAddress" placeholder="Снежанка 2">
</div>
<div class="form-row">
<div class="form-group col-md-6">
<label for="inputAddress">Телефон</label>
<input class="form-control" type="text" name = 'tel' value="{{$user->phone['phone']}}"
placeholder="{{$user->phone['phone']}}"
id="example-tel-input" >
Basically this is a detailed explanation to all that not using the built in Auth system of Laravel
I have a form which have name, email and phone. But i want current page title or url when user submit the form, Because I want to track the user page. Please let me know How i can do it.
This is my form code.
<form class="callus" method="post" action="{{url('/sendmailuser')}}">
#csrf
<div class="col-md-3 col-sm-6">
<div class="single-query form-group">
<input type="hidden" name="product_title" value="{{ request('request') }}" class="keyword-input" placeholder="Enter Your Name" required="">
</div>
</div>
<div class="col-md-3 col-sm-6">
<div class="single-query form-group">
<input type="text" name="user_name" class="keyword-input" placeholder="Enter Your Name" required="">
</div>
</div>
<div class="col-md-3 col-sm-6">
<div class="single-query form-group">
<input type="text" name="user_email" class="keyword-input" placeholder="Enter Your Email" required="">
</div>
</div>
<div class="col-md-3 col-sm-6">
<div class="single-query form-group">
<input type="text" name="user_phone" class="keyword-input" placeholder="Enter Your Phone" required="Field is required">
</div>
</div>
<div class="col-md-3 col-sm-6">
<div class="single-query form-group">
<input type="submit" value="submit now" class="btn-blue">
</div>
</div>
</form>
This is my Email send code...
public function sendyourmail(Request $r)
{
$validator = Validator::make($r->all(), [
'user_name' => 'required',
'user_email' =>'required',
'user_phone' =>'required',
'user_desc' =>'required',
]);
if ($validator->fails()) {
return redirect()->back()->withErrors($validator);
}
$data=[
'user_email' => $r->user_email,
'user_name' => $r->user_name,
'user_phone' => $r->user_phone,
'user_desc' => $r->user_desc,
];
Mail::send('mail', $data, function($message) use($data) {
$message->from($data['user_email'], 'Email Form Sumit');
$message->to('sumit#gmail.com')->cc('sumit#sumit.com');
$message->subject($data['user_desc']);
});
return redirect()->back()->with('message','Your Mail Has Been sent Successfully, We Will Get Back to You Shortly.');
}
You should define the title of the rendered page within the controller and past it as parameter to the view when you specify which template should be rendered.
public function sendyourmailform()
{
$title = 'Sample Page Title';
return view('email_template.blade.php', compact('title'));
}
Because the title variable is past to the template you can access it inside the template by rendering it twice inside the title section
#section('title')
{{ $title }}
#endsection
Inside the layout page which is extends by the template which render the form you should have define section named title like this
<head>
<title>
#section('title')
#endsection
<title>
</head>
And you have access to the title variable inside the template part which show the related form.
<form class="callus" method="post" action="{{url('/sendmailuser')}}">
#csrf
<div>
<input type="hidden" name="page_title" value="{{ $title }}">
</div>
<!-- ... -->
</form>