Laravel Validate numeric multidimensional array - php

I want to give an error message if a string is entered in a integer inputfield with an multidimensional array.
View:
<div class="col-md-8">
<input name="answer[sleep][score]" type="text" class="form-control #error('answer[sleep][score]') #enderror" placeholder="Score" value="{{ #$answer_array['sleep']['score'] }}">
#error('answer[sleep][score]')
<span class="invalid-feedback" role="alert">
<strong>Geen letters alsjeblieft.😉</strong>
</span>
#enderror
</div>
Controller:
$request->validate([
'answer.sleep.score' => 'nullable|numeric',
]);
when i click save it just refreshes the page and does nothing. Can anybody please help me, how do i show the error on a multidimensional array.
Thanks!

#error is a blade directive used to display error messages in your template. The right way to use it is:
#error('answer.sleep.score')
<div>{{ $message }}</div>
#enderror
Notice that in order to detect whether the error message exists, I'm using the same format as you did in the validation i.e. answer.sleep.score and NOT answer[sleep][score].
If you want to add a class to your input element when an error is detected you can do this:
<input name="answer[sleep][score]" type="text" class="form-control {{ $errors->has('answer.sleep.score') ? 'error-class' : '' }}" placeholder="Score" value="{{ old('answer.sleep.score') }}">
By using old, you can pre-fill input field with the posted value.

You can use regular expression for the validation will be much better then this:
$request->validate([
'answer.sleep.score' => 'nullable|regex:/^[0-9]*$/',
]);
This allow you to enter only numbers in the field.

Related

Catch only one specific error in Laravel 7

I have a registration form, which contains the email and password fields. Currently, it returns the following errors in case the user does something wrong:
The email has already been taken.
The password must be at least 8 characters.
The password confirmation does not match.
However, I want that, when the user errs in the registry, only the error he made appears. I don't know if it is necessary to show the form, since there are only two input fields and a button. But, here is the code I made to return the errors:
#if(Session::has('errors') || count($errors) > 0)
#foreach($errors->all() as $error)
<div>
<h3>{{ $error }}</h3>
</div>
#endforeach
#endif
If you have an input like:
<input type="text" name="username" />
You can get the specific error, in the same view, like this:
#error('username')
<span>{{ $message }}</span>
#enderror

Using #error directive to target the previous input field from multiple input fields after submit in Laravel 5.8

The new #error directive was introduced in Laravel 5.8.13. So, instead of doing this:
// old
#if ($errors->has('email'))
<span>{{ $errors->first('email') }}</span>
#endif
You can now do this
// new
#error('email')
<span>{{ $message }}</span>
#enderror
However, I'm having issues trying to target only the input fields where the error was made among several similar input fields. These fields are similar because they have the same name. But they are also in seperate forms and have different submit buttons.
My html blade file is setup with multiple inputs generated from a #forelse statement. I've created a simple error check to check if a negative number is entered and to redirect back to the same page with an error message. The #error directive is also used to insert a custom class to target input field for styling.
#forelse($accounts as $account)
<form method="POST" action="{{ route('account.update', $account->id) }}">
#csrf
<div>
<input type="number" name="credit" class="#error('credit') is-invalid #enderror" required>
<input type="submit" class="btn" value="ok">
#error('credit')
<span class="invalid-feedback" role="alert">
<strong>{{ $message }}</strong>
</span>
#enderror
</div>
</form>
#empty
#endforelse
The form submits to the update() method in AccountController.php
public function update(Request $request, Account $account)
{
if($request->input('credit') < 0)
{
return back()->withErrors(['credit'=>'enter a positive amount']);
}
// ... other logic
}
The problem is that when a negative number is entered in one input field, the error message shows up for every input with the same name, even when they are not in the same form.
I think making the input names unique will solve this, but this will make my backend logic more complex than is required.
Is there anyway of making the error message show for just the target input after the redirect, without having to use unique names for each input field?
Interestingly, the #error directive is not programmatically tied to any input field by an input name. It is only spatially related to an input field by proximity and can be placed any where on the page.
Also, you can conveniently use any string within the #error directive as long as same is passed to the withErrors() call in the controller.
So, solving the problem of targeting the appropriate input among multiple ones becomes as simple as using any unique string (not necessarily the target input name) as key in the withErrors() method call and retrieving the error message by passing the same string to the #error directive. In my case, I chose to use the account id as the unique string.
In AccountController.php:
public function update(Request $request, Account $account)
{
if($request->input('credit') < 0)
{
return back()->withErrors([$account->id=>'enter a positive amount']);
}
// ... other logic
}
And in the html blade template:
#forelse($accounts as $account)
<form method="POST" action="{{ route('account.update', $account->id) }}">
#csrf
<div>
<input type="number" name="credit" class="#error($account->id) is-invalid #enderror" required>
<input type="submit" class="btn" value="ok">
#error($account->id)
<span class="invalid-feedback" role="alert">
<strong>{{ $message }}</strong>
</span>
#enderror
</div>
</form>
#empty
#endforelse
NOTE: Using a non existent key in any #error directive breaks the code for other #error directives and will cause no error messages to be displayed.
A solution would be doing the following:
store the value / posted form in a variable using the value of the submit button
ditch the error directive and use the old version
combine the old version with the variable to check wether you have the correct form or not
You'll get something like this:
#if ($errors->has('email') && $submitted_form_identifier === $form_identifier)
<span>{{ $errors->first('email') }}</span>
#endif

