I am making a Laravel 8 app with posts and post categories. I am now working on the Edit post form, and I need to prepopulate it with the post's current data.
The id
column in the catergories
table is the category_id
foreign key in the posts
table.
In the Posts model I have:
class Posts extends Model {
use HasFactory;
protected $fillable = [
'title',
'category_id',
'description',
'body'
];
}
The route is Route::get('/dashboard/posts/edit/{id}', [PostsController::class, 'editPost'])
.
The editPost
method in the controller:
namespace App\Http\Controllers;
use Illuminate\Http\Request;
use App\Models\Posts;
class PostsController extends Controller {
// More code
public function editPost($id) {
$post = Posts::select (
"posts.id",
"posts.title",
"posts.description",
"posts.body",
"catergories.name as category_name"
)
->leftJoin("catergories", "posts.category_id", "=", "catergories.id")
->where('posts.id', $id)
->first();
echo $post->title . '<br>';
echo $post->category_name . '<br>';
}
}
In the form:
<input type="hidden" id="post_id" value="">
<div >
<label for="title" >Title</label>
<input id="title" type="text" name="title" placeholder="Title" value="{{ old('title', $post->title) }}" autofocus>
@error('title')<span >{{ $message }}</span>@enderror
</div>
<div >
<label for="category" >Category</label>
<select name="category_id" id="category" >
<option value="0">Select a category</option>
@foreach($categorys as $category)
<option value="{{ $category->id }}" {{ $category->id == $post->category_id ? 'selected' : '' }}>
{{ $category->name }}
</option>
@endforeach
</select>
</div>
The goal
The form is placed in a Bootstrap 5 modal, which means that I can not access https://myapp.test/dashboard/posts/edit/1
to get the necessary data. I have to do this via AJAX.
For this purpose, I have the following JavaScript function
function populateEditForm(event, entity) {
var id = event.currentTarget.dataset.id;
var url = `/dashboard/${entity}/edit/${id}`;
console.log(url);
var xmlhttp = new XMLHttpRequest();
xmlhttp.onreadystatechange = function() {
if (xmlhttp.readyState == XMLHttpRequest.DONE) {
if (xmlhttp.status == 200) {
console.log(xmlhttp.responseURL);
}
}
};
xmlhttp.open("GET", url, true);
xmlhttp.send();
}
that I call in a Blade template:
<a onclick="populateEditForm(event, 'posts')" href="#" data-id="{{ $post->id }}" title="Edit post" data-bs-toggle="modal" data-bs-target="#edit_post_modal">
<i ></i>
</a>
The problem
The console corectly displays the path to the edit method in the controller: https://myapp.test/dashboard/posts/edit/1
(for the post with id equal to 1), but I don't know how to use this to get the necessary data ( $post->title
, $post->category_name
, etc) and pass it to the form.
What is missing?
CodePudding user response:
You need to return the response as JSON and repopulate the form.
namespace App\Http\Controllers;
use Illuminate\Http\Request;
use App\Models\Posts;
class PostsController extends Controller {
// More code
public function editPost($id) {
$post = Posts::select (
"posts.id",
"posts.title",
"posts.description",
"posts.body",
"catergories.name as category_name"
)
->leftJoin("catergories", "posts.category_id", "=", "catergories.id")
->where('posts.id', $id)
->first();
return response()->json(['post' => $post]);
}
}
In your JavaScript
function populateEditForm(event, entity) {
var id = event.currentTarget.dataset.id;
var url = `/dashboard/${entity}/edit/${id}`;
console.log(url);
var xmlhttp = new XMLHttpRequest();
xmlhttp.onreadystatechange = function() {
if (xmlhttp.readyState == XMLHttpRequest.DONE) {
if (xmlhttp.status == 200) {
console.log(xmlhttp.response);
}
}
};
xmlhttp.open("GET", url, true);
xmlhttp.send();
}