I am adding a Search functionality to my E-commerce Project using Javascript, I have followed a tutorial that explains that when writing the title in the search bar only the items with the same letter appears. In my project, it was working fine for basic HTML but I am trying to make it a little more complex to include a complete card with some details such as price, not just the title.
Here is the model.py
class Item(models.Model):
title = models.CharField(max_length=100)
image = models.ImageField(blank=False, upload_to=upload_design_to)
price = models.DecimalField(decimal_places=2, max_digits=100)
discount_price = models.DecimalField(decimal_places=2, max_digits=100, blank=True, null=True)
timestamp = models.DateTimeField(default=timezone.now)
Here is the views.py
class ItemListView(ListView):
model = Item
paginate_by = 12
template_name = "store/product_list.html"
ordering = ['-timestamp']
def get_context_data(self, **kwargs):
context = super().get_context_data(**kwargs)
context["qs_json"] = json.dumps(list(Item.objects.values()),cls=DjangoJSONEncoder)
return context
Here is the scripts.py
<script>
const data = '{{qs_json}}'
const rdata = JSON.parse(data.replace(/"/g, '"'))
console.log(rdata)
const input = document.getElementById('search_here')
console.log(input)
let filteredArr = []
input.addEventListener('keyup', (e)=>{
box.innerHTML = ""
filteredArr = rdata.filter(store=> store['title'].includes(e.target.value))
console.log(filteredArr)
if (filteredArr.length > 0){
filteredArr.map(store=>{
box.innerHTML += `<b>${store['title']}</b><br>`
})
} else {
box.innerHTML = "<b>No results found...</b>"
}
})
</script>
Here is the template.html
<input id="search_here" class="mb-2 form-control" placeholder="Type to search...">
<!--Card-->
<div id="box" class='row card-group'>
{% for item in object_list %}
<div class="col-4 mb-3">
<div class="card h-100">
<a href="{{item.get_absolute_url}}">
<embed src="{{ item.image.url }}" class="card-img-top" alt="..."/>
</a>
<div class="card-body">
<h5 class="card-title">{{ item.title }}</h5>
<p class="card-text">
{% if item.description %}
{{ item.description }}
{% endif %}
</p>
</div>
<div class="card-footer">
<small class="text-muted">{{ item.timestamp }}</small>
</div>
</div>
</div>
{% endfor %}
</div>
<!--Card-->
My Question: How do I replace the simple <b>${store['title']}</b><br>
with the below in the scripts with the whole card div with all its information related to it?
If any more information or clarifications required let me know
<div class="col-4 mb-3">
<div class="card h-100">
<a href="{{item.get_absolute_url}}">
<embed src="{{ item.image.url }}" class="card-img-top" alt="..."/>
</a>
<div class="card-body">
<h5 class="card-title">{{ item.title }}</h5>
<p class="card-text">
{% if item.description %}
{{ item.description }}
{% endif %}
</p>
</div>
<div class="card-footer">
<small class="text-muted">{{ item.timestamp }}</small>
</div>
</div>
</div>
Advertisement
Answer
Your template.html
page already have all htmls generated using for-loop
so you don’t need to generate them again .Instead , when user type you can loop through all div and check if card-title
div has that input
if it has simply show that div or else hide it.
Demo Code :
const input = document.getElementById('search_here')
input.addEventListener('keyup', (e) => {
var inputs = e.target.value.toLowerCase(); //do lowercase
//loop through outer div and hide it
document.querySelectorAll('.outers').forEach(function(el) {
el.style.display = 'none';
});
//loop through outer ->card-title
document.querySelectorAll('.outers .card-title').forEach(function(el) {
//compare
if (el.textContent.toLowerCase().indexOf(inputs) > -1) {
el.closest('.outers').style.display = "block"; //if match show that div
}
})
})
.outers {
border: 1px solid blue;
width: 150px;
height: 150px;
margin-bottom: 5px
}
<input id="search_here" class="mb-2 form-control" placeholder="Type to search...">
<div id="box" class='row card-group'>
<!--just added one extra class-->
<div class="col-4 mb-3 outers">
<div class="card h-100">
<a href="{{item.get_absolute_url}}">
<img src="{{ item.image.url }}" class="card-img-top" alt="..." />
</a>
<div class="card-body">
<h5 class="card-title">Somethings</h5>
<p class="card-text">
some things
</p>
</div>
<div class="card-footer">
<small class="text-muted">12:30:00</small>
</div>
</div>
</div>
<div class="col-4 mb-3 outers">
<div class="card h-100">
<a href="{{item.get_absolute_url}}">
<img src="{{ item.image.url }}" class="card-img-top" alt="..." />
</a>
<div class="card-body">
<h5 class="card-title">Abc</h5>
<p class="card-text">
some things
</p>
</div>
<div class="card-footer">
<small class="text-muted">12:30:00</small>
</div>
</div>
</div>
<div class="col-4 mb-3 outers">
<div class="card h-100">
<a href="{{item.get_absolute_url}}">
<img src="{{ item.image.url }}" class="card-img-top" alt="..." />
</a>
<div class="card-body">
<h5 class="card-title">def</h5>
<p class="card-text">
some things
</p>
</div>
<div class="card-footer">
<small class="text-muted">12:30:00</small>
</div>
</div>
</div>
</div>