How to get old value of a field using vue inside blade.php

I am having a registration form that uses vue inside Laravel blade file. I'm using a validator for invalid inputs of user and I want to get the old value of the field but now I can't make it work since some of the fields are using vue. Here's my code:
regist.blade.php
<div class="regist_input">
<input type="email" name="email" v-model="email" v-bind:placeholder="placeholder_email" v-bind:class="{ error: emailError }">
<p class="error_text" v-bind:class="{ active: emailError2 }">Invalid email.</p>
#if($errors->has('email'))
<p class="alert-error">
{{ $errors->first('email') }}
</p>
#endif
</div>
<dd>
<div class="regist_input">
<input class="input_company" type="text" name="company" value="{{ old('company') }}" placeholder="company"> //this one works
</div>
</dd>
controller
if($validator->fails()) {
return redirect()->back()->withInput()->withErrors($validator->errors());
}
I can display its old value if out side the field, which means that my php function that validates is working.
I tried using v-bind:value="{{ old('email') }}" or :value="{{ old('email') }}" but is not working.For this one, how can I display the old value in the input field that has a vue component?
You could pass the blade email data to vue using data attributes.
First should add an id to an HTML element with data attribute on it. Then use blade to parse your data and set the data attribute to email data.
<div id="email-data" data-email="{{ old('email') }}"></div>
TO BE EXACT (OP)
<input type="email" value="{{ old('email') }}" name="email" v-model="email" id="email-data" data-email="{{ old('email') }}" v-bind:placeholder="placeholder_email"
v-bind:class="{ error: emailError }">
Then in the created / mounted hook in vue extract the data and set to the email state.
created() {
const el = document.getElementById('email-data')
const email = el.dataset.email
this.email = email
}
v-bind:value="{{ old('email') }}" or :value="{{ old('email') }} don't work because you are using v-model="email"
When you use v-model, it means that there should be an "email" property in the "data" attribute of a Vue component, and any value set to that "email" property will be what is displayed as the value of the input field.
See this Pen I created to illustrate both scenarios.
So, you'll need to remove the v-model if you want to use the v-bind:value. And now that I'm writing this, I don't think you need the v-bind:value and can just simply use value (just as you're doing with the company input.

How to show the old data in a form input in the Laravel

