I have a foreach loop that has a checkbox in it. I am not sure how to properly get that from the checkbox in the form over to the validation in the controller. I have the following in my view:
<table class="table">
<thead>
<tr>
<th scope="col">Select</th>
</tr>
</thead>
<tbody>
#foreach($plans as $plan)
<tr>
<td>
<input type='checkbox' name='Plan {{$plan->{'Plan ID'} }}' class='form-check-input' value='true'
#if(old($plan->{'Plan ID'},$plan->{'Plan ID'})=="true") checked #endif>
</td>
<td> {{$plan->{'Plan ID'} }}</td>
#endforeach
</tr>
</tbody>
</table>
I have the following in my controller:
$data = request()->validate ([
'current' => '',
'instructions' => '',
'Plan 1' => '',
'Plan 2' => '',
'Plan 3' => '',
'Plan 4' => '',
'Plan 5' => '',
'Plan 6' => '',
'Plan 7' => '',
'Plan 8' => '',
'Plan 9' => '',
'Plan 10' => '',
'Plan 11' => '',
'Plan 12' => '',
'Plan 13' => '',
'Plan 14' => '',
'Plan 15' => '',
]);
$plansubmission = PlanSubmission::find($id);
//$plansubmission->update($data);
$designs = MedicalDesignsToQuote::find($id);
if($designs==null){
$design = MedicalDesignsToQuote::create(['id'=>$id]);
$design->update($data);
}
else{
$designs->update($data);
I do not want to use an array for the 'name' attribute
Added this to controller:
$validator = Validator::make($request->all(), [
"list.*.id" => '', // Object exist validation
"list.*.value" => '',
'current' => '',
'instructions' => '',
]);
$bodyContent = $request->getContent($validator);
$plansubmission = PlanSubmission::find($id);
// $plansubmission->update($data);
$designs = MedicalDesignsToQuote::find($id);
if($designs==null){
$design = MedicalDesignsToQuote::create(['id'=>$id]);
// $design->update($data);
$design->update($validator);
}
else{
$designs->update($validator);
}
I have the following columns in my table:
id
current
instructions
Plan 1
Plan 2
Plan 3
Plan 4
Plan 5
.....
Plan 50
The user can select any or all of the 50 plan options with a checkbox. If, for example, Plan 5 is selected, the value for this given row within the table will be 'True' for plan 5.
So, to persist the data, I would expect I need to do something like this:
$formData = $request->all();
foreach ($formData['list'] as $planData) {
MedicalPlanDesignToQuote::updateOrCreate(
[$planData['id']] => $planData['value']],
);
}
If I had two columns called id and value, I suppose I could do this:
foreach ($formData['list'] as $planData) {
MedicalPlanDesignToQuote::updateOrCreate(
['id' => $planData['id']],
['value' => $planData['value']]
);
}
Is there anyway I can do this with my table structure?
First things first:
You have an error in your example. The #endforeach needs to be moved one column down.
Second:
You need to understand, what you are exactly doing here. You deal with an 1-n relationship between some kind of list and the list items. Ergo, you need to build your post/get body accordingly.
An example for a single table row could be:
<tr>
<td>
<Input type="hidden" value="{{$plan->{'Plan ID'} }}" name="list[][id]">
<Input type="checkbox" value="true" name="list[][value]">
</td>
<td>
{{$plan->{'Plan ID'} }}
</td>
</tr>
Now you are able to iterate over items accordingly, independent from their id.
Now you are able to use request validation as stated here: https://laravel.com/docs/master/validation#validating-arrays
In our case:
"list.*.id" => "...", // Object exist validation
"list.*.value" => "..."
Now how to pass everything to objects and persist them:
You need to be aware, you can't just pass anything into your objects. Right now you pass a validator. Instead use the validation only vor validation. Laravel will take care of returning a response.
$this->validate($request, [
'current' => required'',
'instructions' => 'required',
"list.*.id" => "required", // Object exist validation
"list.*.value" => "required"
]);
Afterwards you get your data from your request object:
$formData = $request->all();
We stored our information in the key 'list' (see html). So you will find it in your request object. There are multiple "plans" stored in our list. Now you need to iterate:
foreach ($formData['list'] as $planData) {
Plan::updateOrCreate(
['id' => $planData['id']],
['value' => $planData['value']]
);
}
Of course you need to also save other objects/create relationships if there are any.
If you want to stay with your table structure (you may should rework it: keyword BCNF), you are still able/need to iterate:
$dataArray = [];
foreach ($formData['list'] as $planData) {
$dataArray['Plan ' . $planData['id']] = $planData['value'];
}
$dataArray['current'] = $formData['current'];
$dataArray['instructions'] = $formData['instructions'];
// This way do not need to use create
$designs = MedicalDesignsToQuote::updateOrCreate(
['id' => $id],
$dataArray
);
You need to create an Option Group and Option tables to handle all your lists.
For example, you need a Location List and a Restaurant List.
Add a parent of Location List in Option Group and the child in Option and join them in Option.php to handle all your list in the future.
public static function getOfficeLocationList(){
return Option::where('group_id', config('constants.OPT_GROUP_OFFICE_LOC'))->orderBy('name','ASC')->get();
}
In my example, group_id is the ID of the parent list, in that way you can get all the location option you stored.
In your controller:
$locationList = Option::getOfficeLocationList();
In your blade:
#foreach($locationList as $item)
your input checkbox with $item->name and $item->id
#endforeach
That's it: Throw the formData in your validation :)
Related
I have 3 tables (2 + pivot) :
categories
id
admin_id
created_at
updated_at
deleted_at
langs
id
langname_fr
langname
....
lang_sector
lang_id
sector_id
sectname
sectshortname
....
I created a form which allow to create several entries depending the number of languages i defined ...
{!! Form::open( array('route' => 'maps.store','method' => 'POST') ) !!}
<fieldset>
<legend>Nom du secteur</legend>
#foreach($langs as $lang)
<div class="form-group m-form__group">
{{ Form::label( 'Nom du secteur en ' . $lang->langname_fr) }}
{{ Form::text('sectname_lang_' . $lang->id, '' , [ 'class' => 'form-control m-input' ]) }}
</div>
<div class="form-group m-form__group">
{{ Form::label( 'Nom abrégé du secteur en ' . $lang->langname_fr ) }}
{{ Form::text('sectshortname_lang_' . $lang->id, '', [ 'class' => 'form-control m-input' ]) }}
</div>
#endforeach
</fieldset>
...
{!! Form::close() !!}
If i want to create an entry in my database, i have to create several entries ...
public function sectorCreate(Request $request) {
Sector::create(array(
'admin_id' => Auth::guard('admin')->user()->id,
'created_at' => Carbon::now(),
'updated_at' => Carbon::now(),
));
$sector = Sector::all()->last();
$sector_id = Sector::all()->last()->id;
$countLang = Lang::count();
for ($i = 1; $i <= $countLang; $i++) {
$insertSector[$i] = $sector->langs()->attach(
$sector_id,
[
'lang_id' => $i,
'sectname' => $request->input('sectname_lang_' .$i),
'sectname_slug' => Str::slug($request->input('sectname_lang_' .$i)),
'sectshortname' => $request->input('sectshortname_lang_' .$i),
'sectdescription' => $request->input('sectdescription_lang_' .$i),
'sectshortdescription' => $request->input('sectshortdescription_lang_' .$i),
'created_at' => Carbon::now(),
'updated_at' => Carbon::now(),
'deleted_at' => NULL
]
);
}
return redirect()->route('admin.home')->with('success', 'Secteur créé');
}
Now my issue is to know how i can update the values of the database and to delete the entry ... I tried to read the documentation but i'm not sure i understood it.
For example
lang_id sector_id sectname sectshortname
-------------------------------------------------------
1 1 longname1 shortname1
2 1 longname2 shortname2
After update i would like to update sectname and sectshortname ... I have made several trials using sync, syncWithoutDetaching and updateExistingPivot without success...
I also add constraints by considering lang_id and sector_id as a primary key ...
UPDATE ----------------------------------------------------------
I modified the update method using sync and syncWithoutDetaching
public function update(Request $request, $id)
{
$sector = Sector::findOrFail($id);
$countLang = Lang::count();
$langs = Lang::all();
foreach ($langs as $lang) {
$lang_id = $lang->id;
}
for ($i = 1; $i <= $countLang; $i++) {
$insertSector[$i] = $sector->langs()->sync(
$sector->id,
$lang_id,
[
'sectname' => $request->input('sectname_lang_' .$i),
'sectname_slug' => Str::slug($request->input('sectname_lang_' .$i)),
'sectshortname' => $request->input('sectshortname_lang_' .$i),
'sectdescription' => $request->input('sectdescription_lang_' .$i),
'sectshortdescription' => $request->input('sectshortdescription_lang_' .$i),
'updated_at' => Carbon::now(),
'deleted_at' => NULL
]
);
}
return $insertSector;
//return redirect()->route('maps.index')->with('success', 'updated');
}
The Documentation states the following:
When attaching a relationship to a model, you may also pass an array of additional data to be inserted into the intermediate table:
$user->roles()->attach($roleId, ['expires' => $expires]);
You got this part correct. Now for updating (and or deleting):
Deleting
$user->roles()->detach([1, 2, 3]);
This removes associated records and clears the intermediate table.
Syncing Associations
You may also use the sync method to construct many-to-many associations. The sync method accepts an array of IDs to place on the intermediate table. Any IDs that are not in the given array will be removed from the intermediate table. So, after this operation is complete, only the IDs in the given array will exist in the intermediate table:
$user->roles()->sync([1, 2, 3]);
You may also pass additional intermediate table values with the IDs:
$user->roles()->sync([1 => ['expires' => true], 2, 3]);
If you do not want to detach existing IDs, you may use the syncWithoutDetaching method:
$user->roles()->syncWithoutDetaching([1, 2, 3]);
Conclusion
Use sync, and set the attributes again. If you just want to update a few records, use the syncWithoutDetaching.
Update
Change your update code to this:
$insertSector[$i] = $sector->langs()->sync(
$lang_id =>
[
'sectname' => $request->input('sectname_lang_' .$i),
'sectname_slug' => Str::slug($request->input('sectname_lang_' .$i)),
'sectshortname' => $request->input('sectshortname_lang_' .$i),
'sectdescription' => $request->input('sectdescription_lang_' .$i),
'sectshortdescription' => $request->input('sectshortdescription_lang_' .$i),
'updated_at' => Carbon::now(),
'deleted_at' => NULL
]
);
You passed both the sector->id and the $lang_id where you only needed to pass the $lang_id with attributes for the intermediate table.
Finally thanks to Douwe de Haan i finally solved my issue for creating an entry with pivot table ... i guess i understood a little bit how it work now
Here is the method :
public function store(Request $request)
{
Sector::create(array(
'admin_id' => Auth::guard('admin')->user()->id,
'created_at' => Carbon::now(),
'updated_at' => Carbon::now(),
));
$sector = Sector::all()->last();
$countLang = Lang::count();
$langs = Lang::all();
foreach ($langs as $lang) {
$lang_id[] = $lang->id;
}
for ($i=0 ; $i < $countLang; $i++) {
$insertSector[$i] = $sector->langs()->syncWithoutDetaching(
[$lang_id[$i] =>
[
'sectname' => $request->input('sectname_lang_' .$lang_id[$i]),
'sectname_slug' => Str::slug($request->input('sectname_lang_' .$lang_id[$i])),
'sectshortname' => $request->input('sectshortname_lang_' .$lang_id[$i]),
'sectdescription' => $request->input('sectdescription_lang_' .$lang_id[$i]),
'sectshortdescription' => $request->input('sectshortdescription_lang_' .$lang_id[$i]),
'created_at' => Carbon::now(),
'updated_at' => Carbon::now(),
'deleted_at' => NULL
]
]
);
}
return redirect()->route('maps.index')->with('success', 'Secteur créé');
}
For updating :
public function update(Request $request, $id)
{
$sector = Sector::findOrFail($id);
$countLang = Lang::count();
$langs = Lang::all();
foreach ($langs as $lang) {
$lang_id[] = $lang->id;
}
for ($i=0 ; $i < $countLang; $i++) {
$insertSector[$i] = $sector->langs()->updateExistingPivot(
$lang_id[$i],
[
'sector_id' => $request->input('sector_id'),
'sectname' => $request->input('sectname_lang_' .$lang_id[$i]),
'sectname_slug' => Str::slug($request->input('sectname_lang_' .$lang_id[$i])),
'sectshortname' => $request->input('sectshortname_lang_' .$lang_id[$i]),
'sectdescription' => $request->input('sectdescription_lang_' .$lang_id[$i]),
'sectshortdescription' => $request->input('sectshortdescription_lang_' .$lang_id[$i]),
'updated_at' => Carbon::now(),
'deleted_at' => NULL
]
);
}
return $insertSector;
//return redirect()->route('sectors.index')->with('success', 'Secteur mis à jour');
}
i already tried different ways and some post here
the 1st data is working savings to acadans_tbl but the update who's user login is not working.
view_file
<td><input type="text" name="assessval" id="assessval" value="1"></td>
Controller
$data1 = array(
'Studnum' => $this->session->userdata['snum'],
'Department' => $this->session->userdata['dept'],
'Course' => $this->session->userdata['course'],
'answer1' => $this->input->post('answer1'),
'answer2' => $this->input->post('answer2'),
'answer3' => $this->input->post('answer3'),
'answer4' => $this->input->post('answer4'),
'answer5' => $this->input->post('answer5'),
'answer6' => $this->input->post('answer6'),
'answer7' => $this->input->post('answer7'),
'answer8' => $this->input->post('answer8'),
'answer9' => $this->input->post('answer9'),
'answer10' => $this->input->post('answer10')
);
$data2 = array(
'assessval' => $this->input->post('assessval')
);
if ($this->Questions_model->create_ans($data1, $data2)) {
MODEL
public function create_ans($data1, $data2) {
$this->db->insert('acadans_tbl', $data1);
$data2['assesed'] = $this->db->insert_id();
$this->db->insert('users', $data2);
}
In your Controller, you write:
$data2 = array(
'assessval' => $this->input->post('assessval')
);
Its mean that you will insert the value from $this->input->post('assessval') to field assessval in the database. So, you have to ensure in the users table you have assessval field.
And in your model, just insert to the database:
$this->db->insert('users', $data2);
public function index1()
{
$g = Request::Input('grade');
$s = Request::Input('subject');
if(strcmp($g,'Select A Grade')==0 || strcmp($s,'Select A Subject')==0) {
if (strcmp($s, 'Select A Subject') == 0) {
// Session::flash('msg', 'Please select the Subject.');
return redirect()->back()->withInput();
} else if (strcmp($g, 'Select A Grade') == 0) {
// Session::flash('msg', 'Please select the Grade.');
return redirect()->back()->withInput();
}
}
else{
$u = DB::table('upldtbls')->where('grade',$g)->where('subject',$s)->get();
return view('2Eng',compact('u'));
}
}
Above is the controller method. Main else part executed correctly. But main if part not executed as I wanted. In main if condition I want to stay on the same page if drop box values are equal to that which means when they haven't select an option from drop box. Can any one figure out this mess?
{!! Form::select('Select A Grade', array('' => 'Select A Grade','2' => '2', '3' => '3','4' => '4'), 'Select A Grade', ['class' => 'form-control'])
{!! Form::select('Select A Subject', array('' => 'Select A Subject','English' => 'English', 'Mathematics' => 'Mathematics','Environmental Studies' => 'Environmental Studies'), 'Select A Subject', ['class' => 'form-control']) !!}
The if part is probably not being executed because the condition is not being met. Check that $g or $s is equal to 0 as per you check. If you are simply trying to see if these Input parameters are empty / blank, amend your if statement to:
if(!$g || !$s){
...
}
Also, you should really use Request::Input instead of $_GET, but you need to fix it to one of the below:
# Laravel 5.1.x or earlier
$g = Request::Input('grade');
$s = Request::Input('subject');
or
# Laravel 5.2.x or later
$g = $request->input('grade');
$s = $request->input('subject');
UPDATE
The issue is with your select boxes. You have incorrectly named them, and you would have noticed this if you carried out some basic debugging. Update them as follows:
{!! Form::select('grade', array('' => 'Select A Grade','2' => '2', '3' => '3','4' => '4'), null, ['class' => 'form-control'])
{!! Form::select('subject', array('' => 'Select A Subject','English' => 'English', 'Mathematics' => 'Mathematics','Environmental Studies' => 'Environmental Studies'), null, ['class' => 'form-control']) !!}
i.e. the first parameter should be the name of the field, which gets passed to $_GET. After updating the form, please update the if statement to my suggestion above.
I am sending multiple arrays via AJAX to my controller and I'm having trouble with validation.
I have 2 text inputs. Now, the issue is that at times both these inputs are present, but at other times only one might be present.
<input type="text" name="typeDetails[games]" class="form-control input-global"/>
<input type="text" name="typeDetails[art]" class="form-control input-global"/>
My JS is like this.
var data = { 'typeDetails[games]' : [], 'typeDetails[art]' : [] };
$("input[name='typeDetails[games]']").each(function() {
data['typeDetails[games]'].push($(this).val());
});
$("input[name='typeDetails[art]']").each(function() {
data['typeDetails[art]'].push($(this).val());
});
In my controller, I want to (1) make sure that there's a validation of required and (2) if the "games" array is present, perform a particular action and if the "art" array is present, perform a different action.
$typeDetails = Input::get('typeDetails');
if ($request->has('typeDetails.games'))
{
return 'games';
}
if ($request->has('typeDetails.art'))
{
return 'art';
}
What happens here is that in my console it properly returns 'games', but even if the "art" array has values and is sent with the request, it doesn't return 'art'. I must be missing a fundamental understanding with php here.
Thanks!
ANSWER
Here's how I got it to work.
$typeDetails = Input::get('typeDetails');
$this->validate($request, [
'typeDetails.*.*' => 'required|max:50'
],[
'required' => 'You must type in some keywords to continue.',
'max' => 'Your input must be less than 50 characters.'
]);
if ($request->has('typeDetails.games'))
{
$gameInfo = Input::get('typeDetails.games');
foreach ($gameInfo as $key => $value)
{
DB::table('user_type')->insert([
'user_id' => Auth::user()->id,
'type_id' => '1',
'user_type_details' => $value,
'created_at' => Carbon::now()
]);
}
}
if ($request->has('typeDetails.art'))
{
$artInfo = Input::get('typeDetails.art');
foreach ($artInfo as $key => $value)
{
DB::table('user_type')->insert([
'user_id' => Auth::user()->id,
'type_id' => '2',
'user_type_details' => $value,
'created_at' => Carbon::now()
]);
}
}
I have a ajax link in yii when user click it do something and update a element html (content of td) without refresh page how can change 2 element html?
I explain more:
in view i have a table by some td for show information a td for send information (there are a image ajaxlink) and a td by message of content (example: "not send")
When user click image link call a function and valid information (...) and change message of td ('validation is success').("not send" change to "validation is success")
I did what I was told but i want to remove ajaxlink and replace it by a simple image how
can I do it?
i add:
CHtml::image(Yii::app()->theme->baseUrl . "/img/gridview/email-send.png", '', array('title' => 'sended success'))
view.php:
<td id="send_<?php echo CHtml::encode($profileInformationServices->id); ?>"><?php echo "not send"; ?></td>
<td id="sended_<?php echo CHtml::encode($profileInformationServices->id); ?>">
<?php
echo $profileInformationServices->send ? CHtml::image(Yii::app()->theme->baseUrl . "/img/gridview/email-send.png", '', array( 'title' => 'sended success')):
CHtml::ajaxLink(CHtml::image(Yii::app()->theme->baseUrl . "/img/gridview/send.png", '', array(
'title' => 'Send for valid')), Yii::app()->createUrl('/profileInformationService/send'),
array( // ajaxOptions
'type' => 'POST',
'data' => array( 'id' => $profileInformationServices->id ),
'update' => '#send_'.$profileInformationServices->id,
)
);
?>
</td>
controller:
public function actionSend() {
if (Yii::app()->request->isPostRequest) {
$model = $this->loadModel($_POST["id"]);
$model->send = 1;
$model->save();
echo "sended success";
}
}
Use ajaxLink callback to change the text in td.
<?php
//I am keeping your ternary code in if-else condition for readability
if($profileInformationServices->send)
{
echo CHtml::image(Yii::app()->theme->baseUrl . "/img/gridview/email-send.png", '', array('title' => 'sended success'));
}
else
{
echo CHtml::ajaxLink
(
CHtml::image(Yii::app()->theme->baseUrl . "/img/gridview/send.png", '', array('title' => 'Send for valid')),
Yii::app()->createUrl('/profileInformationService/send'),
array
(
'type' => 'POST',
'data' => array('id' => $profileInformationServices->id),
'success'=>'function(data)
{
if(data=="sended success")
{
$("#send_'.$profileInformationServices->id.'").html("validation is success");
}
}',
)
);
}
?>