Laravel 5.5: Send value of hidden form input to controller - php

In my view, I'm getting all the available slots so a user can click the book button to book that slot. However, I just can't seem to find a way to get the correct value (id of the input) so I can set the status of the specific booking in the database to booked.
index.blade.php
#if(count($slots) > 0)
<table class="table table-striped">
<tr>
<th>Date</th>
<th>Time</th>
<th></th>
</tr>
#foreach($slots as $slot)
<tr>
<td>{{$slot->date}}</td>
<td>{{$slot->time}}</td>
<td>
<input name="id" value="{{$slot->id}}" type="hidden"> THIS IS WHAT I WANT TO SEND
<button class="btn btn-primary pull-right" type="submit">Book</button>
</td>
</tr>
#endforeach
BookingsController.php
public function store(Request $request)
{
$booking = new Booking;
$booking->user_id = auth()->user()->id;
$booking->date_id = THIS IS WHAT I NEED;
DB::table('calendar')
->select('id','status')
->where('id', GET DATE ID)
->update(['status' => 1]);
$booking->save();
return redirect('/bookings')->with([
'success' => 'Booking successful!',
]);
}

Use the request object to retrieve the parameters you send :
$whatYouNeed = $request->id (or in general $request->WhateverYouNamedYourField)
Edit : This is not related to hidden fields only, it works with any kind of form fields.

Request docs
In store function you are Typehinting Request.
store(Request $request)
The first Request is referring to the request handler.
So if you'll put this after your.
$booking->date_id = $request->input('id')
Thats your answer.
You are requesting the input id from the request input

from the docs
$request->all();
or
$request->get('filedName');
or
$request->fieldName;
or
$request->input('fieldName');
These are the ways of getting inputs including hidden ones

Related

Laravel Array to Input checkbox true or false value

Hi I have a row of data where I will like to allow the users to click on a checkbox on/off the data for use. I have read up on https://stackoverflow.com/a/43995087/14936674 answer and it is working fine, except that my checkbox value can only be update if it is checked. If I want to uncheck the box and update it, there will be no update done to it. Currently I have tested out just by updating the checkbox, however it will update and uncheck all of my data.
Below are my blade.php
<tbody>
#foreach($operatinghrs as $i => $operatinghr)
<tr id="{{ $operatinghr->{'opID'} }}">
<td>
<input type="hidden" name="operatinghrs[{{ $i }}][opID]" value="{{ $operatinghr->{'opID'} }}">{{ $operatinghr->{'day'} }}
</td>
<td>
<input type="time" id="start_time" name="operatinghrs[{{ $i }}][start_time]" min="00:00" max="23:59" value="{{ display24HTime(old('start_time', $operatinghr->start_time))}}">
</td>
<td>
<input type="time" id="end_time" name="operatinghrs[{{ $i }}][end_time]" min="00:00" max="23:59" value="{{ display24HTime(old('end_time', $operatinghr->end_time))}}">
</td>
<td>
<div class="switch">
<input type="checkbox" id="clinic_open" name="operatinghrs[{{ $i }}][clinic_open]" class="switch-input" value="1" {{ old('clinic_open', $operatinghr->clinic_open=="true") ? 'checked="checked"' : '' }}/>
<div class="circle"></div>
</div>
</td>
</tr>
#endforeach
</tbody>
Below are the codes in my controller class:
public function update(Request $request)
{
foreach($request->get('operatinghrs', []) as $operatinghr) {
$db = new OperatingHour();
$db->where('opID', $operatinghr['opID'])->where('clinic_id', '=', $_SESSION['clinic_ID'])
->update(
[
'clinic_open' => $request->input('clinic_open') ? true : false,
]
);
}
return back()->with('success_message', 'Details updated successfully!');
}
If you want to only update where $operatinghr['clinic_open'] value is true condition.
Consider this from MDN:
If a checkbox is unchecked when its form is submitted, there is no value submitted to the server to represent its unchecked state (e.g. value=unchecked); the value is not submitted to the server at all. If you wanted to submit a default value for the checkbox when it is unchecked, you could include an inside the form with the same name and value, generated by JavaScript perhaps.
Also you must access clinic_open value over $operatinghr as $operatinghr['clinic_open'] for specific entry. Not as $request->input('clinic_open')
So solution must like that:
// Get all Operating values.
$operatinghrs = $request->get('operatinghrs', []);
/*
* Filter values with clinic_open criteria.
* Checkbox values are only present when is checked.
* So isset control work for us.
*/
$operatingsForUpdate = array_filter($operatinghrs, function($op){
return isset($op['clinic_open']); // return only has clinic_open value.
});
// Loop for only for update operatings.
foreach($operatingsForUpdate as $operatinghr) {
// Update specific entry which contain clinic_open value is true.
}
Working with checkbox is always tricky, the default values of a checkbox are on and off, but if the checkbox is unchecked it won't appear in request data.
So you need to validate if the checkbox exists in request before try to update, and if not, save a string 'off' in the database or don't save anything and set a default value ('off') for that field, when you retrieve the data in the edit/update form, all the checkbox with 'off' value will be unchecked.
Using the has method on the $request, like this:
if($request->has('clinic_open')) {
foreach($request->get('operatinghrs', []) as $operatinghr) {
$db = new OperatingHour();
$db->where('opID', $operatinghr['opID'])->where('clinic_id', $_SESSION['clinic_ID'])
->update(['clinic_open' => $request->input('clinic_open')]);
}
}
Some advices:
Avoid using the '=' condition on where methods, laravel asummes it, save time and space.
Remove the value='1' of the checkbox, leave some work to the browser and do less.

