Reputation: 15824
I'm learning to utilize pure JS in Django projects. Being a server-side developer the concepts are relatively new for me, so need a hand.
Imagine a form where a user can post text, and/or upload an image. Think of it as a simple Django form like so:
class PostForm(forms.Form):
image = forms.ImageField(required=False)
reply = forms.CharField(required=False, widget=forms.Textarea(attrs={'cols':30,'rows':3,'class': 'cxl','autocomplete': 'off','autofocus': 'autofocus'}))
def __init__(self,*args,**kwargs):
super(PostForm, self).__init__(*args,**kwargs)
self.fields['image'].widget.attrs['id'] = 'browse_image_btn'
def clean(self):
data = self.cleaned_data
# perform cleaning
return data
If I were to render this form in HTML, something like the following would do:
<form action="{% url 'post_content' %}" method="POST" enctype="multipart/form-data">
{% csrf_token %}
{{ post_form.reply }}<br>
{{ post_form.image }}
<label for="browse_image_btn" style="cursor: pointer;"><img alt="Select photo" src="{{ STATIC_URL }}img/upload.svg" width="70" height="70"></label>
<input type="submit" value="submit">
</form>
But how do I create this HTML solely via JS?
Use-case: imagine a page that contains a long list of content, with a reply
button under each. The form above only appears under specific content once the user has pressed the reply
button. Moreover, pressing the same button toggles it off
too.
I can't seem to wrap my head around solving a problem like that. Please advise, preferably with an illustrative example. I'd prefer to understand the most efficient, scalable way to do this, one that can be deployed in professional settings. Only pure JS, no JQuery.
I've made attempts at this, but they're half-baked since I'm a JS newbie. Here's what I've got so far:
var okBtn = document.createElement('button');
setUpSubmitBtn(okBtn);
e.target.parentNode.insertAdjacentElement('afterend', okBtn);
var camBtn = document.createElement('img');
setUpCameraBtn(camBtn);
e.target.parentNode.insertAdjacentElement('afterend', lineBreak);
e.target.parentNode.insertAdjacentElement('afterend', camBtn);
var replyBox = document.createElement('textarea');
setUpReplyBox(replyBox);
e.target.parentNode.insertAdjacentElement('afterend', replyBox);
Where there are simple JS functions to create each of the widgets referred above:
function setUpReplyBox(replyBox) {
replyBox.classList.add('mts');
replyBox.setAttribute('id', 'reply-message');
replyBox.setAttribute('style', 'display:inline');
replyBox.setAttribute('placeholder', 'Reply');
}
function setUpSubmitBtn(okBtn) {
okBtn.classList.add('btn', 'bcb', 'bs', 'mts');
okBtn.setAttribute('style','border:none;height:25px;display:inline;');
okBtn.setAttribute('id','reply-ok');
okBtn.innerHTML = "OK";
}
function setUpCameraBtn(camBtn) {
camBtn.setAttribute('id','camera');
camBtn.setAttribute('src','/static/img/cam1.svg');
camBtn.setAttribute('width','45');
camBtn.setAttribute('height','45');
camBtn.setAttribute('style','display:inline;float:right;');
}
I feel like I'm doing it the hard/wrong way. The right pattern is probably going to be much simpler.
Upvotes: 0
Views: 1760
Reputation: 3091
Hope it helps:
var formTemplate = document.querySelector('#form-template form');
var idInput = document.getElementById('id-input');
function toggleReply(e) {
if (!formTemplate) return;
e.target.parentNode.insertBefore(formTemplate, e.target);
idInput.value = e.target.getAttribute('data-id');
};
Array.from(document.querySelectorAll('button.reply'))
.forEach(btn => btn.onclick = toggleReply)
form + .reply {
display: none;
}
<link href="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.7/css/bootstrap.min.css" rel="stylesheet"/>
<div id="form-template" style="display: none;">
<form action="" method="POST" enctype="multipart/form-data">
<input id="id-input" type="hidden" name="id" value="">
<div class="form-group">
<label for="reply">Reply:</label>
<textarea class="form-control" type="text" name="text"></textarea>
</div>
<input type="submit" class="btn btn-default pull-right" value="submit">
</form>
</div>
<div class="container">
<div class="list-group">
<div class="panel panel-default">
<div class="panel-heading">
<h3 class="panel-title">Comment title</h3>
</div>
<div class="panel-body">
Comment content
</div>
<div class="panel-footer clearfix">
<button class="reply btn btn-default pull-right" type="button" data-id="24">Reply</button>
</div>
</div>
<div class="panel panel-default">
<div class="panel-heading">
<h3 class="panel-title">Comment title</h3>
</div>
<div class="panel-body">
Comment content
</div>
<div class="panel-footer clearfix">
<button class="reply btn btn-default pull-right" type="button" data-id="25">Reply</button>
</div>
</div>
</div>
</div>
Upvotes: 1