Custom errorBag for different cards in one livewire form - laravel

My livewire form has four cards in it, and users can choose which cards they would like to answer, and it can be more than one card. So I did a condition that checks which cards are selected and only validates data and creates database entry based on the cards selected.
CardFormComponent.php:
public function submit()
{
$user = auth()->user();
if($this->showDiv1){
$salary_data = $this->validate([
'emp_name' => 'required',
'emp_length' => 'required',
'emp_monthly_gross_salary' => 'required',
'monthly_allowance' => 'required',
])->validateWithBag('salary_error');
}
if($this->showDiv2){
$gig_data = $this->validate([
'role' => 'required',
'est_earnings' => 'required',
])->validateWithBag('gig_error');
}
if($this->showDiv3){
$self_data = $this->validate([
'business_type' => 'required',
'other_type' => 'required',
'date_com_trade' => 'required',
'no_of_emp' => 'required',
'business_registration_number' => 'required',
'office_ph_no' => 'required',
'share_of_bus' => 'required',
'last_2_year_profit' => 'required'
])->validateWithBag('self_error');
}
if($this->showDiv4){
$investment_data = $this->validate([
'inv_name' => 'required',
'yearly_earning' => 'required',
])->validateWithBag('invest_error');
}
$user->user_current_step = Constant::CURR_STEP_COMMITMENT;
$user->save();
alert('success','Your income are saved.');
return redirect()->route('borrower.landing');
}
So this code works for saving the user input from all the cards, however, for example when I chose two cards, and submit an empty form, error messages only appear in the first card. When tested individually, error messages appear for all the cards, so I am sure that its not the problem with the display of the messages. My assumption is that once the validation fails in the first card, it straight away return to the view before going through the other loops. Is there any way to prevent the controller returning to the view before it goes through all the validation?
Additional note, a senior suggested me to use error bags for each cards, thus explaining the validateWithBag('name) in the code, but from my research it seems like I can only pass one error bags to the view? And it also seems like validateWithBag() does automatic redirection.
Is there any way from my code or any alternative for me to get all the error messages displayed according to the cards selected?

I got this answer from my facebook posting for this question and I thought I should share it here.
Answer:
Yes, the Laravel validate() method will stop execution of the code and return the errors.
You could try running a validate() only once at the end of the if statements, inside each if statement, you should add the rules that represent your Livewire models.
Hope this answers your question and helps you out.
The screencap on how to write the code

Related

Validating form comaring two fields values

I'm trying to find Laravel 8 documentation on how to validate comparing two fields to each other. I'm creating an app that allows creating matches from teams in a database table, using the create() method in the controller. I looked into Laravel #Validation, even #Custom Validation Rules, but I can't find anything when comparing the two fields.
public function store(Request $request)
{
$validatedData = $request->validate([
'local_team' => 'required',
'local_score' => 'required|numeric',
'visitor_team' => 'required',
'visitor_score' => 'required|numeric',
]);
$score = new Score();
$score->local_team = $request->local_team;
$score->local_score = $request->local_score;
$score->visitor_team = $request->visitor_team;
$score->visitor_score = $request->visitor_score;
$score->save();
$new = true;
return redirect()->route('scores.show',
['id' => $score->id, 'new' => true]);
}
In my case, the 'local_team' and 'visitor_team' fields should be different. Any clue on how to do it?

Array Validation: unique validation on multiple columns

I am trying to check unique validation on three columns employee_id,designation_id,station_id but the data are coming as an array which is making my situation unique and different from other SO questions/answers. I already checked few question like below: checks unique validation on multiple columns
But in my case, I can't get the value as they are inside an array. I also tried to implement Custom Rule or Request but in vain. For all the attempts, I am failing to get the field value such as $request->employee_id as they are inside an array for my case. May be I'm not trying it right.
Controller Code:
$this->validate($request, [
'posting.*.employee_id' => 'required,unique: // what to do here ??',
'posting.*.designation_id' => 'required',
'posting.*.station_id' => 'required',
'posting.*.from_date' => 'required|date',
]);
I am trying to validate uniqueness for both create and update (along with ignore $this->id facility) but don't know how to implement it here for array. It would be no problem if there was no array. Any help/suggestion/guide is much appreciated. Thanks in advance.
You can do this by creating a rule i.e UniquePosting so your controller code would look like
$this->validate($request, [
'posting' => ['required'],
'posting.*' => ['required', new UniquePosting()],
'posting.*.employee_id' => 'required',
'posting.*.designation_id' => 'required',
'posting.*.station_id' => 'required',
'posting.*.from_date' => 'required|date',
]);
Now inside your UniquePosting rule passes function will look like
public function passes($attribute, $value) {
$exists = Posting::where(['employee_id' => $value['employee_id'], 'designation_id' => $value['designation_id'],'station_id' => $value['station_id')->exists();
return !$exists;
}
Add any change if needed, overall that's the concept for testing uniqueness of the whole array.

Laravel: Validate input only if available in DOM

I created a form with the following fields:
Name
Email
Country
City
Address
If the user selects a country that has states (ex. United States) then the form transforms to:
Name
Email
Country
State
City
Address
To validate this I created a separate form request like so:
public function rules()
{
return [
'name' => 'required|max:255',
'email' => 'required|email,
'country_id' => 'required|integer',
'state_id' => 'nullable|integer',
'city_id' => 'required|integer',
'address' => 'required',
];
}
The problem is that if I leave it like that, then if I don't select a state it will pass validation.
If i make it:
'state_id' => 'sometimes|nullable|integer',
Then again it passes validation.
If I make it:
'state_id' => 'required|nullable|integer',
It will not pass validation, but then again it will throw a validation error if there is no state field in the form.
I read a lot of articles about this but nothing seems to solve it for me.
PS1: I want to solve this in the form request, not in the controller. I assume that an
if($request->has('states')){...}
can help, but then again, i would like to keep everything tidy in the form request.
PS2: I am using VueJS and Axios to add/remove states from the form. The whole form is actually a Vue component.
Any clues?
Thank you in advance!
You can conditionally add rules via the sometimes method on Validator.
$v->sometimes('state_id', 'required|integer', function ($input) {
return in_array($input->countries, [1,2,3,4...]
});
You could use the required_with line of parameters, but because the validation is based on the value of the input instead of just the presence, the custom validation rule is probably your best bet.
Per https://laravel.com/docs/5.7/validation#conditionally-adding-rules

Google reCaptcha always resetting with laravel 5.1

I've searched about it on internet but it seems to be different. I'm using laravel5.1 and implemented google recaptcha. The scenario is, if the form was submitted and returns the validation with error, the recaptcha is resetting again and again, what I want is to not to reset it again, just staying as validated, because it annoys users to validate again and again. Do you have any idea about this?
Update: for code
public function postRegister(Request $request){
// Validation
$this->validate($request, [
'username' => 'required|unique:users|max:20|min:3',
'password' => 'required|min:6',
'retype_password' => 'required|same:password',
'email' => 'required|unique:users|email|max:255',
'g-recaptcha-response' => 'required|recaptcha'
]);
// Database save part here...
return redirect()->route('register')->with('info', 'Success!');
}
This is a little more verbose now that I am trying to write the code, but you get the gist.
Validate your Recaptcha field first. If it is valid, set a session variable to prevent it being rendered in your form again.
public function postRegister(Request $request)
{
// Prepare validation rules
$defaultRules = [
'username' => 'required|unique:users|max:20|min:3',
'password' => 'required|min:6',
'retype_password' => 'required|same:password',
'email' => 'required|unique:users|email|max:255',
];
$recaptchaRules = [
'g-recaptcha-response' => 'required|recaptcha',
];
// Set session if recaptcha is valid
if (Validator::make($request->all(), $recaptchaRules)->passes()) {
session(['recaptcha' => true]);
}
// Add recaptcha rules to default rules if failed to get single message bag with all errors
else {
$defaultRules = array_merge($defaultRules, $recaptchaRules);
}
// Validation
$this->validate($request, $defaultRules);
// Database save part here...
// Reset recaptcha validity so that the recaptcha is displayed on the next submission
session(['recaptcha' => false]);
return redirect()->route('register')->with('info', 'Success!');
}
Only output the Recaptcha field it if hasn't already been validated.
#unless (session('recaptcha'))
{{ Recaptcha::render() }}
#endunless

Laravel 5 validation rules

previously I have used validation within a Request class e.g.
public function rules()
{
return [
'userName' => 'required', 'min:3',
'userEmail' => 'required|email',
'departmentId' => 'required',
'slug' => 'required',
];
}
But I now have another form but I can't see any options within the documentation that might help me.
Basically, lets say I have a form with the same fields as the validation above. The only time validation should fail is if ALL fields contain absolutely no data. So if I put something like "hi" within the slug input and submit, it should pass the validation.
Would something like this be possible?
Thanks
You can probably use the required_without_all validation rule.
http://laravel.com/docs/5.1/validation#rule-required-without-all
The field under validation must be present only when all of the other
specified fields are not present.
It would give you something like
public function rules()
{
return [
'userName' => 'required_without_all:userEmal,departmentId,slug','min:3',
'userEmail' => 'required_without_all:userName,departmentId,slug|email'
...
];
}
But it's not very handy if you have a lot of fields.
If you have to deal with many fields, creating a custom validator might be a better solution.
http://laravel.com/docs/5.1/validation#custom-validation-rules

Resources