How to have different view based on date in Laravel

I'm having a problem in having a different view by comparing today's date and expired date. Before I'm telling deeper about my problem, let me show you the code:
buyer table
id
name
address
phone_no
email
expired_at (date)
created_at
BuyerController.php
public function create(Request $request)
{
$buyers = Buyer::create([
'name' => $request->name,
'address' => $request->address,
'phone_no' => $request->phone_no,
'email' => $request->email,
'expired_at' => Carbon::today()->addDays(730),
]);
return response()->json($buyers);
}
buyers\index.blade.php
<div class="panel-body">
<table class="table table-hover" id="buyer-table">
<thead>
<tr>
<th>ID</th>
<th>Name</th>
<th>Address</th>
<th>Phone No</th>
<th>Email</th>
<th>Registered Date</th>
<th>Liability Period</th>
</tr>
</thead>
#foreach($buyers as $buyer)
<tr class="buyer{{$buyer->id}}">
<td>{{$buyer->buyer_id}}</td>
<td>{{$buyer->name}}</td>
<td>{{$buyer->address}}</td>
<td>{{$buyer->phone_no}}</td>
<td>{{$buyer->email}}</td>
<td>{{date('d/m/Y', strtotime($buyer->created_at))}}</td>
#if(now() < $buyer->expired_at)
<td class="text-success">Valid</td>
#else
<td class="text-danger">Expired</td>
#endif
</tr>
#endforeach
</table>
</div>
Until here, I manage to complete my code which I successfully compared the expired date and today's date in the table view.
web.php
Route::get('/report-form','ComplaintController#create');
ComplaintController.php
public function create()
{
return view('buyers.complaints.create');
}
However, before deciding to develop this new idea, buyer can just view the create.blade.php in order to make a new complaint. But now, if the expired_at is already passed today's date, buyer can not make any complaint which will return to view expired.blade.php.
buyers\complaints\create.blade.php
<div class="panel-heading">
<h3 class="panel-title"><strong>Make New Report</strong></h3>
</div>
//There is a form for the buyers to fill in the complaint
buyers\complaints\expired.blade.php
<div class="panel-heading">
<h3 class="panel-title"><strong>Sorry you can't make any report</strong></h3>
</div>
I only have an idea to make if else statement in function create() but I do not know what is the correct query. What I already tried:
public function create()
{
$expired = Buyer::select('id')->where('expired_at','>', now())->get();
$valid = Buyer::select('id')->where('expired_at','<', now())->get();
if ($expired) {
return view('buyers.complaints.create');
}
elseif ($valid) {
return view('buyers.complaints.expired');
}
}
I do not know what I'm trying to do because there is no difference. If the buyers liability period has end (expired date has passed today's date) also can view the buyers\complaints\create.blade.php and I'm still new in Laravel. So, I hope there is someone can help me in figuring this out. Thank you in advanced.
You only have 2 outcomes (unless a blank response was a 3rd) so one query to check the existence of a record should work:
if (Buyer::where('expired_at', '>=', now())->exists()) {
return view('buyers.complaints.create');
}
return view('buyers.complaints.expired');
This is assuming you are looking for any Buyer who still isn't expired.
If you want to restrict this to a certain buyer and pass the buyer to the view:
$buyer = Buyer::findOrFail($buyerId);
$view = ($buyer->expired_at >= now()) ? 'create' : 'expired';
return view('buyers.complaints.'. $view, ['buyer' => $buyer]);

