Confusion regarding action in the form - laravel

I am fairly new to Laravel and I am trying CRUD operations using Resource Controller. The problem I am facing is regarding what should be the action in create a task form. Let me give you an overview, how the application is designed. I have created separate directories for MVC as listed below:
Todo_Model\todo_model.php
Todo_Controller\todo_controller.php
Todo_View\home.blade.php
Todo_View\create.blade.php
Route: Route::resource('todo','Todo_Controller\todo_controller');
route:list
Controller:
public function index()
{
return view('Todo_View\home');
}
public function create()
{
return view('Todo_View\create');
}
public function store(Request $request)
{
$todo= new todo_model();
$todo->title=$request->title;
$todo->body=$request->body;
$todo->save();
return redirect('todo');
}
create.blade.php
<form method="POST" action="../todo">
{{csrf_field()}}
<tr><td><input type="text" name="title" value="" placeholder="Title"></td></tr>
<tr><td><input type="text" name="body" value="" placeholder="Body"></td></tr>
<tr><td><input type="submit" name="submit" value="Submit"></td></tr>
</form>
Now the problem is that the action of the form should be todo as can be seen in the route:list but when I hit submit with that I get MethodNotAllowedHttpException and the URL shown is http://localhost/laravel-7/blog/public/todo/todo. But during the hit and trial I figured out I should use form action as ../todo. I am highly confused as to why do I have to use that action as it doesn't make any sense because in the route list, URI is clearly mentioned as todo
Another point, when I hit index page, URI is http://localhost/laravel-7/blog/public/todo and when I get redirected from home page to create page, the URI is http://localhost/laravel-7/blog/public/todo/create

You are confusing action with native php in laravel.
Replace your action="../todo" with action="{{url('todo')}}"
<form method="POST" action="{{url('todo')}}">
{{csrf_field()}}
<tr><td><input type="text" name="title" value="" placeholder="Title"></td></tr>
<tr><td><input type="text" name="body" value="" placeholder="Body"></td></tr>
<tr><td><input type="submit" name="submit" value="Submit"></td></tr>
</form>

You just need to specify the route exactly no need for saying where the file is actually located so action="/todo" would work fine

Related

Laravel Get Method Not Supported Exception (While the form method is already POST)

I am working on a Laravel project in which I have a form to write styled text, inside the form I used WYSIWYG editor, and the method of the form is POST. Sometimes when I submit the form it gives me (The GET method is not supported for this route. Supported methods: POST). This usually occurs when I give some styling to my text e.g. adding background color or inserting Arabic Characters. but when I insert plain text English words It works as expected and every things ok.
I added the header("Content-Type: text/html;charset=UTF-8"); at the top of index.php file but the result was not changed
Note: the application works in my local xampp server, but when I upload online I get the problem.
Here is form.blade.php (view)
<form method="POST" action="{{action('MainController#Insert')}}" accept-charset="utf-8">
{{csrf_field()}}
#method('post')
<input type="text" name="title" class="form-control" placeholder="Title"/>
<textarea name="details" id="myeditor"></textarea>
<input type="submit" value="Save"/>
</form>
<script>
CKEDITOR.replace('myeditor');
</script>
Here is my web.php (Routes)
Route::get('/', function () { return view('welcome'); });
Route::get('/form','MainController#LoadForm');
Route::post('/save','MainController#Insert');
And the is my controller
public function LoadForm(Request $req){
return view('form');
}
public function Insert(Request $req){
DB::table('notes')->insert(["title"=>$req->title,"details"=>$req->details]);
return redirect()->back()->with(["message"=>"Note Saved Successfully!"]);
}
Where is the problem?
to simplify it
<form method="POST" action="/save" accept-charset="utf-8">
{{csrf_field()}}
<input type="text" name="title" class="form-control" placeholder="Title"/>
<textarea name="details" id="myeditor"></textarea>
<input type="submit" value="Save"/>
</form>

Create urls using forms in Thymeleaf

I am new to Thymeleaf, and I have an issue with dynamically creating URLs using forms.
I have a simple spring boot app that stores objects in a database, and I can query the database using simple urls. For instance, the url /distance/0.3 would return objects whose distance attribute is lower than or equal to 0.3. These urls work perfectly when I edit them in the browser.
I would like users to be able to set these search values themselves. I tried to create a simple form to create the above url with user inputs, but I am getting the following error:
Neither BindingResult nor plain target object for bean name 'dist' available as request attribute
I have tried with this in the html document:
<form th:action="#{/distance/{pathParam}(pathParam=${dist}}">`
<p>Distance: <input type="text" th:field="*{dist}" /></p>
<p><input type="submit" value="Submit" /> <input type="reset" value="Reset" /></p>
</form>
and trying various answers from this discussion, but with no luck.
I have also tried to use the controller as suggested here, with this in the controller:
#GetMapping("/distance/search/")
public String userSetDistance(#RequestParam("dist") String dist) {
return "redirect:/distance/" + dist;
}
and this in the html file:
<form th:action="#{/distance/search/}">
<p>Distance: <input type="text" th:field="*{dist}" /></p>
<p><input type="submit" value="Submit" /> <input type="reset" value="Reset" /></p>
</form>
But this did not work either.
Could you please help me with this? The idea is simple but I cannot get something that works... thank you!
UPDATE
Based on the below answer from MohamedSanaulla, I decided to use the controller to do this, created a "forms" object with the required fields and edited my code as follows:
<form action="#" th:action="#{/distance/search}" th:object="${param}" method="post">`
<p>Distance: <input type="text" th:field="*{dist}"/></p>
<p><input type="submit" value="Submit" /> <input type="reset" value="Reset" /></p>
</form>
#PostMapping("/distance/search")
public String userGetClose(#ModelAttribute ("param") Forms form) {
String distance = String.valueOf(form.getDist());
return "redirect:/distance/" + distance;
}
Ideally I wanted to create and call the url directly from the html page, to avoid going back to the controller just to create the url, but this works fine.
You have to either use ModelMap or Model in your controller and then use addAttribute to set the dist:
public String controllerMethod(#RequestParam("dist") String dist,
Model model){
model.addAttribute("dist", dist);
return "viewName";
}
Or Thymeleaf provides context object to get query params like ${param.dist} directly in your HTML
Update:
Just saw that there is a redirect: in the controller. So the dist is no longer available in the request param and hence ${param.dist} will not work. The easier solution is to use ModelMap and put the dist as part of the view model.

