Reputation: 109
I've been looking at various ways of the process of obtaining an ID and its contents within a modal using AJAX and Laravel. All I'm trying to accomplish is to allow a user to edit a reply by clicking on modal. I am aware I need to fetch the ID of a selected reply and pass that ID to the controller and target that reply. I have a one-to-many relationship between 'Ticket aka a Post' & 'Reply'. What does work is submitting the data to the database using AJAX, however, when clicking 'Confirm' to edit the reply, the content seems to change all of the replies and not just the one that was selected. I've tried adding a data=id field and using my reply->id, as well as giving my actual modal a reply->id and data-target reply-id; this seems to work but again doesn't uniquely identify which reply I want to update.
TicketController
public function editReply(Ticket $ticket)
{
$message = request()->input('message');
$ticket->reply()->update(['message' => $message]);
return response()->json($message);
}
Ticket Blade
@foreach($slug->reply as $r)
<div class="card-footer reply-footer bg-transparent" style="height: 2.5rem">
@if(Auth::user()->id == $r->user->id )
<button type="button" class="btn btn-light btn-outline-dark" id="open-modal"
data-toggle="modal" data-id="{{$r->id}}"
data-target="#edit-modal">Edit
</button>
@endif
</div>
@endforeach
<!-- edit reply modal !-->
<div class="modal fade" tabindex="-1" role="dialog" id="edit-modal">
<div class="modal-dialog" role="document">
<div class="modal-content">
<div class="modal-header">
<h5 class="modal-title" id="tit">Edit</h5>
<button type="button" class="close" data-dismiss="modal"
aria-label="Close">
<span aria-hidden="true">×</span>
</button>
</div>
<div class="modal-body">
<form id="edit-reply">
<div class="form-group">
<input type="hidden" name="replyID">
<textarea class="form-control testing" id="edit-box" rows="12"
name="edit-message"
required></textarea>
</div>
<button type="button" class="btn btn-light btn-outline-dark"
id="edit-button" data-dismiss="modal"
style="font-weight: bold;">Confirm
</button>
</form>
</div>
</div>
</div>
</div>
JS
<script type="text/javascript">
jQuery(document).ready(function () {
$('#edit-button').on('click', function (e) {
e.preventDefault();
$.ajaxSetup({
headers: {
'X-CSRF-TOKEN': $('meta[name="csrf-token"]').attr('content')
}
});
$.ajax({
url: "{{ route('ticket.edit-reply', $slug->slug) }}",
type: 'PATCH',
data: {
message: jQuery('#edit-box').val()
},
success: function (result, exception) {
},
error: function (jqXHR, exception) {
alert(jqXHR.status + ' - ' + exception);
}
});
});
});
</script>
Ticket Model
class Ticket extends Model
{
public function reply()
{
return $this->hasMany(Reply::class);
}
public function getRouteKeyName()
{
return 'slug';
}
}
Reply Model
class Reply extends Model
{
protected $fillable = [
'message', 'user_id', 'ticket_id', 'edit-message'
];
public function ticket()
{
return $this->belongsTo(Ticket::class);
}
public function user()
{
return $this->belongsTo(User::class);
}
}
So at the moment it updates all replies instead of just one, so am I meant to somehow use a GET (which I researched before) but then thought how would I use a GET with AJAX to fetch the ID in association with the controller and then a PATCH to submit the data using another method to submit the data? Unless I just make two separate doing each task independently?
Some guidance pointing me in the right direction would be highly appreciated as I've been trying to suss this out for about a week now.
Upvotes: 1
Views: 898
Reputation: 5180
All records got updated because $ticket->reply()
return all replies, and ->update()
is called for all of them.
YOu must instead look for that single edited Reply. In blade you must specify in the form the replyID to be edited. The same way you put message in
<textarea class="form-control testing" id="edit-box" rows="12" name="edit-message" required></textarea>
you will put replyID in
<input type="hidden" name="replyID">
And in Controller you can have :
public function editReply()
{
$reply = Reply::find(request()->input('replyID'));
$message = request()->input('edit-message');
$reply->update(['message' => $message]);
return response()->json($message);
}
Or if your URI is already containing the $replyID a parameter then :
public function editReply(Reply $reply)
{
$message = request()->input('edit-message');
$reply->update(['message' => $message]);
return response()->json($message);
}
And 2 things you should do :
1 - Change Many side relation to plural for more standard :
class Ticket extends Model
{
public function replies(){
return $this->hasMany(Reply::class);
}
public function getRouteKeyName()
{
return 'slug';
}
}
2 - Verify ownership in controller like you did in Blade view cause anyone can change the replyID
value in Browser and edit another one's reply.
Upvotes: 1