Symfony3 change form field type in the controller

I have a form builder which builds a form
public function buildForm(FormBuilderInterface $builder, array $options)
{
$builder->
add('typeTask',TextType::class,array('label'=>"Вид заявка"))->
add('description',TextareaType::class,array('label'=>"Описание"))->
add('term',DateType::class, array(
'widget' => 'choice',
'label'=>"Краен срок"
))->
add('designer',TextareaType::class,array('label'=>"Дизайнер",
"required"=>false))->
add('executioner',TextareaType::class,array('label'=>"Под изпълнител",
"required"=>false))->
add("file",TextType::class,array('label'=>"Файл",
"required"=>false))->
add("ergent",CheckboxType::class,array('label'=>"Спешно",
"required"=>false))->add("approved",HiddenType::class,array(
"required"=>false
))->add("rejected",HiddenType::class,array(
'required'=>false
));
}
As you see I have 2 fields which are "approved" which can be true or false and rejected which can also be true and false. Usually they are hidden because only 1 type of user can access them - ROLE_ADMIN and the rest is for ROLE_EDITOR. In my case the ADMIN needs to only approve or reject it and the EDITOR can't do that. The biggest issue is that I don't need a whole form, but rather 2 buttons - "Approve" and "Reject" when the Project is shown ("show" action), but the action which changes the Project is "edit" and so what I tried so far is from "show" to send a form to "edit" and then when the edit action is over to load the "show" action again.I tried achieving this by creating 2 forms - approveForm and rejectForm which can hold only 1 property each and send and flush them to "edit" function, but the edit function doesn't accept the form and also if it did it would have deleted everything else. Here is my code so far
In show action -
$projectFormApprove = $this->createForm('AppBundle\Form\ProjectType', $project,array(
"method"=>"post"
));
$projectFormApprove->remove("description");
$projectFormApprove->remove("designer");
$projectFormApprove->remove("executioner");
$projectFormApprove->remove("term");
$projectFormApprove->remove("typeTask");
$projectFormApprove->remove("file");
$projectFormApprove->remove("ergent");
$projectFormApprove->remove("approved");
$projectFormApprove->remove("rejected");
$projectFormApprove->add("approved",HiddenType::class,array(
"data"=>true
));
$projectFormReject = $projectFormApprove;
$projectFormReject->remove("approved");
$projectFormReject->add("rejected",HiddenType::class,array(
'data'=>true
));
This will create 2 forms each having 1 property and here is what happens in my twig template
<tr>
<td>
{{ form_start(approveForm, {'action': path('project_edit', { 'id': project.id })}) }}
{{ form_widget(approveForm) }}
<input type="submit" value="Approve" />
{{ form_end(approveForm) }}
</td>
</tr>
<tr>
<td>
{{ form_start(rejectedForm,{'action': path('project_edit', { 'id': project.id })}) }}
{{ form_widget(rejectedForm) }}
<input type="submit" value="Reject" />
{{ form_end(rejectedForm) }}
</td>
</tr>
I need two forms since there are 2 buttons which simply submit them and no one actually changes the value ( this is the reason why in "show" function the created property have "data"=>true. If the form is submitted it will do it automatically.
Here is what is in my "edit" function -
/** #var $user User */
$user = $this->getUser();
$project = new Project();
$form = $this->createForm('AppBundle\Form\ProjectType', $project);
if($user->getType() != "LittleBoss"){
$form->remove("designer");
$form->remove("executioner");
}
$form->handleRequest($request);
if ($form->isSubmitted() && $form->isValid()) {
$project->setFromUser($user->getUsername());
$project->setDepartment($user->getDepartment());
$project->setIsOver(false);
$project->setDate(new \DateTime());
$project->setSeenByDesigner(false);
$project->setSeenByExecutioner(false);
$project->setSeenByLittleBoss(false);
$project->setSeenByManager(false);
$em = $this->getDoctrine()->getManager();
$em->persist($project);
$em->flush();
return $this->redirectToRoute('project_show', array('id' => $project->getId()));
}
return $this->render('project/new.html.twig', array(
'project' => $project,
'form' => $form->createView(),
));
Now to my actual problem - As you see I first remove "approved" field and then I add new one with predefined value. What I want is to change not the values, but the type of description and the rest fields. Is there a way to say $form->change(); or anything that can change the types of the fields without having to remove them. The type I want them to be is HiddenType and set their data so that when I submit one of the 2 forms it will be accepted as valid in the "edit" action then flushed to the database and everything will be fine. So far when one of the buttons - "Approve" or "Reject" is clicked in the "edit" action $edit_form->IsSubmited() returns false.
I suggest you to create seperate forms, one for editor and another for admin. Then in controller use the form you need by permissions of the logged in user.
if ($this->authorizationChecker->isGranted('ROLE_EDITOR')) {
$form = $this->createForm(EditorType::class);
} elseif ($this->authorizationChecker->isGranted('ROLE_ADMIN')) {
$form = $this->createForm(AdminType::class);
}
$form->handleRequest($request);
In both forms you can use same entity, but different fields.

Update a section of page from button click in table with laravel

I'm trying to figure out how to have a table where each row has data including a unique ID and an edit button. When the edit button is clicked I would like for another section of the page to show a form to edit the data on that line. So far I have something like:
//linePage.blade.php
<table>
#foreach($lineList as $line)
<tr>
<td>{{ $line->Name }}</td>
<td>Edit</td>
</tr>
#endforeach
</table>
#if (!empty($lineSelected))
{{-- show form --}}
#endif
//routes.php
Route::get('/LinePage/{lineSelected?}', 'Forms#linePage');
Route::post('/LinePage/{lineSelected?}', 'Forms#updateLinePage');
//Forms.php
public function linePage($lineSelected = NULL){
$data = array('lineSelected=>$lineSelected);
return View::make('Forms\linePage',$data);
}
public function updateLinePage($lineSelected = NULL){
$data = array('lineSelected=>$lineSelected);
return View::make('Forms\linePage',$data);
}
This is working for me but I feel like I'm making it more complicated than it needs to be. Am I going about this correctly? Also, I don't like how the address bar shows localhost/LinePage/LineName once the line is selected. Is it possible to somehow hide the data being passed within the page?
Thanks
a simpler method for this is to use Javascript (and/or) jQuery .
The basic idea is, when you click a button in the table, you will make an ajax request. In that ajax request, you have only the form for that particular lineName . In this way, the page will not be reloaded, and you won't get to change the URL, and it's more fast .
If you choose to do this with jQuery. You will have something like :
//linePage.blade.php
<table>
#foreach($lineList as $line)
<tr>
<td>{{ $line->Name }}</td>
<td>Edit</td>
</tr>
#endforeach
</table>
//in the footer somewhere, after you load query
<script>
$(function()
{
$('a.btn-line').click(function(event){
var id = event.target.id;
fieldName = id.split('-');
lineName = fieldName[1];
$.get(
"{{action('Forms#lineForm'}}?lineName="+lineName,
function(data){
$('div#line-form').html(data);
}
);
});
</script>
in your routes :
Route::get('/linePage/form/', 'Forms#lineFormPage');
and in your controller, you will return the view with only the form
Maybe this is not the easiest way to do, but you won't need to refresh every time you need to reload the form, + it keeps things more separated

Populate table in Laravel with ajax?

I have a Laravel application where I create a page layout, adding a table to it as a "content" variable (pretty much all from tutorials I found). Here's the controller action:
public function getMain() {
$js_config = Category::all();
$resources = Resource::all()->take(100);
$this->layout->content = View::make('categories.show')->with('js_config', $js_config)->with('resources', $resources);
}
This uses the main layout template and inserts this table using the content variable:
<table class="table table-striped table-bordered">
<thead>
<tr>
<td>ID</td>
<td>Name</td>
</tr>
</thead>
<tbody>
#foreach($resources as $key => $value)
<tr>
<td>{{ $value->id }}</td>
<td>{{ $value->title }}</td>
</tr>
#endforeach
</tbody>
</table>
But then comes the problem: I have a jstree where the user can select nodes, triggering a jQuery method:
$('#jstree2').on("changed.jstree", function (e, data) {
console.log(data.selected);
$.get("filter", { category: data.selected })
.done(function (resultdata) {
//Test only, this returns the data wanted in json, which I stringify just to display in test
alert("Data Loaded: " + JSON.stringify(resultdata));
});
});
The jQuery calls this action method in the controller:
public function getFilter()
{
$input = Input::get('category.0');
$categories = Category::find($input);
//category is the name from the model below
return Response::json(array(
'error' => false,
'category' => $categories->toArray()),
200
);
}
(The reason there's an array as input is I eventually want to be able to allow picking multiple nodes in the tree)
This action gets the data from the DB correctly and returns it as json. The callback in the jQuery above then alerts this at the moment, just as a test.
But what I really want to do, of course, is to repopulate the table. Now, as you can see I have used Bootstrap to create a pretty table and all, and I just want to be able to let the user repopulate it at will, without refreshing the page.
But I don't know how to do that, except by painstakingly recreate this table in some sort of string return value, but that doesn't seem like a good idea.
I'm hoping there's some way of passing the return value back to the view and have it reload the values in the table, utilizing the same "sub view" that I loaded in the php variable "content" as described above?
Any help greatly appreciated!
EDIT:
As requested, here's a sample of the json (taken from the browser console output, and it's actually not the categories table, but the same format):
[{"id":"1","title":"Transportation AC 4494","created_by":"4","modified_by":null},{"id":"2","title":"Safety First AC 4294","created_by":"3","modified_by":null},{"id":"3","title":"Warranty AC 34066","created_by":"4","modified_by":null}]
EDIT 2 (Just realized there was some crap from the controller in the previous edit of the json, so I changed it to a cleaner sample now)
EDIT 3:
I have made this work by creating the table rows in jQuery:
var trHTML = '';
$.each(resultdata, function (i, item) {
trHTML += '<tr><td>' + item.id + '</td><td>' + item.title + '</tr>';
});
$('#ajaxtable').html(trHTML);
But mainly I'm hoping this might explain my question better: this is not what I wanted to do. What I would have wanted was to just create a partial view and then load that ready-made view with the jquery:
A partial view like this:
<table class="table table-striped table-bordered" id="resultstable">
<thead>
<tr>
<td>ID</td>
<td>Name</td>
</tr>
</thead>
<tbody id="ajaxtable">
#foreach($resources as $key => $value)
<tr>
<td>{{ $value->id }}</td>
<td>{{ $value->title }}</td>
</tr>
#endforeach
</tbody>
</table>
I tested this by creating and calling a new function in the controller from the jquery code:
public function getTable()
{
$resources = Resource::all()->take(5);
return View::make('categories.results')->with('resources', $resources);
}
But it doesn't work. Although it does indeed give me the html of that view, it is unprocessed. I.e, the foreach loop is not resolved, but still there as code in the table. See the image:
So how can I load this view with the jquery code? It feels to me that even if the jquery creation of table rows works, doing the view in php and then just loading it with jquery should be the more correct way of doing it...?
Have you looked into the Datatables jQuery plugin? There is actually a nice package for Laravel that helps integrate Laravel and Datatables. The Laravel package generates the json and you can use Datables+AJAX to repopulate the data. Might be working checking out...
https://github.com/Chumper/datatable
http://datatables.net/
Otherwise, you'll just need to use AJAX to repopulate the table.
As Sirago answered, using jQuery Datatables is a good option to load data into tables in ajax manner.
In addition to what Sirago suggested, here is another great Laravel 4 package which is dedicated to generate JSON data from server side.
https://github.com/bllim/laravel4-datatables-package
But apart from server side configuration(modifying files like composer.json, config/app.php etc.), you need to code in Javascript, utilizing Datatables as well.

Categories