My viewModel this..
function ViewModel() {
var self = this;
self.model = {};
self.Message = ko.observable("");
self.model.CurrentDisplayAmr = ko.observable();
self.model.SelectedAmr = ko.observable();
self.model.CurrentAmrWirings = ko.observableArray([]);
self.model.CurrentSelectedWire = ko.observable();
self.model.AmrCommands = ko.observableArray([]);
//selected Amr is update here
self.selectAmr = function (item) {
self.model.SelectedAmr(item);
self.GetAmrWirings();
};
//Amrs search is here
self.GetAmrs = function (searchTerm) {
var self = this; // Retain scope of view model
$.ajax({
url: '/AmrSearch/SearchAmrs',
cache: false,
contentType: 'application/json',
data: ko.toJSON({ AmrNo: self.SearchAmrNo }),
type: "POST",
success: function (result) {
$('#processing-modal').modal('hide');
if (result.success) {
self.model.CurrentDisplayAmr(result.data);
self.Message(result.message);
}
else
self.Message("Modem aramada sorun oluştu: " + result.message);
},
error: function (errorDetail) {
$('#processing-modal').modal('hide');
self.Message("Modem arama isteğinde hata: " + errorDetail);
}
});
}
Amr Selection html is here :
<form class="form-horizontal">
<fieldset>
<div class="col-md-4">
<div class="input-group">
<input disabled type="text" class="form-control" placeholder="0000000" data-bind="value: model.CurrentDisplayAmr.AmrRemoteId">
<span class="input-group-btn">
<button class="btn btn-default" type="button" data-bind="click: $root.selectAmr" data-toggle="modal" data-target="#processing-modal">
<span class="glyphicon glyphicon-ok"></span> Seç
</button>
</span>
</div>
</div>
</fieldset>
</form>
and if i bind text self.model.SelectedAmr.AmrRemoteId is no problem.
this code is ok :
<span class="glyphicon glyphicon-hdd" style="font-size: 38px;"></span> <a data-bind="text:model.SelectedAmr.AmrRemoteId"></a>
result is :
00000012
but if i change this :
<span class="glyphicon glyphicon-hdd" style="font-size: 38px;"></span> <a data-bind="text:'Selected Modem ' + model.SelectedAmr.AmrRemoteId"></a>
result is
Selected Modem undefined
why cant combine string and numeric value?
Related
With Django I made a Show more comments button using ajax. This system works, but the problem is that there are form fields in the comments I brought in this way, and when I click the more button, csrf_token does not appear in this comment field. As such, I get a csrf_token error when I submit the form. I leave my codes below.
To solve this problem, I ran the form with the get method, but as such, the function in the views directs me to the page with JsonResponse. Another solution was to give the header information csrf_token, but that didn't solve the problem either.
blog_detail.html
<script>
$(document).ready(function(){
$('#load_form').submit(function(e){
e.preventDefault();
var limit = $(this).attr('limit')
var page = document.getElementById('pagination')
var blog_comment_list = $('#blog-comment-list')
var serializedData = $(this).serialize();
$.ajax({
type:'GET',
url: "{% url 'load-more-comments' %}",
data : serializedData,
success: function(response){
blog_comment_list.html(response.comment_html)
if (page.value >= limit){
$('#submit_button').hide()
}
page.value = parseInt(page.value)+1
},
})
})
})
</script>
<div id="blog-comment-list">
{% include 'front_end/blog/comment/partial-comment.html' %}
</div>
<form method="GET" id="load_form" limit="{{num_pages}}">
<input type="hidden" name="pk" value="{{details.id}}">
<input type="hidden" name="page" value="2" id="pagination">
<input type="submit" name="load" value="Load More" id="submit_button">
</form>
partial-comment-html
<div class="media-holder mt-5">
<h3 class="title mb-3">All Comments</h3>
{% for item in comments %}
<div class="infinite-container">
<div class="media mb-5">
<img class="img-fluid rounded-circle box-shadow mr-4" alt="image" src="{{item.owner.get_image_or_default}}" style="width: 100px;height: 100px;">
<div class="media-body">
<h6>{{item.owner.name}} {{item.owner.surname}}</h6>
<br>
<small><span style="font-size:14px;" class="stars-container stars-{% widthratio item.rate.rate 1 20 %}" id="stars">★★★★★</span></small>
<div class="comment-date"> <span class="date">{{item.created_date|naturaltime}}</span>
</div>
<p>{{item.content}} </p>
<div align="center">
{% if item.comments.all %}Cevapları Görüntüle ({{item.comments.count}}){% else %}Cevap Ver{% endif %}
</div>
<div class="generic-comment" id="generic-comment-id-{{item.id}}" style="display:none;">
<!-- -->
<div class="infinite-generic-comment">
<form action="{% url 'comment-answer' %}" method="POST" id="answer_form">
{% csrf_token %}
<input type="hidden" name="comment_id" value="{{item.id}}">
<div class="row">
<div class="col-9">
<input type="text" placeholder="Cevap Ver" name='generic_comment' class="form-control">
</div>
<div class="col-2">
<input type="submit" value="Cevap Ver" class="btn btn-outline-primary">
</div>
</div>
</form>
{% for comment in item.comments.all %}
<div class="media mb-2">
<img class="img-fluid rounded-circle box-shadow mr-4" alt="image" src="{{item.owner.get_image_or_default}}" style="width: 100px;height: 100px;">
<div class="media-body">
<h6>{{comment.owner.name}} {{comment.owner.surname}}</h6>
<div class="comment-date"> <span class="date">{{comment.created_date|naturaltime}}</span>
</div>
<p>{{comment.content}} </p>
</div>
</div>
{% endfor %}
</div>
<!-- -->
</div>
</div>
</div>
</div>
{% endfor %}
</div>
<script>
var aTag = document.getElementsByClassName('show-answers')
for (let i = 0; i< aTag.length; i++){
aTag[i].addEventListener('click', (event) => {
var generic = document.getElementById(`generic-${event.target.id}`)
if (generic.style.display == 'none'){
$(`#generic-${event.target.id}`).slideDown('slow')
}
else{
$(`#generic-${event.target.id}`).slideUp('slow')
}
})
}
function getCookie(name) {
var cookieValue = null;
if (document.cookie && document.cookie !== '') {
var cookies = document.cookie.split(';');
for (var i = 0; i < cookies.length; i++) {
var cookie = jQuery.trim(cookies[i]);
// Does this cookie string begin with the name we want?
if (cookie.substring(0, name.length + 1) === (name + '=')) {
cookieValue = decodeURIComponent(cookie.substring(name.length + 1));
break;
}
}
}
return cookieValue;
}
var csrftoken = getCookie('csrftoken');
function csrfSafeMethod(method) {
// these HTTP methods do not require CSRF protection
return (/^(GET|HEAD|OPTIONS|TRACE)$/.test(method));
}
$(document).ready(function(){
$('#answer_form').submit(function(e){
e.preventDefault()
var serializedData = $(this).serialize()
var url = $(this).attr('action')
$.ajaxSetup({
beforeSend: function(xhr, settings) {
if (!csrfSafeMethod(settings.type) && !this.crossDomain) {
xhr.setRequestHeader("X-CSRFToken", csrftoken);
}
},
//headers: { "X-CSRFToken": getCookie("csrftoken") }
});
$.ajax({
type:'POST',
url: url,
data:serializedData,
success: function(response){
if (response.success){
$('#answer_form').trigger('reset')
Swal.fire(
'Başarılı!',
'Cevap onaya gönderildi',
'success'
)
}
}
})
})
})
</script>
views.py
def answer_comment(request):
if request.method=='POST':
comment = Comment.objects.get(id=request.POST.get('comment_id'))
comment.comments.create(owner=request.user, content=request.POST.get('generic_comment'))
return JsonResponse({'success':True},status=200)
return JsonResponse({'success':False}, status = 403)
Note: I tried the csrf_exempt decorator function, but still could not solve the problem.
The methods I use are available in the script tag in partial-comment-html. How can I solve this problem. As I said, when I press the load more button, the necessary form fields to respond to a comment are just below these comments and when load more with ajax, the csrf_token information is deleted in these form fields, and nothing happens in new comments.
Note 2: When {{csrf_token}} is entered, I added the hidden input field with javascript myself, but Django realized that I added it and prevented me.
Is it possible to get req.body back for more than single set of object?
HTML (EJS)
<form action="/newQuote" method="POST">
<h4 id="new-form-heading">New Document</h4>
<div class="total-quote-items">
<div id="item1" class="quote-item">
<div class="form-group">
<label>Item</label>
<a href="#" class="delete-item float-right text-danger" onclick="removeItem(this)"><i
class="fas fa-times-circle"></i></a>
<input type="text" name="name1" class="form-control item-name" placeholder="List your item here !"
required>
</div>
<div class="form-row">
<div class="form-group col-md-4">
<label>Quantity</label>
<input type="number" name="quantity1" class="form-control item-quantity" required>
</div>
<div class="form-group col-md-4">
<label>Price</label>
<input type="number" name="price1" class="form-control item-price" required>
</div>
<div class="form-group col-md-4">
<label>Total</label>
<input type="text" name="total1" class="form-control price-total" required>
</div>
</div>
</div>
</div>
<span class="btn btn-info add-item" onclick="addItem()"><i class="fas fa-plus-square"></i> New Item</span>
<div class="modal-footer">
<button class="btn btn-primary d-block" type="submit">Save Changes</button>
</div>
</form>
JS
function addItem() {
numberofDiv = document.querySelectorAll('.quote-item').length + 1
var original = document.querySelector('.quote-item')
var clone = original.cloneNode(true); // "deep" clone
clone.querySelector('.item-name').value = '';
// clone.querySelector('.item-name').name = '';
clone.querySelector('.item-quantity').value = '';
clone.querySelector('.item-quantity').name = '';
clone.querySelector('.item-price').value = '';
clone.querySelector('.item-price').name = '';
clone.querySelector('.price-total').value = '';
clone.querySelector('.price-total').name = '';
original.parentNode.appendChild(clone);
// console.log(numberofDiv)
Array.from(document.querySelectorAll('.quote-item')).forEach((itemId, i) => {
console.log(itemId.querySelector('.item-name').name = 'name' + (i + 1))
console.log(itemId.querySelector('.item-quantity').name = 'quantity' + (i + 1))
console.log(itemId.querySelector('.item-price').name = 'price' + (i + 1))
console.log(itemId.querySelector('.price-total').name = 'total' + (i + 1))
// console.log(i)
itemId.id = 'item' + ( i + 1 )
})
}
function removeItem(param) {
deleteItem = param.parentNode.parentNode
numberofDiv = document.querySelectorAll('.quote-item').length - 1
console.log(numberofDiv)
if (numberofDiv <= 0) {
return
} else {
deleteItem.remove()
}
Array.from(document.querySelectorAll('.quote-item')).forEach((itemId, i) => {
// console.log(itemId)
// console.log(i)
itemId.id = 'item' + ( i + 1 )
})
}
App.js (route)
app.post('/newQuote', (req, res) => {
if (req.isAuthenticated()) {
console.log(req.user.id)
console.log(req.body)
} else {
res.redirect('/login');
}
});
This what I currently got back, as i add more than 1 item
{
name1: 'apple',
quantity1: '123',
price1: '123',
total1: '123',
name2: 'banana',
quantity2: '456',
price2: '456',
total2: '456',
name3: 'carrot',
quantity3: '789',
price3: '789',
total3: '789'
}
This is what how i would want it, (probably?)
{
name1: 'apple',
quantity1: '123',
price1: '123',
total1: '123',
},
{
name2: 'banana',
quantity2: '456',
price2: '456',
total2: '456',
},
{
name3: 'carrot',
quantity3: '789',
price3: '789',
total3: '789',
}
** Should i assign the iterate number for every item's name and other attributes?
** What i'm trying to achieve is req.body and for every input user have added, dynamically save the object(s) to MongoDB (If user add / post 4 quote items = 4 quote documents created and saved), I'm i on the right path here?
my modal code
<form action="/update" method="post">
<div class="modal fade" id="duzen" tabindex="-1" role="dialog" aria-labelledby="exampleModalLabel" aria-hidden="true">
<div class="modal-dialog" role="document">
<div class="modal-content">
<div class="modal-header">
<h5 class="modal-title" id="Moda1">Etiketi Düzenle</h5>
<button type="button" class="close" data-dismiss="modal" aria-label="Close">
<span aria-hidden="true">×</span>
</button>
</div>
<div class="modal-body">
<div class="form-group">
<input type="text" name="okuyucu" class="form-control okuyucu" placeholder="okuyucu" required>
</div>
<div class="form-group">
<input type="text" name="x" class="form-control x" placeholder="x" required>
</div>
<div class="form-group">
<input type="text" name="y" class="form-control y" placeholder="y" required>
</div>
</div>
<div class="modal-footer">
<input type="hidden" name="idnew_table" class="idnew_table">
<button type="button" class="btn btn-secondary btn-pill" data-dismiss="modal">Kapat</button>
<button type="submit" class="btn btn-primary btn-pill">Güncelle</button>
</div>
</div>
</div>
</div>
</form>
my ajax code
<script>
$(document).ready(() => {
var x1="";
var y1="";
var okuyucu1="";
var id="";
$.ajax({
url: "http://localhost:10001/etiketokuyucu",
method: 'GET',
success: function(response){
if(response.length > 0){
for(let index = 0; index < response.length; index++) {
var newRow = $("<tr>");
var cols = "";
var okuyucu = '';
var x = '';
var y = '';
var id='';
cols += '<td>' + response[index].idnew_table+'</td>';
cols += '<td> '+ response[index].okuyucu +'</td>' ;
cols += '<td> '+ response[index].x +'</td>';
cols += '<td> '+ response[index].y +'</td>';
cols += '<td>'
+
'<div class="dropdown d-inline-block widget-dropdown">'+
'<a class="dropdown-toggle icon-burger-mini" href="" role="button" id="dropdown-recent-order1" data-toggle="dropdown" aria-haspopup="true" aria-expanded="false" data-display="static"></a>'+
'<ul class="dropdown-menu dropdown-menu-right" aria-labelledby="dropdown-recent-order1">'+
'<li class="dropdown-item edit">'+
'Düzenle'+
'</li>'+
'<li class="dropdown-item delete">'+
'Sil'+
'</li>'+
'</ul>'+
'</div>'+
'</td>' ;
newRow.append(cols);
$("#example .tbody").append(newRow);
}
}
}
})
})
my modal script code
<script>
$(document).ready(function(){
//showing data to modal for edit record
$('#example').on('click','.edit',function(){
var idnew_table = $(this).data('idnew_table');
var okuyucu= $(this).data('okuyucu');
var x = $(this).data('x');
var y = $(this).data('y');
console.log(idnew_table+"okuyucu="+okuyucu + "x=" +x+" y="+y);
var modal = $(this);
modal.find('#okuyucu').text(okuyucu);
modal.find('#x').text(x);
modal.find('#y').text(y);
/*$('#duzen').modal('show');
$('.okuyucu').val($(this).data('okuyucu'))
$('.x').val(x);
$('.y').val(y);
$('.idnew_table').val(idnew_table);
*/ });
//showing modal for delete record
});
I want to show my mysql data on modal but ı got an error.In this code first show true value in console okuyucu,x,y etc but in modal shows they are undefined.why are they not show true value in my console when they second run?It passes data from ajax to table and I read that value from script code but doesn't show in my modal
Thank you for your help
Your current code for appending value to table was having 2 class edit i.e : li and <a> so when you click on edit link both class where getting called and it was returning undefined .Also , your input inside modal doesn't have any id instead it only have namei have corrected your code .
Demo Code :
//demo data
var response = [{
"idnew_table": "1",
"okuyucu": "abc",
"x": "12",
"y": "fbg"
}, {
"idnew_table": "2",
"okuyucu": "abcd",
"x": "152",
"y": "f5bg"
}, {
"idnew_table": "3",
"okuyucu": "abce",
"x": "125",
"y": "fb5g"
}]
if (response.length > 0) {
for (let index = 0; index < response.length; index++) {
var newRow = $("<tr>");
var cols = "";
var okuyucu = '';
var x = '';
var y = '';
var id = '';
cols += '<td>' + response[index].idnew_table + '</td>';
cols += '<td> ' + response[index].okuyucu + '</td>';
cols += '<td> ' + response[index].x + '</td>';
cols += '<td> ' + response[index].y + '</td>';
cols += '<td>' +
'<div class="dropdown d-inline-block widget-dropdown">' +
'<a class="dropdown-toggle icon-burger-mini" href="" role="button" id="dropdown-recent-order1" data-toggle="dropdown" aria-haspopup="true" aria-expanded="false" data-display="static"></a>' +
'<ul class="dropdown-menu dropdown-menu-right" aria-labelledby="dropdown-recent-order1">' +
'<li class="dropdown-item ">' + //<--remove class edit
'Düzenle'+
'</li>' +
'<li class="dropdown-item delete">' +
'Sil' +
'</li>' +
'</ul>' +
'</div>' +
'</td>';
newRow.append(cols);
$("#example .tbody").append(newRow);
}
}
//showing data to modal for edit record
$('#example').on('click','.edit',function(){
var idnew_table = $(this).data('idnew_table');
var okuyucu = $(this).data('okuyucu');
var x = $(this).data('x');
var y = $(this).data('y');
console.log(idnew_table + "okuyucu=" + okuyucu + "x=" + x + " y=" + y);
//find input under modal and set value of inputs
$("#duzen").find('input[name=okuyucu]').val(okuyucu);
$("#duzen").find('input[name=x]').val(x);
$("#duzen").find('input[name=y]').val(y);
$('#duzen').modal('show');
});
<link rel="stylesheet" href="https://stackpath.bootstrapcdn.com/bootstrap/4.3.1/css/bootstrap.min.css" integrity="sha384-ggOyR0iXCbMQv3Xipma34MD+dH/1fQ784/j6cY/iJTQUOhcWr7x9JvoRxT2MZw1T" crossorigin="anonymous">
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/popper.js/1.14.7/umd/popper.min.js" integrity="sha384-UO2eT0CpHqdSJQ6hJty5KVphtPhzWj9WO1clHTMGa3JDZwrnQq4sF86dIHNDz0W1" crossorigin="anonymous"></script>
<script src="https://stackpath.bootstrapcdn.com/bootstrap/4.3.1/js/bootstrap.min.js" integrity="sha384-JjSmVgyd0p3pXB1rRibZUAYoIIy6OrQ6VrjIEaFf/nJGzIxFDsf4x0xIM+B07jRM" crossorigin="anonymous"></script>
<table id="example" border="1">
<thead>
<th>idnew_table</th>
<th>okuyucu</th>
<th>x</th>
<th>y</th>
<th>Action</th>
</thead>
<tbody class="tbody">
</tbody>
</table>
<form action="/update" method="post">
<div class="modal fade" id="duzen" tabindex="-1" role="dialog" aria-labelledby="exampleModalLabel" aria-hidden="true">
<div class="modal-dialog" role="document">
<div class="modal-content">
<div class="modal-header">
<h5 class="modal-title" id="Moda1">Etiketi Düzenle</h5>
<button type="button" class="close" data-dismiss="modal" aria-label="Close">
<span aria-hidden="true">×</span>
</button>
</div>
<div class="modal-body">
<div class="form-group">
<input type="text" name="okuyucu" class="form-control okuyucu" placeholder="okuyucu" required>
</div>
<div class="form-group">
<input type="text" name="x" class="form-control x" placeholder="x" required>
</div>
<div class="form-group">
<input type="text" name="y" class="form-control y" placeholder="y" required>
</div>
</div>
<div class="modal-footer">
<input type="hidden" name="idnew_table" class="idnew_table">
<button type="button" class="btn btn-secondary btn-pill" data-dismiss="modal">Kapat</button>
<button type="submit" class="btn btn-primary btn-pill">Güncelle</button>
</div>
</div>
</div>
</div>
</form>
This is not a question. I am sharing the knowledge I gained after much research and testing. I built a search for optional fields using angle 6 and HttpParams. I am sharing this, because I searched a lot, not having been successful in the search.
Dev. Env.: Angular 6.0.9, Spring boot 2.0.7.
Form:
<form [formGroup]="searchForm" (ngSubmit)="submitSearch()">
<div class="row">
<div class="col-md-1">
<label>Código/Ano: </label>
</div>
<div class="col-md-2">
<input type="text" class="form-control form-control-sm" id="inputCodigo" formControlName="codigo" placeholder="código" maxlength="10">
</div>
<div class="col-md-1">
<input type="text" class="form-control form-control-sm" id="inputAno" formControlName="ano" placeholder="ano" maxlength="4">
</div>
<div class="col-md-1">
<label>Período: </label>
</div>
<div class="col-md-2">
<input type="text" class="form-control form-control-sm" placeholder="de" onfocus="(this.type = 'date')" formControlName="dataInicio">
</div>
<div class="col-md-2">
<input type="text" class="form-control form-control-sm" placeholder="ate" onfocus="(this.type = 'date')" formControlName="dataFinal">
</div>
<div class="col-md-1">
<input class="btn btn-primary btn-sm" type="submit" value="Buscar">
</div>
<div class="col-md-2">
<a [routerLink]="['/documentos/cadastro']" class="btn btn-sm btn-danger">Novo Documento</a>
</div>
</div>
Component:
export class DocumentosComponent implements OnInit {
documentos: Documento[];
searchForm: FormGroup;
docFiltro: DocumentoSearch = new DocumentoSearch();
constructor(
private documentoService: DocumentoService,
private fb: FormBuilder,
private page: Page
) {}
ngOnInit() {
this.page.page = "0";
this.createFormGroup();
this.getDocumentosByFilter();
}
getDocumentosByFilter() {
this.docFiltro = this.searchForm.value;
let searchParams = this.createSearchParam(this.docFiltro);
this.documentoService.findPage(searchParams).subscribe(
data => {
this.documentos = data["content"];
this.page.pages = new Array(data["totalPages"]);
},
error => {
console.log(error.error.message);
}
);
}
createSearchParam(docFiltro: DocumentoSearch): HttpParams {
let searchParams = new HttpParams()
searchParams = searchParams.set("page",this.page.page)
if (
docFiltro.codigo != null &&
docFiltro.codigo != undefined &&
docFiltro.codigo != ""
) {
searchParams = searchParams.set("codigo", docFiltro.codigo);
}
if (
docFiltro.ano != null &&
docFiltro.ano != undefined &&
docFiltro.ano != ""
) {
searchParams = searchParams.set("ano", docFiltro.ano);
}
if (
docFiltro.dataInicio != null &&
docFiltro.dataInicio != undefined &&
docFiltro.dataInicio != ""
) {
searchParams = searchParams.set("dataInicio", docFiltro.dataInicio);
}
if (
docFiltro.dataFinal != null &&
docFiltro.dataFinal != undefined &&
docFiltro.dataFinal != ""
) {
searchParams = searchParams.set("dataFinal", docFiltro.dataFinal);
}
return searchParams;
}
setPage(i, event: any) {
event.preventDefault();
this.page.page = i;
this.getDocumentosByFilter();
}
createFormGroup() {
this.searchForm = this.fb.group({
codigo: [""],
ano: [""],
dataInicio: [""],
dataFinal: [""]
});
}
submitSearch() {
this.page.page = '0';
this.getDocumentosByFilter();
}
}
Service method:
findPage(searchParams: HttpParams) {
return this.http.get<Documento[]>(`${API_URL}/sge/documento/search`, {params: searchParams});
}
I'm using Ajax in a comments section in my blog project. It was working fine however clearly I've changed something because now when I go to edit a comment it won't work and when I try to delete, it does destroy the comment but it also gets rid of a load of other comments until I refresh the page when everything looks fine. The only Ajax function now working is create new comment.
Here's my show page code for my comments section:
<!--================== COMMENTS DISPLAY SECTION ====================================================================-->
<div id="comments">
<% blog.comments.forEach(function(comment){ %>
<div class="comment-container">
<div class="jumbotron comment">
<div class="row">
<div class="col-md-1">
<img class="comment-ico" src = "<%=comment.author.image%>">
</div>
<div class="col-md-7">
<h4><%=comment.author.username%></h4>
</div>
</div>
</div>
<div><p><%=comment.text%></p></div>
<!--=================EDIT COMMENT FORM =========================================================================-->
<form id="edit-comment-form" action = "/blogs/<%= blog._id %>/comments/<%=comment._id%>?_method=PUT" method = "POST" id="newComment">
<textarea class = "form-control" rows="4" name = "comment[text]"><%=comment.text%></textarea>
<button class = "btn btn-lg btn-primary btn-block">Submit</button>
</form>
<!--==================================================================================================================-->
<!-- if current user is the same as author -->
<% if(currentUser && currentUser.username == comment.author.username) { %>
<div class="row">
<div class="col-md-1 choice">
<a class="edit">Edit</a>
</div>
<div class="col-md-1">
<form id = "delete-form" action = "/blogs/<%= blog._id %>/comments/<%=comment._id%>?_method=DELETE" method = "POST">
<input type = "submit" class = "button-delete" value = "Delete"></form>
</div>
<% } %>
<% if(currentUser && currentUser.username == comment.author.username) { %>
<div class="col-md-1 choice-report">
<a class="report">Report</a>
</div>
<% } else { %>
<div class="col-md-1 choice-no-user">
Report
</div>
<% } %>
</div>
<br>
<hr class = "style-three">
<% }) %>
</div>
</div>
</div>
<!--==================================================================================================================-->
<% if(currentUser){ %>
<div class = "container-form">
<form action = "/blogs/<%= blog._id %>/comments" method = "POST" id="newComment">
<div class="row">
<div class="col-md-2">
<img class="newComment-ico" src = " <%=currentUser.image%>">
</div>
<div class="col-md-10">
<label for="comment">Add comment</label>
</div>
</div>
<textarea class = "form-control" rows="4" placeholder = "Type comment here..." name = "comment[text]"></textarea>
<button class = "btn btn-lg btn-primary btn-block">Submit</button>
</form>
</div>
<% } %>
And my Ajax code:
// update comment
$('#comments').on('submit', '#edit-comment-form', function(e){
e.preventDefault();
// get info from form
var formData = $(this).serialize();
var formAction = $(this).attr('action');
var $originalItem = $(this).parent('.comment-container');
$.ajax({
url: formAction,
data: formData,
type: 'PUT',
originalItem: $originalItem,
success: function(data) {
var blog_id = location.pathname.replace("/blogs/", "");
this.originalItem.html(
`
<div class="comment-container">
<div class="jumbotron comment">
<div class="row">
<div class="col-md-1">
<img class="comment-ico" src = "${data.author.image}">
</div>
<div class="col-md-7">
<h4>${data.author.username}</h4>
</div>
</div>
</div>
<div><p>${data.text}</p></div>
<form id="edit-comment-form" action = "/blogs/${blog._id}/comments/${data._id}?_method=PUT" method = "POST" id="newComment">
<textarea class = "form-control" rows="4" name = "comment[text]">${data.text}</textarea>
<button class = "btn btn-lg btn-primary btn-block">Submit</button>
</form>
<div class="row">
<div class="col-md-1 choice">
<a class="edit">Edit</a>
</div>
<div class="col-md-1">
<form id = "delete-form" action = "/blogs/${blog._id}/comments/${data._id}?_method=DELETE" method = "POST">
<input type = "submit" class = "button-delete" value = "Delete"></form>
</div>
<div class="col-md-1 choice-report">
<a class="report">Report</a>
</div>
</div>
<br>
<hr class = "style-three">
`
);
}
});
});
And here's the update comments route:
// comment update route
router.put("/:comment_id", function(req, res){
Comment.findByIdAndUpdate(req.params.comment_id, req.body.comment, {new: true}, function(err, updatedComment){
if(err) {
res.redirect("back");
} else {
if(req.xhr);
res.json(updatedComment);
// } else {
// res.redirect("/blogs/" + req.params.id);
// }
}
})
})
My destroy Ajax code:
// delete comments asynchonously
$('#comments').on('submit', '#delete-form', function(e){
e.preventDefault();
var confirmResponse = confirm('Are you sure you want to delete this comment?');
if(confirmResponse){
var actionURL = $(this).attr('action');
$itemToDelete = $(this).closest('.comment-container');
$.ajax({
url: actionURL,
type: 'DELETE',
itemToDelete: $itemToDelete,
success: function(data){
this.itemToDelete.remove();
}
})
} else {
$(this).find('input').blur();
}
})
And destroy route:
// comments destroy route
router.delete("/:comment_id", function(req, res){
Comment.findByIdAndRemove(req.params.comment_id, function(err, comment){
if(err) {
res.redirect("back");
} else {
res.json(comment);
}
})
})
UPDATE:
I noticed a couple of errors on my Ajax code whereby I had referenced ${blog._id} rather than ${blog_id}. I've updated as follows:
// update comment
$('#comments').on('submit', '#edit-comment-form', function(e){
e.preventDefault();
// get info from form
var formData = $(this).serialize();
var formAction = $(this).attr('action');
var $originalItem = $(this).parent('.comment-container');
$.ajax({
url: formAction,
data: formData,
type: 'PUT',
originalItem: $originalItem,
success: function(data) {
var blog_id = location.pathname.replace("/blogs/", "");
this.originalItem.html(
`
<div class="jumbotron comment">
<div class="row">
<div class="col-md-1">
<img class="comment-ico" src = "${data.author.image}">
</div>
<div class="col-md-7">
<h4>${data.author.username}</h4>
</div>
</div>
</div>
<div><p>${data.text}</p></div>
<form id="edit-comment-form" action = "/blogs/${blog_id}/comments/${data._id} method = "POST" id="newComment">
<textarea class = "form-control" rows="4" name = "comment[text]">${data.text}</textarea>
<button class = "btn btn-lg btn-primary btn-block">Submit</button>
</form>
<div class="row">
<div class="col-md-1 choice">
<a class="edit">Edit</a>
</div>
<div class="col-md-1">
<form id = "delete-form" action = "/blogs/${blog_id}/comments/${data._id}?_method=DELETE" method = "POST">
<input type = "submit" class = "button-delete" value = "Delete"></form>
</div>
<div class="col-md-1 choice-report">
<a class="report">Report</a>
</div>
</div>
<br>
<hr class = "style-three">
`
);
}
});
});
Now the comment will update asynchronously, however until the page is refreshed, again it's kicking off a load of other comments.Essentially it's getting rid temporarily of all comments beneath the one being edited. When you refresh though, all comments re-appear in the correct order including the edits made to the comment in question