I have a Vue form that let users add work experience for there profile.
Users can add extra experience by clicking on a button. Clicking on that will add an new item with new input fields. I can't add the whole script because it's quit big. But here is an example to give you an idea:
<div class="item">
<div class="row">
<div class="form-group col-md-6">
<label class="form-label">Title</label>
<input type="text" name="experiences[0][title]" class="form-control">
</div>
<div class="form-group col-md-6">
<label class="form-label">Institution</label>
<input type="text" name="experiences[0][institution]" class="form-control">
</div>
</div>
<div class="row">
<div class="col-md-12">
<textarea name="experiences[0][comments]" class="form-control"></textarea>
</div>
</div>
</div>
<div class="item">
<div class="row">
<div class="form-group col-md-6">
<label class="form-label">Title </label>
<input type="text" name="experiences[1][title]" class="form-control">
</div>
<div class="form-group col-md-6">
<label class="form-label">institution </label>
<input type="text" name="experiences[1][institution]" class="form-control">
</div>
</div>
<div class="row">
<div class="col-md-12">
<textarea name="experiences[1][comments]" class="form-control"></textarea>
</div>
</div>
</div>
After each element there is a button to add a new row. This works fine but I have some validation issues.
I only want to validate the fields if one of the fields has a value. For example:
If experiences[0][institution] has a value, experiences[0][title] and experiences[0][comments] are required.
This has to work in every order. If title has a value, the other fields are required.
I can't really find out a way how to validate this. This is my validation rule:
$this->validate(request(), [
'experiences.*.title' => 'required_if:experiences.*.institution,null',
'experiences.*.institution' => 'required_if:experiences.*.title,null',
]);
Problem here is that it simply doesn't validate. I can't figure out how to make a rule that says, if field X has a value, Y and Z are required.
Hope anyone here can help me finding a solution! :)
Like Azeame said, make a custom validation rule and check if all values are filled or all are empty. Something in de lines of:
public function passes($attribute, $value)
{
$required = ['title','institution','comments'];
$experience = collect($value)->reject(function ($item, $key) {
return empty($item);
});
if (count($experience) == 0) {
return true;
}
foreach ($required as $field) {
if ( !$experience->has($field)) {
return false;
}
}
return true;
}
Maybe there is a beter way, but this should work.
required_if doesn't work with null as it will treat it as a string ("null"), it will work with boolean values though.
Instead you can use the required_without rule:
$this->validate(request(), [
"experiences.*.title" => "required_without:experiences.*.institution",
"experiences.*.institution" => "required_without:experiences.*.title",
]);
Example
$experiences = [
[
"title" => "My title",
"institution" => "",
"comments" => "<p>My first description</p>", //passes
],
[
"title" => "",
"institution" => "My title",
"comments" => "<p>My second description</p>", //passes
],
[
"title" => "My title",
"institution" => "My title",
"comments" => "<p>My third description</p>", //passes
],
[
"title" => "",
"institution" => null,
"comments" => "<p>My forth description</p>", //fails
],
];
$rules = [
"experiences.*.title" => "required_without:experiences.*.institution",
"experiences.*.institution" => "required_without:experiences.*.title",
];
$validator = Validator::make(compact('experiences'), $rules);
dd($validator->fails());
Write a custom rule with php artisan make:rule and in the passes() function write a check to ensure that all of the array keys are present and also that at least 2 of the array values are not null. I'm thinking something like this:
function passes($attribute, $value){
if(array_keys($value) !== ['title','institution','comments']){
return false;
}
if(empty($value['title']) && empty($value['institution'])){
return false;
}
return true;
}
and in your $this->validate pass the rule as ['experiences.*' =>['array', new CustomRule()] instead of required_if...
I haven't checked this so feel free to edit if it's broken.
Related
I am trying to post an array from my form to database
The form fields are showing up as NULL
HTML form excerpt:
#foreach (range(0,9) as $x)
<div class="row m-3 credit-card-details">
<div class="col-lg-4">
<div class="form-group">
<label for="financeCompany-{{ $x }}">Finance Company name #{{ $x }}</label>
<input type="text" class="form-control" id="financeCompany-{{ $x }}" name="creditCards[{{ $x }}][financeCompany]" value="" placeholder="Finance Company Name" />
</div>
</div>
<div class="col-lg-4">
<div class="form-group">
<label for="creditLimit-{{ $x }}">Credit limit</label>
<input type="text" class="form-control" id="creditLimit-{{ $x }}" name="creditCards[{{ $x }}][creditLimit]" value="" placeholder="$" />
</div>
</div>
<div class="col-lg-4">
<div class="form-group">
<label for="consolidate-{{ $x }}">Consolidate this card?</label>
<input type="text" class="form-control" name="creditCards[{{ $x }}][consolidate]" id="consolidate-{{ $x }}" value="" />
</div>
</div>
</div>
#endforeach
My Controller:
public function store(CreateApplicationRequest $request, Applicant $applicant, CreditCard $creditCard)
{
$applicant = Applicant::create([
...
]);
$application = $applicant->application()->create([
...
]);
$creditCards = $request->input('creditCards');
foreach ($creditCards as $creditCard)
{
$application->creditCards()->create([
'financeCompany' => $request->input('financeCompany'),
'creditLimit' => $request->input('creditLimit'),
'consolidate' => $request->input('consolidate')
]);
}
...
}
My dd results are showing up like this:
The right amount of records are being created in my credit_cards table and the application_id, created_at and updated_at fields are being correctly recorded, however the financeCompany, creditLimit and consolidate fields (from the form) are all showing up as NULL.
Database:
CreditCard model:
protected $fillable = [
'application_id',
'financeCompany',
'creditLimit',
'consolidate'
];
Only the application_id is being collected by the database.
Still quite new at this, any help would be greatly appreciated.
so your request() has $creditCards by the look of it. The values you are interested in seems to be within $creditCards
you need to do something like this
collect($creditCards)
->each(fn ($creditCard) => $application->creditCards()
->create([
'financeCompany' => creditCard['financeCompany'],
'creditLimit' => creditCard['creditLimit'],
'consolidate' => creditCard['consolidate']
])
);
or if you want to use foreach
foreach ($creditCards as $creditCard) {
$application->creditCards()->create([
'financeCompany' => creditCard('financeCompany'),
'creditLimit' => creditCard('creditLimit'),
'consolidate' => creditCard('consolidate')
]);
}
Make sure you have them declared in the $fillable in your model otherwise the ORM will not pick them up.
Example:
protected $fillable = [
'financeCompany',
'creditLimit',
'consolidate',
];
Using Laravel I created a form where dynamically input fields can be added and remove using jQuery.
I am now trying to insert the data into the database, there I encounter a problem. My database exists of two tables; Tasks and issues.
The 'issue' table is linked to the tasks table bij task_id. This task_id should be also sent to the database but I can't get it, wright. See my code below.
Thanks for the help.
IssueController.php
The first method works but then my task id "null". All records are inserted from all fields.
The second method only adds the data of 1 field but it adds the correct id.
public function store(Request $request, Issue $issue, Task $task)
{
## First method
// foreach($request->issueInfo as $key => $value) {
// Issue::create($value);
// }
## Second method
foreach ($request->issueInfo as $key => $name) {
dd($name);
$names[] = [
'task_id' => $task->id,
'issue_name' => $name,
'issue_time' => $name,
'issue_date' => $name,
'issue_type' => $name,
];
}
Issue::insert($names);
return back();
}
web.php
Route::post('/tasks/{task}/issues', 'IssueController#store');
show.blade.php
#extends('layout')
#section('content')
<script>
$(document).ready(function() {
var i = 1;
$('.addmore').click(function(){
i++;
$('#dynamicFields').append('<div class="form-group"><label for="issue_name">Issue Name</label><select class="form-control" name="issueInfo['+i+'][issue_name]"><option></option><option value="Error">Error</option><option value="Grammer">Grammer</option><option value="Undefined">Undefined</option><option value="Typpo">Typpo</option><option value="No errors">No errors</option></select></div><div class="form-group"><label for="issue_date" class="label">Issue Date</label><input class="form-control" type="date" name="issueInfo['+i+'][issue_date]"></div><div class="form-group"><label for="issue_time" class="label">Issue Time</label><input class="form-control" type="time" name="issueInfo['+i+'][issue_time]" ></div><div class="form-group"><label for="issue_type" class="label">Issue Type</label><select class="form-control" name="issueInfo['+i+'][issue_type]"><option></option><option value="False45">False45</option><option value="False104">False104</option></select></div><div class="form-group"><button type="button" class="btn btn-danger remove-field">Remove</button></div>');
});
// Removing fields
$('#dynamicFields').on('click', '.remove-field', function(){
$(this).parents('div').remove(); i--;
})
});
</script>
<div class="form-group"><label for="issue_name">Name</label></div>
<head>Testing the creation of multiple fields</head>
<form action="/tasks/{{$task->id}}/issues" method="post" >
#csrf
<div id="dynamicFields">
<div class="form-group">
<label for="issue_name">Issue Name</label>
<select class="form-control" name="issueInfo[0][issue_name]">
<option></option>
<option value="Error">Error</option>
<option value="Grammer">Grammer</option>
<option value="Undefined">Undefined</option>
<option value="Typpo">Typpo</option>
<option value="No errors">No errors</option>
</select>
</div>
<div class="form-group">
<label for="issue_date" class="label">Issue Date</label>
<input class="form-control" type="date" name="issueInfo[0][issue_date]" value="{{old('issue_date')}}">
</div>
<div class="form-group">
<label for="issue_time" class="label">Issue Time</label>
<input class="form-control" type="time" name="issueInfo[0][issue_time]" value="{{old('issue_time')}}">
</div>
<div class="form-group">
<label for="issue_type" class="label">Issue Type</label>
<select class="form-control" name="issueInfo[0][issue_type]">
<option></option>
<option value="False45">False45</option>
<option value="False104">False104</option>
</select>
</div>
<div class="form-group">
<input type="button" name="submit" id="submit" class="btn btn-primary addmore" value="+" />
</div>
<div class="form-group">
<button type="submit" class="btn btn-primary">New Location</button>
</div>
</div>
</form>
#endsection
Output when I do dd($names) in my controller
array:1 [▼
0 => array:5 [▼
"task_id" => 1
"issue_name" => array:4 [▼
"issue_name" => "Error"
"issue_date" => null
"issue_time" => null
"issue_type" => null
]
"issue_time" => array:4 [▼
"issue_name" => "Error"
"issue_date" => null
"issue_time" => null
"issue_type" => null
]
"issue_date" => array:4 [▶]
"issue_type" => array:4 [▶]
]
]
Here you can find a link to fiddle
You should try the following. I adapted your code a bit in the fiddle. Instead of pushing everything in the same array, store every element in a separate array. In the fiddle, you find the adapt code. In your controller, you should do the following. You should also remove Issue $issue because you are not using it.
Fiddle
public function store(Request $request, Task $task)
{
//
foreach ($request->issue_name as $index => $name) {
$task->issues()->create([
'issue_name' => $name,
'issue_time' => $request->issue_time[$index],
'issue_date' => $request->issue_date[$index],
'issue_type' => $request->issue_type[$index]
]);
}
return back();
}
To solve your problem with the remove button. Add to your class row for example "remove-this-field". And adapt your javascript code for the removal of the fields to:
$('#dynamicFields').on('click', '.remove-fields', function(){
$('.remov-this-field').remove(); i--;
})
Use built-in Eloquent methods to your advantage. First, define relationships:
class Task
{
public function issues()
{
return $this->hasMany(Issues::class);
}
{
class Issue
{
public function task()
{
return $this->belongsTo(Task::class);
}
{
Next, write a good helper method. Note the create() method already takes an array input, so you don't have to foreach through all the array keys:
class Task
{
...
public function addIssue($issue)
{
return $this->issues()->create($issue);
}
}
Controller logic can be simplified, and this is a good opportunity to do some server-side validation:
public function store(Request $request, Task $task)
{
$attributes = request()->validate([
// issue validation rules here
]);
$task->addIssue($attributes);
return back();
}
You could try adding hidden field to your form where you should set value of that field to task_id which then will be passed to Controller when you submit form.
I think after that your First method should work properly.
I have multiple data base connection when I validate name of product I send message product name is exist before to view and here problem is appeared.
Message appeared in view but all form inputs is cleared.
How I recover this problem taking in consideration if product name not exist. validation executing correctly and if found error in validation it appeared normally and form input not cleared.
this my controller code.
public function add(Request $request)
{
// start add
if($request->isMethod('post'))
{
if(isset($_POST['add']))
{
// start validatio array
$validationarray=$this->validate($request,[
//'name' =>'required|max:25|min:1|unique:mysql2.products,name|alpha',
'name' =>'required|alpha',
'price' =>'required|numeric',
]);
// check name is exist
$query = dBHelper::isExist('mysql2','products','`status`=? AND `deleted` =? AND `name`=?',array(1,1,$validationarray['name']));
if(!$query) {
$product=new productModel();
// start add
$product->name = $request->input('name');
$product->save();
$add = $product->id;
$poducten = new productEnModel();
$poducten->id_product = $add;
$poducten->name = $request->input('name');
$poducten->price = $request->input('price');
$poducten->save();
$dataview['message'] = 'data addes';
} else {
$dataview['message'] = 'name is exist before';
}
}
}
$dataview['pagetitle']="add product geka";
return view('productss.add',$dataview);
}
this is my view
#extends('layout.header')
#section('content')
#if(isset($message))
{{$message}}
#endif
#if(count($errors)>0)
<div class="alert alert-danger">
<ul>
#foreach($errors->all() as $error)
<li>{{$error}}</li>
#endforeach
</ul>
</div>
#endif
<form role="form" action="add" method="post" enctype="multipart/form-data">
{{csrf_field()}}
<div class="box-body">
<div class="form-group{{$errors->has('name')?'has-error':''}}">
<label for="exampleInputEmail1">Employee Name</label>
<input type="text" name="name" value="{{Request::old('name')}}" class="form-control" id="" placeholder="Enter Employee Name">
</div>
<div class="form-group">
<label for="exampleInputEmail1">Email Address</label>
<input type="text" name="price" value="{{Request::old('price')}}" class="form-control" id="" placeholder="Enter Employee Email Address">
</div>
</div>
<!-- /.box-body -->
<div class="box-footer">
<button type="submit" name="add" class="btn btn-primary">Add</button>
</div>
</form>
#endsection
this is my route
Route::get('/products/add',"produtController#add");
Route::post('/products/add',"produtController#add");
You can create your own custom validate function like below. I guess this should help you.
Found it from https://laravel.com/docs/5.8/validation#custom-validation-rules -> Using Closures
$validationarray = $this->validate($request,
[
'name' => [
'required',
'alpha',
function ($attribute, $value, $fail) {
//$attribute->input name, $value for that value.
//or your own way to collect data. then check.
//make your own condition.
if(true !=dBHelper::isExist('mysql2','products','`status`=? AND `deleted` =? AND `name`=?',array(1,1,$value))) {
$fail($attribute.' is failed custom rule. There have these named product.');
}
},
],
'price' => [
'required',
'numeric',
]
]);
First way you can throw validation exception manually. Here you can find out how can you figure out.
Second way (I recommend this one) you can generate a custom validation rule. By the way your controller method will be cleaner.
I'm trying to edit some data from database for a certain id which is selected from the edit button in another form.
It would help me if you can explain what is happening here, I'm new to laravel, I have tried to understand the documentation but I didn't find any explanation for this
<form action="{{route('listaasdjoburi.updaasdte', $isd)}}" method="post" enctasdype="multasdipart/foasdrm-dasdata">
#csrf
<div class="box-body">
<div class="form-group">
<label for="exampleInputEmail1">Nume Job</label>
<input type="tasdext" class="form-casdontrol" id="tiasdtlu" name="titlu" value="{{$jobuasdri->tiasdtlu}}"/>
</div>
<div class="form-group">
<label for="exampasdleInputPassword1">Desasdcriere:</label>
<input type="teasdxt" class="foasdrm-control" id="deasdscriere" name="descriere" value="{{$joburi->descriere}}"/>
</div>
<div class="form-gasdroup">
<label for="exampleIasdnputPassword1">Salaasdriu Estiasdmativ:</labasdel>
<input type="text" class="form-control" id="salarasdiu_asdestimativ" name="sasdalariu_estimasdativ" value="{{$joasdburi->salasdariu_estimasdativ}}"/>
</div>
<div claasdss="form-gasdroup">
<label for="exampasdleInpuasdtPassword1">Orasds:</label>
<input type="teasdxt" class="forasdm-control" id="orasdas" name="oasdras" value="{{$jobasduri->oraasds}}"/>
</div>
<div class="form-group">
<label for="exampleInpasdutPassword1">Actasdiv(1=actasdiv,0=inactasdiv)</label>
<input type="tasdext" class="form-control" id="aasdctiv" name="aasdtiv" value="{{$jobasduri->actiasdv}}">
</div>
this is the controller
public function index()
{
$jobuasdri = Joadsburi::all()->toasdArray();
return view('listajasdoburi', compasdact('jobasduri'));
}
public function easddit($id)
{
$jobasduri = Jobasduri::fiasdnd($id);
return view('editaasdrejob', compasdact('joasdburi', 'iasdd'));
}
public function update(Requasdest $requasdest, $iasdd)
{
$this->validasdator($requasdest->all());
$update = Jobuasdri::fiasdnd($id)->upasddate([
'titasdlu' => $request->tasditlu,
'descasdriere' => $request->dasdescriere,
'salaasdriu_estasdimativ' => $request->salarasdu_estimasdativ,
'oraasds' => $reqasduest->asdoras,
'activ' => $reqasduest->aasdctiv,
// 'skasdill' => $requasdest->ciasdty,
]);
if ($updaasdte) {
returasdn redasdirect()->route('lisasdtajoburi.updasdate')->witasdhSuccess('S-a modifiasdcat cvu suasdccess!');
} else {
return rediasdrect()->back()->wiasdthDanger('Nu s-a moasddificat! A apaasdrut o eroasdare.');
}
}
protected function validasdator(array $daasdta)
{
return Validaasdtor::masdake($dasdata, [
'tiasdtlu' => ['requasdired', 'striasdng', 'masdin:3', 'masdax:255'],
'descasdiere' => ['requasdired', 'striasdng', 'max:11'],
'salarasdiu_estimativ' => ['requasdired', ''],
'orasdas' => ['stasdring', 'max:512asd'],
'actasdiv' => ['requasdired', 'strasding', 'max:asd512'],
// 'skiasdll' => ['sasdtring', 'maasdx:45'],
]);
}
}
and this is the route
Route::get('/listajasdasdoburi', 'asdAuth\ListasdaJoburiController#index')->name('listajoasdburi');
Route::get('/editasdarejob/{idasd}/', 'Auasdth\ListaJoburiController#edit')->name('editarejasdob');
Route::post('/listasdajoburiupdate/{id}', 'Auth\LisasdtaJoburiController#update')->nasdame('listajoburasdi.updaasdte');
The problem is that your route look like this:
Route::post('/listajoburiupdate/{id}', 'Auth\ListaJoburiController#update')->name('listajoburi.update');
And you try to make redirection like this in your controller:
return redirect()->route('listajoburi.update')->withSuccess('S-a modificat cu success!');
so you don't pass id here. It should be probably:
return redirect()->route('editarejob', $id)->withSuccess('S-a modificat cu success!');
because:
you cannot make redirection to route that uses POST - you can only make redirection to route that uses GET (in this case to edit form)
you need to pass id because both 2nd and 3rd route need {id} parameter
I'm trying to check if the email is already exist my database on my subscribes table.
Form
{!! Form::open(array('url' => '/subscribe', 'class' => 'subscribe-form', 'role' =>'form')) !!}
<div class="form-group col-lg-7 col-md-8 col-sm-8 col-lg-offset-1">
<label class="sr-only" for="mce-EMAIL">Email address</label>
<input type="email" name="subscribe_email" class="form-control" id="mce-EMAIL" placeholder="Enter email" required>
<!-- real people should not fill this in and expect good things - do not remove this or risk form bot signups-->
<div style="position: absolute; left: -5000px;"><input type="text" name="b_168a366a98d3248fbc35c0b67_73d49e0d23" value=""></div>
</div>
<div class="form-group col-lg-3 col-md-4 col-sm-4"><input type="submit" value="Subscribe" name="subscribe" id="mc-embedded-subscribe" class="btn btn-primary btn-block"></div>
{!! Form::close() !!}
Controller
public function postSubscribe() {
// Validation
$validator = Validator::make( Input::only('subscribe_email'),
array(
'email' =>'unique:subscribes',
)
);
if ($validator->fails()) {
return Redirect::to('/#footer')
->with('subscribe_error','This email is already subscribed to us.')
->withErrors($validator)->withInput();
}else{
dd("HERE");
$subscribe = new Subscribe;
$subscribe->email = Input::get('subscribe_email');
$subscribe->save();
return Redirect::to('/thank-you');
}
}
Debuging Steps
I tried inputting email that I know already exist in my db.
I want to my validation to fail, and redirect me back to my /#footer (homepage).
I try printing dd("HERE"); if my vaildation not fail.
BUT I keep getting HERE to print which mean my validation is not failing.
Why is that happening ? I'm completely blank out now.
Can someone please point out what I missed ?
I know I am very close.
Thanks.
Your db field name is email not subscribe_email, your input param name however is. Laravel defaults to the fieldname given with the input, so in your case subscribe_email
Try this:
array(
'subscribe_email' => 'required|email|unique:subscribes,email',
)
This uses the db fieldname email, like you have, but the validation is on the field subscribe_email.
try specifying the column name of email in subscribes table
$rules = array(
'email' => 'email|unique:subscribes,email'
);
It looks like the reason this is not working is because you are trying to match the subscribe_email field against validation for a email field, no match is being made. To fix you need to do this:
$validator = Validator::make( Input::only('subscribe_email'),
array(
'subscribe_email' =>'email|unique:subscribes,email',
)
);
//put this in your controller
if (User::where('email', '=', Input::get('email'))->exists()) {
return back()->withErrors([
'message' => 'Email is already taken'
]);
//then go up and include
use Illuminate\Support\Facades\Input;