I write the form.blade.php like this:
<div class="form-group">
<label>Start at</label>
<div id="start_date" class="input-group date form_datetime col-md-4" data-date-format="yyyy-mm-dd hh:ii:ss">
<input class="form-control" name="start_at" size="16" type="text" value="{{ $activity->start_at }}">
<span class="input-group-addon"><span class="glyphicon glyphicon-remove"></span></span>
<span class="input-group-addon"><span class="glyphicon glyphicon-th"></span></span>
</div>
</div>
Both Create and Edit method use the view to display the form. In the Edit method, the $activity is used and everything is normal. But in the Create method, the $activity is null, so I have a error in {{ $activity->start_at }}.
I know I can use if(!empty($activity)) to prevent this error. but I do not want to use this anywhere.
What is the better way?
You could use this,
{{ $activity->start_at or '' }}
I also like to reuse code and use the same view to create or edit an object. What I do is to pass a brand new instance of the object to the create view. This way I have the object on its initial state including defaults (if any) and I am able to prefill those defaults (if any) on the displayed form. It gives me an additional benefit: if anything goes wrong with the validation at the server level the user doesn't lose any data, I just need to do something like this in the view:
<div class="form-group">
<label for="test_field" class="control-label">Fecha de firma</label>
<input type="text" value="{{ ( !empty($isabi) ? $isabi->fecha_firma : old('fecha_firma')) }}"
name="fecha_firma" id="isabi-fechafirma" class="form-control" placeholder="Este campo es obligatorio">
</div>
This is the create method with extra functionality removed for clarity (check if the user is authenticated, linking the created object with the company the user works for and other stuff):
public function create()
{
return view('isabis.create', [
"isabi" => new Isabi()
])->with($this->data);
}
I use $this->data for view configuration. Hope this helps.

Laravel4+Bootstrap: How to make fields red on validation error

Inside a Laravel4 + Bootstrap 2.3.1 I have a form properly working with validation.
There are three fields obligatory: Name - Email - Phone.
When nothing is inserted, or the email is not in a proper format, the error messages are displayed.
But besides this, I would like to make the fields red, to show better where the error is.
How can I do this in Laravel + Bootstrap?
This is the form with the three fields obligatory:
<form name="room" method="post" class="narrow_width">
<label><span><i class="icon-user"></i></span> Name <span class="color-red">*</span></label>
{{ Form::text('name',Input::old('name'), array('class' => 'span7 border-radius-none')) }}
<label><span><i class="icon-envelope-alt"></i></span> Email <span class="color-red">*</span></label>
{{ Form::text('email',Input::old('email'), array('class' => 'span7 border-radius-none')) }}
<label><span><i class="icon-phone"></i></span> Phone number <span class="color-red">*</span></label>
{{ Form::text('phone',Input::old('phone'), array('class' => 'span7 border-radius-none')) }}
<p><button type="submit" name="submit" class="btn-u">Send Message</button></p>
</form>
Thank you very much!
I don't think there's an easy way to do this with the laravel Form class. I personally use my own package https://github.com/AndreasHeiberg/theme for this. You can use it if you wan't but it's subject to change.
Anyway raw code to do this is the following:
<div class="control-group {{ $errors->has($id) ? 'error' : false }}">
<label for="{{ $id }}" class="control-label">{{ $text }} {{ $required ? '<span class="required-red">*</span>' : ''}}</label>
<div class="controls">
<input type="{{ $type }}" id="{{ $id }}" name="{{ $id }}" value="{{ $value }}">
#if ($helpText)
<span class='help-inline'>{{ $helpText }}</span>
#endif
#foreach($errors->get($id) as $message)
<span class='help-inline'>{{ $message }}</span>
#endforeach
</div>
</div>
This being the important part
<div class="control-group {{ $errors->has($id) ? 'error' : false }}">
You can wrap this up in a form macro http://laravel.com/docs/html#custom-macros use a helper function or my package to do this.
With my package you would just use:
+#formText('name')
You can easily use Form macros, there is a bunch available here for Bootstrap 3:
http://forums.laravel.io/viewtopic.php?id=11960
Hope this helps...
Thanks for your efforts, especially #AndHeiberg.
For reason of simplicity, i decide to renounce to Laravel-Bootstrap validation and use instead a jquery plugin: https://github.com/jzaefferer/jquery-validation
The main reason is that is extremely easy to use.
It's enough to call the plugin and insert 'required' into the tag.
And the plugin will do all the rest, highlighting the field in red and displaying an error message for that field.
If your intention is to make the error more obvious to where it is, you can wrap the message text that is returned from Laravel validation errors in a span and give styling to that.
{{ $errors->first('email', "<span class='error'>:message</span>")}}
where :message is a "placeholder" for your error message. And then you can give any styling to .error spans as you wish. Check this Laracast lesson for more details (after 3:10).
In bootstrap, you can create errorfield with the id "inputError":
<input type="text" class="form-control" id="inputError">

Categories