I'm building a request system with Laravel 7. In the index page, there is a form for user to fill in and a submit button. If the button is clicked, the data in the form will be sent to the supervisor via email. The email which the supervisor receives, all user input data will be listed along with a "Approve" button and a "Reject" button. If the "Approve" button is clicked, the user input data will be stored in the database. All user input data is stored in $data and can be accessed in email template view. So, in the email template, how do I pass the user input data and Auth::user()->id to the controller so that the storing process will start?
I read this post and it looks useful to me, but it is using <a> to do the redirection to trigger the controller. Is it possible to pass the blade variables from the <form> in the email template view to the controller, so that I can use <button>?
Update:
index.blade.php:
<form action="/sendSupervisor" method="post">
<input type="text">
<input type="text">
<button type="submit">Send</button>
</form>
web.php:
Route::post('/sendSupervisor', 'CatViewController#sendSupervisor')->middleware('auth')->middleware('verified');
CatViewController.php:
// one of the methods
public function sendSupervisor()
{
$data = request();
Mail::to('supervisor#abc.com')->send(new ApprovalMail($data));
return redirect('/');
}
approval.blade.php:
<!-- Email Template -->
User Input: {{ $data->name }}
<form action="/approve">
<button>Approve</button>
</form>
<form action="/reject">
<button>Reject</button>
</form>
An email is not a browser, and in almost every case a <form> tag will have no effect. You cannot retrieve user input from an email, however in your case if you have two buttons in the email, and that email is being sent to a user that exists in your system, AND the input you are receiving is 'accept' or 'reject' based on which button they click, this is doable.
You can have two routes that are publicly accessible and build two "buttons" with hrefs that will carry out those actions. Like:
Route::get('email/accept/{user_id}', 'EmailController#accept');
Route::get('email/reject/{user_id}', 'EmailController#reject');
Then link to those routes in your email temple like:
Accept
Reject
Then in that controller, you can resolve the user based on id in those methods, and you can carry out any logic you would like.
A note of caution: since these links need to be publicly accessible, using id's is not ideal. You should generate some sort of token to resolve the user.
A better approach:
It's better to save the user request once he post it with a column flag called "status" that holds either ("Pending", "Approved", "Rejected"), and then send an email to the supervisor
index.blade
<form action="/sendRequest" method="post">
<input type="text">
<input type="text">
<button type="submit">Send</button>
</form>
web.php
Route::get('/sendRequest', 'MyController#sendRequest)
MyController.php
public function sendRequest(Request $request){
// UserRequest table should has column 'status' with default value 'Pending'
$userRequest = UserRequest::create($request->all());
Mail::to('supervisor#abc.com')->send(new ApprovalMail($userRequest));
return redirect('/');
}
The email template should only notify the supervisor to take an action with the request, with a button 'Take action' that opens a page in the browser for him to take the action.
email-template.blade
<!-- User data displayed for example in a table -->
<a href={{ route('takeAction', $userRequest->id) }}>
<button> Take Action <button>
</a>
web.php
Route::get('/take-action/{requestId}', 'SupervisorController#takeAction')
->name('taleAction');
SupervisorController.php
public function takeAction($requestId){
$userRequest = UserRequest::find($requestId);
return view('take-action', [$userRequest]);
}
take-action.blade
<-- User data displayed for example in a table -->
<form method='POST' action={{ route('takeActionPost', $userRequest->id) }}>
#csrf
<input type='hidden' name='action' value='Approved'>
<button type='submit'>Approve</button>
</form>
<form method='POST' action={{ route('takeActionPost', $userRequest->id) }}>
#csrf
<input type='hidden' name='action' value='Rejected'>
<button type='submit'>Rejected</button>
</form>
web.php
Route::post('/take-action/{requestId}', 'SupervisorController#takeActionPost')
->name('takaActionPost');
SupervisorController.php
public function takeActionPost(Request $request, $requestId){
$userRequest = UserRequest::find($requestId);
$userRequest->update(['status', $request->action]);
}
Of course the names I'm using here are very bad, I just want to explain my idea
Add hidden input fields in the form whose values are the user data. But I think there is a better design for your system that I'll explain in a separate answer.
Related
So I tried to make a basic table with database integration, which worked flawlessly. Now I need to make a table that adds you the permission to edit the data you inserted into the form. But I need it to only give the person who made the form the permissions to edit it. Below I added my current progress without the permissions added. Currently I finished the Jetstream page with laravel, it has login and register so I'd want the username to be the authed person to edit the data. Is there any easy way to do it?
The controller I made:
`$rada= new Raja;
$rada->id=$req->id;
$rada->raja_nimi=$req->raja_nimi;
$rada->raja_asukoht=$req->raja_asukoht;
$rada->save();
return redirect('list');`
The view file:
<form action="add" method="POST">
#csrf
<input type="text" name="id" placeholder="Raja ID"> <br> <br>
<input type="text" name="raja_nimi" placeholder="Raja nimi"> <br> <br>
<input type="text" name="raja_asukoht" placeholder="Raja asukoht"> <br> <br>
<button type="submit">Lisa</button>
</form>
You'd need to store the id of the author in your controller, for example...
$rada= new Raja;
$rada->id=$req->id;
$rada->raja_nimi=$req->raja_nimi;
$rada->raja_asukoht=$req->raja_asukoht;
$rada->author_id = Auth::id();
$rada->save();
Then when you come to update the post in your controller you'd implement a check to make sure that the user owns the post...
$post = Raja::find($req->id);
if(Auth::id() == $post->author_id) {
//Update functionality here
} else {
//Redirect to 401 or send response message
}
A more Laravel appropriate way to perform a check when the user attempts to save a model would be to use a policy, you can find an example here
https://laravel.com/docs/8.x/authorization#policy-responses
I'm building an app with Laravel
In the same blade file I have different forms. In a div I have two forms.
In one form the user writes something in a textarea. After press the button ok, the page is reloaded and the data stored in a table of database.
The other form appears in a modal and it contains other option that the user can set and after press another button the data should stored in another table of database.
So how I can do this? I tried to route the function in my controller in this way:
Route::post('/anam','AnamnController#store');
Route::post('/anam','AnamnController#storePar');
and the tag form:
<form action="{{ action('AnamController#store') }}" method="post" class="form-horizontal">
<form id="formA" action="{{ action('AnamnesiController#storePar') }}" method="" class="form-horizontal">
But these return to me errors. So what I have to do?
Thanks!
it's impossible to use the same route for two different functions unless you change one by get instead of post for example:
Route::post('/anam','AnamnController#store');
Route::get('/anam','AnamnController#storePar');
but you can make this logic:
Route::post('/anam','AnamnController#store');
and the tag form:
<form action="{{ action('AnamController#store') }}" method="post" class="form-horizontal">
<input name="input_name" value="input-val" />
</form>
in controller:
public function store (){
if(request()->input_name == 'val-1')
this->store1();
else
this->store2();
}
protected function store1 () {
//
}
protected function store2 () {
//
}
You can't have two routes with the same url that has the same route method.
In your case you have two POST methods going to the same url. The second route definition is cancelling out the first.
Rename one of them.
I'm trying to return the value of a checkbox within my laravel controller, but every time I request a input from a checkbox element in a form, it returns null.
My controller, retrieving the input of a element called Filter-Method.
Here I'm trying to request a input method called filter-method which is a checkbox.
My Route, since this function will execute on a button:
My Blade, where I'm trying to retrieve the result of my filter-method checkbox:
On line 38 I have a checkbox called filter-method, and when you click on the button on line 115 it should send a request to the controller where it would return a result but instead it returns null
Any ideas of why I'm returning null?
You are not passing any parameter named filter-method. If you are posting values you should use post method.
Like following
Route::post('GetFilterByColumns','MentorController#FilterByValuesColoumns')
If you want to list data according to filter-method then try the following.
Route::get('GetFilterByColumns/{filter-method}','MentorController#FilterByValuesColoumns')
And in your mentorlist.blade.php page
change the href value according to route.
You have to add form to your blade around checkbox either with get or post method as per your requirement change route according to your form method
consider demo blade file
<form method="get" action="{{ url('GetFilterByColumns') }}" class="form-horizontal form-label-left" id="">
<div class="checkbox">
<label><input type="checkbox" name="filter-method" value="filter-method>Method</label>
</div>
<input type="submit" value="submit"/>
</form>
Now you will get a checkbox value in contoller
This is very basic thing just use form instead of <a> tag. Every time you need to send input value to server you need to use <form> element. In image you have uploaded there is no <form> and you are using a <a> tag.
You need to do it like this
<form method="get" action="/getFilterBycolumns">
<input type="checkbox" name="filter-method">
// other input fields
// and then a submit button instead of <a>
<button class="your-class" type="submit"> Send</button>
just use POST instead of GET if you are sending form values
In my blade I have field called $jobs. I am trying give every single form a unique url based on the $job->id. So the url is jobs/$job->id. However when I click on the a tag for to submit the form all the urls show jobs/the last $job->id. In my case all the urls show job/386. What should I so every url has a unique url? Here is my code.
#foreach($jobs as $job)
<form method="post" action="{{url('jobs/'. $job->id)}}" id="start-jobs">
{{csrf_field()}}
<a onclick="document.getElementById('start-jobs').submit()">( start )</a>
</form>
#endforeach
This is actually a JavaScript problem, not a Laravel problem.
All your forms have the same id (which isn't actually valid HTML), and which is why getElementById('start-jobs') is getting you the last one. If you need to have an identifier for all of the forms, use class instead of id.
It seems like you should be able to use just a regular submit button instead of the submit link you're using.
#foreach($jobs as $job)
<form method="post" action="{{url('jobs/'. $job->id)}}" class="start-jobs">
{{csrf_field()}}
<input type="submit" value="( start )">
</form>
#endforeach
This is my two routes which pass variable on each view.
Route::resource('product', 'ProductController');
Route::resource('booking', 'BookingController');
I created a view which display the current product (ex. http://localhost:8000/product/15) using the ProductController.
Now i created another view to book this product then insert it (modal pop up) inside the product view using #include('partials.booking').
The problem is how can i pass the product id to the BookingController? It is possible?
This depends a lot on what framework you use in your frontend ( jquery etc. )
Usually your popup should somehow know what product it is referred to. You can do this for example like this
<!-- this is your html / blade -->
<div class="booking-popup">
<button class="book" data-product="{{$product->id}}">Book Now!</button>
</div>
You can then use ajax and jquery for example to get the data attribute
Another option is to provide a form with a hidden field
<form action="/booking" method="post">
{{csrf_field()}}
<input type="hidden" name="product_id" value="{{$product->id}}" />
<input type="submit" value="Book Now!" />
</form>
If you use the laravel html collective you can simplify it even more
EDIT
Since your Bookings actually belong to a product you could also rearrange your resources so that a booking is create with the route
/product/5/booking (POST)
You could then simply access the product id as parameter of the route
EDIT 2
To access it from your controller simply ( case of hidde form input )
public function store(\Illuminate\Http\Request $request) {
dd($request->input('product_id');
}
If you defined it via route simply go for whatever you set as placeholder
Route::post('product/{product}/book', 'BookingController#store');
Controller then:
public function store(\Illuminate\Http\Request $request, $product) {
dd($product)
}
Include your model page as #include('partials.booking', ['product'=>$product])
Change your form action to
<form action="{{url('product/'.$product->id.'/booking')}}" method="post"> and most important add _token hidden field if your CSRF middleware is enabled.
Change your route to
Route::post('product/{product_id}/booking', 'BookingController#store');