Can pass models to Spring, but Thymeleaf still indicates an error

My problem is that I can pass models between Thymeleaf and Spring, but Thymeleaf still indicates an error.
Spring code:
#GetMapping("{id}/edit")
String getEdit(#PathVariable Long id, Model model) {
postRepository.findById(id).ifPresent(o -> model.addAttribute("post", o));
return "edit";
}
#PostMapping("{id}/edit")
String postEdit(#ModelAttribute Post post) {
postRepository.save(post);
return "redirect:/";
}
Thymeleaf code:
<form th:action="|/${post.id}/edit|" th:method="POST" th:object="${post}">
<input type="text" th:value="*{title}" name="title">
<input type="text" th:value="*{content}" name="content">
<input type="submit" value="Edit">
</form>
Thymeleaf indicates that it can't resolve ${post.id}, *{title} and *{content}. I have stopped and rerun the application more times so I suppose something is amiss in my code, even if it works.
What should I do to solve this issue?
First of all I think you don't need path variable in post mapping. You can use post mapping without path variable. So try modifying you controller like
#PostMapping("/edit")
String postEdit(#ModelAttribute Post post) {
postRepository.save(post);
return "redirect:/";
}
If you write controller like this it will be easy defining path in thymeleaf.
And second error can't resolve *{title} and *{content} is because of invalid keyword. Please try modifying your thymeleaf like
<form th:action="#{/edit}" th:method="POST" th:object="${post}">
<input type="text" th:field="*{title}" name="title">
<input type="text" th:field="*{content}" name="content">
<input type="submit" value="Edit">
</form>
I think this will work as you are expecting.

laravel 5.5 | old() empty in view unless $request->flash() used

I've run into an odd issue where the helper function old() always returns null in a blade view unless $request->flash() is used prior to loading the view. I have never had to do this when using laravel in the past. Did something change or is there something that I have forgotten to set/configure. Below is a simple example of the behavior:
web.php
Route::get('/test', function(){
return view('testView');
});
Route::post('/test', function(Illuminate\Http\Request $request){
$request->flash(); // if uncommented old() works, if commented old() does not work
return view('testView');
});
form in testView.blade.php
<form action="/test" method="POST">
{{csrf_field()}}
<input type="hidden" name="test001" value="001"/>
<input type="hidden" name="test002" value="002"/>
<div class="">
{{old('test001')}}
<br/>
{{old('test002')}}
</div>
<button type="submit">GO</button>
</form>
after form submitted without $request->flash()
after form submitted with $request->flash()
EDIT
Thinking this might have something to do with using a single route name for both post and get methods, the form was changed so to submit via get, and the issue persists. For example:
web.php
Route::get('/test', function(function(Illuminate\Http\Request $request){
return view('testView');
});
form in testView.blade.php
<form action="/test" method="GET">
<input type="hidden" name="test001" value="001"/>
<input type="hidden" name="test002" value="002"/>
<div class="">
{{old('test001')}}
<br/>
{{old('test002')}}
</div>
<button type="submit">GO</button>
</form>
Use redirect back() instead of loading view directly in a post method.
return redirect()->back()->withInput();
You need to flash request data to put old input into session, otherwise old() will return empty result. See official doc here.

How to update laravel 5.2 user edit form by using patch method

I am following laravel tutorial by jeffrey. But I have got a problem with while update the form. I'm getting all form fields but when updating it is showing that page not found. I have tried many multiple what jeffrey told how to updating form in 5.2
https://laracasts.com/series/laravel-5-from-scratch
<form action="form/{{$user->id}}" method="POST">
{{method_field("PATCH")}}
<label for="name">Name</label>
<input type="text" name="name" value="{{$user->name}}">
<label for="email">Email</label>
<input type="text" name="email" value="{{$user->email}}">
<label for=""></label>
<input type="submit" value="Submit" name="submit">
</form>
this is routes
Route::get("form/{id}/edit", "you#edit");
Route::patch("form/{user}", "you#update");
This is my controller
public function edit($id)
{
$user = laravel::findorfail($id);
return view("form", compact("user"));
}
public function update(Request $request, User $user)
{
$user->update($request->all());
}
Thank you in advance.
Try to run php artisan route:clear.
You also need to add field with CSRF token. Here's an example from the documentation:
<input type="hidden" name="_token" value="{{ csrf_token() }}">
As I see this, the problem with the route to be form/form/{id} is because of your action route of the form. To avoid this add / before the path, then, the final path will be /form/{id}. Another way you can get this is just using deleting the form/ words from you path and just keeping the {id}.
Explaining a little about what this is happening when you add / and the beginning of a route you are creating an absolute path, but if you start the path without the / then you are using relative path, this means that the path will depend on the current app url.
The best way to avoid this sort of things is using named routes. I always try to use them.
Eventually I found out the solution.
The routes patch should be:
Route::patch("form/{user}", "you#update");
but actually it should be like:
Route::patch("form/form/{id}", "you#update");
and the update controller should be like:
public function update(Request $request, $id)
{
$user = laravel::find($id);
$user->update($request->all());
return "sucess";
}

Resources