card rendering function fails only after clicking on pagination button - javascript

I'm trying to figure out why my function that renders bootstrap 5 cards fails but only after first clicking a pagination button then selecting a drop down menu option. The pagination buttons work fine it seems and the dropdown menu also works fine but only if a pagination button is never clicked.
The problem seems to be in my displayList() function. After clicking a pagination button and clicking a dropdown option the correct array is passed into displayList() but let paginatedItems = items.slice(start, end); returns an empty array. Any help at all would be greatly appreciated.
I've my stripped down code so that hopefully it's easier to read and understand:
const setPosters = [{id:'1',img:'libs/images/pdfFile.jpg',title:'Virus Treatments',author:'Sam Smith',category:'treatments'},{id:'2',img:'libs/images/pdfFile.jpg',title:'Treatments',author:'Dave Smith',category:'illness'},{id:'3',img:'libs/images/pdfFile.jpg',title:'Pain',author:'Sam Smith',category:'illness'},{id:'4',img:'libs/images/pdfFile.jpg',title:'Virus Treatments',author:'Bob Burke',category:'illness'},{id:'5',img:'libs/images/pdfFile.jpg',title:'Pain Treatments',author:'James Frank',category:'cures'},{id:'6',img:'libs/images/pdfFile.jpg',title:'Sinus Treatments',author:'Ted Reed',category:'illness'},{id:'7',img:'libs/images/pdfFile.jpg',title:'Migrain Treatments',author:'Ted Reed',category:'remedy'},{id:'8',img:'libs/images/pdfFile.jpg',title:'Flu Treatments',author:'Ted Reed',category:'remedy'},{id:'9',img:'libs/images/pdfFile.jpg',title:'Virus Treatments',author:'James Frank',category:'remedy'},{id:'10',img:'libs/images/pdfFile.jpg',title:'Flu Treatments',author:'Ralph Barnes ',category:'remedy'},{id:'11',img:'libs/images/pdfFile.jpg',title:'Virus Treatments',author:'Thomas Smith',category:'cures'},{id:'12',img:'libs/images/pdfFile.jpg',title:'Pain Treatments',author:'Ralph Barnes',category:'remedy'},{id:'13',img:'libs/images/pdfFile.jpg',title:'Virus Treatments',author:'Sam Smith',category:'treatments'},{id:'14',img:'libs/images/pdfFile.jpg',title:'Treatments',author:'Dave Smith',category:'illness'},{id:'15',img:'libs/images/pdfFile.jpg',title:'Pain',author:'Sam Smith',category:'illness'},]
// this continues for a total of about 80 cards in my local version
let posters;
const cardElement = $('#cards');
const paginationElement = $('#pagination');
let currentPage = 1;
let rows = 10;
let page_count;
///////////\\\\\\\\\\\
// **** Functions ***\\
//////////\\\\\\\\\\\\\\
function displayList(items, wrapper, rows_per_page, page) {
wrapper.html("");
page--;
console.log('displayList', items);
let start = rows_per_page * page;
let end = start + rows_per_page;
let paginatedItems = items.slice(start, end);
console.log('paginatedItems:', paginatedItems);
for (let i = 0; i < paginatedItems.length; i++) {
wrapper.append(`
<div class="col gx-2">
<div class="card">
<img
src=${paginatedItems[i].img}
class="card-img-top"
alt="..."
/>
<div class="card-body p-1">
</div>
<div class="card-footer">
Title: ${paginatedItems[i].title}
Category: <strong>${paginatedItems[i].category}</strong><br>
Author: ${paginatedItems[i].author}<br>
id: ${paginatedItems[i].id}<br>
</div>
</div>
</div>
`)
};
};
function setupPagination(items, wrapper, rows_per_page) {
wrapper.html("");
page_count = Math.ceil(items.length / rows_per_page) + 1;
for (let i = 1; i < page_count; i++) {
wrapper.append(`<li class="page-item"><a class="page-link" href="#">${i}</a></li>`);
};
};
/////////////////////\\\\\\\\\\\\\\\\\\\\
// **** Posters By Category Dropdown ***\\
////////////////////\\\\\\\\\\\\\\\\\\\\\\
//Adds Categories to Dropdown Select Options
uniqCatergoriesArray = uniqCatergories(setPosters, it => it.category);
function uniqCatergories(data, key) {
return [...new Map(data.map(x => [key(x), x])).values()]
}
for (var i = 0; i < uniqCatergoriesArray.length; i++) {
$('#selPosterCat').append($('<option>', {
value: uniqCatergoriesArray[i].category,
text: uniqCatergoriesArray[i].category,
}));
}
//Displays Posters By Category
$('#selPosterCat').on('change', function() {
console.log($('#selPosterCat').val());
$('#textSearchResult').html('&nbsp');
$('#inlineFormInput').val('');
if ($('#selPosterCat').val() === 'all') {
posters = setPosters.filter(item => item);
displayList(posters, cardElement, rows, currentPage);
setupPagination(posters, paginationElement, rows);
} else {
posters = setPosters.filter(item => item.category === $('#selPosterCat').val());
console.log('dropdown', posters);
displayList(posters, cardElement, rows, currentPage);
setupPagination(posters, paginationElement, rows);
}
});
/////////////////\\\\\\\\\\\\\
// **** Pagination Click ***\\
/////////////////\\\\\\\\\\\\\\
$(document).on("click", "ul.pagination li a:not(.static)", function(e) {
currentPage = parseInt($(this).text());
posters = setPosters.filter(item => item);
displayList(posters, cardElement, rows, currentPage);
});
posters = setPosters.filter(item => item)
displayList(posters, cardElement, rows, currentPage);
setupPagination(posters, paginationElement, rows);
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<!-- *** Main Content Container *** -->
<div class="container-fluid" id="mainContainer">
<div id="mainCardContainer">
<!-- *** Search Bar *** -->
<div class="container-fluid">
<div class="row">
<div class="col">
<form id="form-id">
<div class="mb-3 d-flex justify-content-center" style="margin-top: 5vh;">
<select id="selPosterCat" class="form-select-sm w-25" aria-label="Default select example" style="border-right: none; border-width: 1px; height: 2rem;">
<option value="all" selected>All Categories</option>
<!-- other options added here by javaScript -->
</select>
</div>
</form>
</div>
</div>
<div class="row row-cols-1 row-cols-lg-5 row-cols-sm-2 g-4" id="cards">
<!-- individual cards added here by javaScript -->
</div>
<!-- *** Pagination Bar *** -->
<div class="container-fluid mt-3 pe-0 me-0">
<nav aria-label="Page navigation example">
<ul class="pagination justify-content-end">
<li class="page-item" id="previousBtn">
<a class="page-link static" href="#" tabindex="-1" aria-disabled="true" id="">Previous</a>
</li>
<div class="d-flex" id="pagination">
<!-- page numbers added here by javaScript -->
</div>
<li class="page-item" id="nextBtn">
<a class="page-link static" id="" href="#">Next</a>
</li>
</ul>
</nav>
</div>

Just change this code:
item => item.category === $('#selPosterCat').val()
With this:
item => item.category = $('#selPosterCat').val()
and be sure from adding these links respectively:
https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js
https://cdn.jsdelivr.net/npm/bootstrap#5.0.1/dist/css/bootstrap.min.css
https://cdn.jsdelivr.net/npm/bootstrap#5.0.1/dist/js/bootstrap.bundle.min.js
http://jsfiddle.net/rewan_95/107zxr3g is the fiddle I tested on.
Note: don't forget to add the above links for testing on jsfiddle

Related

javascript in django template not working

I'm new in Django, im create product page in Django in product card i add increment decrement add to cart button, but add to cart button work on first product card so,what can i do?
I'm added add to card increment and decrement button using JavaScript why JavaScript only apply on one card product in Django. so, how to resolve when ever i use looping in Django my JavaScript not working or shown in console btn varriable already declared.
{% for i in productskey %}
<div class="col-sm-4">
<div class="product-image-wrapper" style="border:1px solid #ddd ;">
<div class="single-products">
<div class="productinfo text-center">
<a href="{% url 'prodetail' i.id %}">
<img src=" {{i.productImage.url}} " alt="" style="width:255px; height:255px"/>
</a>
<h2>₹{{i.productPrice}}</h2>
<p>{{i.productName}}</p>
<div class="btn">
<button class="mainusbtn">-</button>
<button class="mainbtn" class="btn btn-default" class="fa fa-shopping-cart">ADD TO CART</button>
<button class="plusbtn">+</button>
</div>
<!-- <i class="fa fa-shopping-cart"></i>Add to cart -->
</div>
<!-- <div class="product-overlay">
<div class="overlay-content">
<h2>$56</h2>
<p>Easy Polo Black Edition</p>
<i class="fa fa-shopping-cart"></i>Add to cart
</div>
</div> -->
</div>
<!-- <div class="choose">
<ul class="nav nav-pills nav-justified">
<li><i class="fa fa-plus-square"></i>Add to wishlist</li>
<li><i class="fa fa-plus-square"></i>Add to compare</li>
</ul>
</div> -->
</div>
<!-- </a> -->
</div>
<script>
let btn = document.querySelector('.mainbtn');
let pbtn = document.querySelector('.plusbtn');
let mbtn = document.querySelector('.mainusbtn');
btn.addEventListener("click", () => {
if (btn.innerText == 'ADD TO CART') {
btn.innerText = 1;
pbtn.style.display = 'inline-block';
mbtn.style.display = 'inline-block';
}
})
mbtn.addEventListener("click", () => {
if (btn.innerText == 5) {
pbtn.style.display = 'inline-block';
}
if (btn.innerText < 2) {
btn.innerText = 'ADD TO CART';
pbtn.style.display = 'none';
mbtn.style.display = 'none';
} else {
btn.innerText = btn.innerText - 1;
}
})
pbtn.addEventListener("click", () => {
btn.innerText = +(btn.innerText) + +1;
// if(btn.innerText == 5){
// pbtn.style.display = 'none';
// }
})
</script>

Updating module on instant change when list is updated

Sorry for the long post, but I tried explaining things in as much detail as possible.
So as I dive deeper into JavaScript and start learning more and more about AJAX requests and other components, I've stumbled across something that I can't seem to figure out.
So below, I will explain what I'm doing and what I would like to do, and see if someone has some guidance for me.
So here is my Vue.js app:
new Vue({
name: 'o365-edit-modal',
el: '#o365-modal-edit',
data: function() {
return {
list: {},
}
},
created() {
this.fetchApplicationsMenu();
},
methods: {
fetchApplicationsMenu() {
var self = this;
wp.apiRequest( {
path: 'fh/v1/menus/applications',
method: 'GET',
}).then(menu => self.list = menu.data);
},
changed() {
const selected = this.$data.list.selected;
function get_ids(list, field) {
const output = [];
for (let i=0; i < list.length ; ++i)
output.push(list[i][field]);
return output;
}
const result = get_ids(selected, "id");
wp.apiRequest( {
path: 'fh/v1/menus/applications',
method: 'PUT',
data: {
ids: result,
},
}).then((post) => {
return post;
},
(error) => {
console.log(error);
});
},
add(x) {
this.$data.list.selected.push(...this.$data.list.available.splice(x, 1));
this.changed();
},
remove(x) {
this.$data.list.available.push(...this.$data.list.selected.splice(x, 1));
this.changed();
},
},
});
Then here is the HTML portion that I'm using to render the two columns:
<div class="column is-half-desktop is-full-mobile buttons">
<nav class="level is-mobile mb-0">
<div class="level-left">
<div class="level-item is-size-5 has-text-left">Selected</div>
</div>
<div class="level-right">
<div class="level-item">
<i class="fas fa-sort-alpha-up is-clickable"></i>
</div>
</div>
</nav>
<hr class="mt-1 mb-3">
<draggable class="list-group"
v-model="list.selected"
v-bind="dragOptions"
:list="list.selected"
:move="onMove"
#change="changed">
<button class="button is-fullwidth is-flex list-group-item o365_app_handle level is-mobile" v-for="(app, index) in list.selected" :key="app.id">
<div class="level-left">
<span class="icon" aria-hidden="true">
<img :src="app.icon_url" />
</span>
<span>{{app.name}}</span>
</div>
<div class="level-right">
<span class="icon has-text-danger is-clickable" #click="remove(index)">
<i class="fas fa-times"></i>
</span>
</div>
</button>
</draggable>
</div>
<div class="column is-half-desktop is-full-mobile buttons">
<div class="is-size-5 has-text-left">Available</div>
<hr class="mt-1 mb-3">
<draggable class="list-group"
v-model="list.available"
v-bind="dragOptions"
:list="list.available"
:move="onMove">
<button class="button is-fullwidth is-flex list-group-item o365_app_handle level is-mobile" v-for="(app, index) in list.available" :key="app.id">
<div class="level-left">
<span class="icon" aria-hidden="true">
<img :src="app.icon_url" />
</span>
<span>{{app.name}}</span>
</div>
<div class="level-right">
<span class="icon has-text-primary is-clickable" #click="add(index)">
<i class="fas fa-plus"></i>
</span>
</div>
</button>
</draggable>
</div>
That outputs the following items, and all works great. See the video display below of each component working as needed. This all works great! I'm calling the changed() method on add and remove which grabs all the IDs and stores them in the DB via an endpoint.
The Problem:
Now I have the following dropdown menu, which depends on the fh/v1/menus/applications endpoint to pull in all the items as shown below:
As you can see below, when I open the dropdown, it has three apps, when I open the cog wheel and remove one of the apps and it saves it but the dropdown doesn't get automatically updated, I have to refresh the page and then I will see the updates.
Does anyone know how to fetch the new items without a refresh?
Here is the HTML and the JS for the dropdown piece:
HTML: As you can see in there, I have data-source="applications" which pulls in the items inside the init_menu as shown in the JS.
<div class="dropdown-menu" id="dropdown-o365" role="menu">
<div class="dropdown-content">
<div class="container is-fluid px-4 pb-4">
<?php if ($application = Applications::init()): ?>
<div class="columns">
<div class="dropdown-item column is-full has-text-centered is-size-6">
<div class="level is-mobile">
<div class="level-left">
<?= $application->get_name() ?>
</div>
<div class="level-right">
<a class="navbar-item modal-element icon" id="o365-apps-cogwheel" data-target="o365-modal-edit" aria-haspopup="true">
<i class="fa fa-cog"></i>
</a>
</div>
</div>
</div>
</div>
<div class="columns is-multiline" data-source="applications"></div>
<?php else: ?>
<div class="columns">
<div class="column is-full">
No applications present.
</div>
</div>
<?php endif; ?>
</div>
</div>
</div>
Then here is the JavaScript. I initilize the method inside DOMContentLoaded using init_menu('applications');:
function init_menu(paths)
{
paths.forEach(path => {
const target = document.querySelector('[data-source=' + path + ']');
if (target) {
wp.api.loadPromise.done(function () {
const Menus = wp.api.models.Post.extend({
url: wpApiSettings.root + 'fh/v1/menus/' + path,
});
const menus = new Menus();
menus.fetch().then(posts => {
// This returns the data object.
const data = posts.data;
let post_list;
// Check if it's an array and see if selected is empty otherwise show available.
if (Array.isArray(data.selected) && data.selected.length !== 0) {
post_list = data.selected;
} else {
post_list = data.available;
}
post_list.forEach(function (post) {
switch(path) {
case 'applications':
target.appendChild(create_apps_dom_tree(post));
break;
default:
console.log('Path route is invalid.');
break;
}
})
})
})
}
});
}
function create_apps_dom_tree(post) {
const {
icon_url,
url,
name,
} = post
const container = document.createElement('div');
container.className = 'column is-one-third is-flex py-0';
const anchor = document.createElement('a');
anchor.href = url;
anchor.className = 'dropdown-item px-2 is-flex is-align-items-center';
const figure = document.createElement('figure');
figure.className = 'image is-32x32 is-flex';
const img = document.createElement('img');
img.src = icon_url;
const span = document.createElement('span');
span.className = 'pl-2';
span.textContent = name;
figure.appendChild(img);
anchor.append(figure, span);
container.appendChild(anchor);
return container;
}
If anyone has some guidance or an answer on how to pull in live data from the database on the fly, that would be amazing.
Basically, I need my data-source: to automatically grab the items when my vue/db request is sent so I don't have to refresh the page.
Inside my Vue app, I have the following method:
fetchApplicationsMenu() {
var self = this;
wp.apiRequest( {
path: 'fh/v1/menus/applications',
method: 'GET',
}).then(menu => self.list = menu.data);
},
which calls a GET request and then stores the data inside the return { list: {} }.
A quick fix might be to just invoke init_menu() from the component's beforeDestroy() hook, called when the dialog closes. You might choose to do it from changed() instead if the dropdown is still accessible with this dialog open.
new Vue({
// option 1:
beforeDestroy() {
init_menu('applications');
},
// option 2:
methods: {
changed() {
init_menu('applications');
}
}
})
Alternative: You already know what the final application list is in changed(), so you could update the dropdown with the new list from that method.
function update_menu(path, post_list) {
const target = document.querySelector('[data-source=' + path + ']');
// remove all existing children
Array.from(target.childNodes).forEach(x => x.remove());
post_list.forEach(post => target.appendChild(create_apps_dom_tree(post)))
}
new Vue({
methods: {
changed() {
update_menu('applications', this.$data.available);
}
}
})

Items in an array disappear mysteriously

So I'm currently doing a Calorie Counter project that consists on giving the user the option to firstly, add items with the respective name and number of calories, remove items or update them when clicking on an edit icon next to the item, and finally removing all items at once.
The UI will basically display all the items that the user has added (including the name and the number of calories), where each item will have an edit icon next to it, and if the icon is clicked, it will give the user the option to edit them and delete them.
I still haven't gotten to the edit part because I'm currently stuck in the delete part.
Let's say I have 3 items in the list, when I click on the edit button and then delete, everything works out fine, the html element is deleted and it looks good. If I repeat the process one more time it still works, but when I repeat the process one last time, the problem happens.
For some reason, when I hit the edit button nothing happens, I've checked and apparently the item array is completely empty, even though I only deleted 2 out of the 3 items.
I've tried everything and I've been completely stuck for 3 days straight.
// Item Controller
const ItemController = function() {
// Hard coded items
data = [{
name: "Hamburguer",
id: 0,
calories: 1000
},
{
name: "Pasta",
id: 1,
calories: 700
},
{
name: "Apple",
id: 2,
calories: 70
}
]
return {
getItems: function() {
return data;
},
deleteAllItems: function() {
data.items = [];
UIController().clearItems();
},
getTotalCalories: function() {
totalCalories = 0;
this.getItems().forEach(item => {
totalCalories += parseInt(item.calories)
});
UIController().changeToTotalCalories(totalCalories);
},
removeSingleItem: function(item, li) {
// Getting the index of the item
indexItem = items.getItems().indexOf(item);
// Deleting item from array
items.getItems().splice(indexItem, 1);
// Deleting li item from UI
li.remove();
console.log(items.getItems());
}
}
};
const items = ItemController();
// UI controller
const UIController = function() {
return {
displayItems: function(itemsPresented) {
itemsPresented.forEach(function(item) {
itemList = document.getElementById("item-list");
itemList.innerHTML += `
<li class="collection-item" id="${item.id}">
<strong>${item.name}: </strong><em>${item.calories} calories</em>
<a href="#" class="secondary-content">
<i class="edit-item fa fa-pencil">
</i>
</a>
</li>
`;
})
},
clearItems: function() {
itemList = document.getElementById("item-list");
itemList.innerHTML = "";
items.getTotalCalories();
},
changeToTotalCalories: function(totalCalories) {
document.querySelector(".total-calories").textContent = totalCalories;
},
}
}
const uiCtrl = UIController();
// So when the page loads, the hard coded items can be represented
uiCtrl.displayItems(items.getItems());
// To delete all the items at once
clearAllBtn = document.querySelector(".clear-btn");
clearAllBtn.addEventListener("click", (e) => {
items.deleteItems();
e.preventDefault();
})
// Getting the li element (The one that has all the hard-coded items)
itemList = document.getElementById("item-list");
itemList.addEventListener("click", e => {
// Checking if the user is clicking the Edit Icon
if (e.target.classList.contains("edit-item")) {
items.getItems().forEach(item => {
li = e.target.parentElement.parentElement;
// Getting the item that has the edit icon that the user clicked
if (item.id === parseInt(e.target.parentElement.parentElement.id)) {
// Putting the name and the calories of the item that is being edited in the input fields
document.getElementById("item-name").value = item.name;
document.getElementById("item-calories").value = item.calories;
// Changing the buttons so when the user edits an item, they have the options Update and Delete
document.querySelector(".add-btn").style.display = "none";
document.querySelector(".update-btn").style.display = "block";
document.querySelector(".delete-btn").style.display = "block";
document.querySelector(".back-btn").style.display = "none";
// If the user clicks the delete button
document.querySelector(".delete-btn").addEventListener("click", e => {
// Changing all the buttons back to normal
document.querySelector(".add-btn").style.display = "block";
document.querySelector(".update-btn").style.display = "none";
document.querySelector(".delete-btn").style.display = "none";
document.querySelector(".back-btn").style.display = "block";
// Clearing out the input fields
document.getElementById("item-name").value = "";
document.getElementById("item-calories").value = "";
// Deleting item
items.removeSingleItem(item, li);
// Updating the calories
items.getTotalCalories();
e.preventDefault();
});
}
});
}
})
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/materialize/1.0.0/css/materialize.min.css">
<link href="https://stackpath.bootstrapcdn.com/font-awesome/4.7.0/css/font-awesome.min.css" rel="stylesheet" integrity="sha384-wvfXpqpZZVQGK6TAh5PVlGOfQNHSoD2xbE+QkPxCAFlNEevoEH3Sl0sibVcOQVnN" crossorigin="anonymous">
<script src="https://code.jquery.com/jquery-3.5.1.min.js" integrity="sha256-9/aliU8dGd2tb6OSsuzixeV4y/faTqgFtohetphbbj0=" crossorigin="anonymous"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/materialize/1.0.0/js/materialize.min.js"></script>
<nav>
<div class="nav-wrapper blue">
<div class="container">
<a href="#" class="brand-logo center">
Tracalorie
</a>
<ul class="right">
<li>
<a href="#" class="clear-btn btn blue lighten-3">
Clear All
</a>
</li>
</ul>
</div>
</div>
</nav>
<br>
<div class="container">
<!-- Form Card -->
<div class="card">
<div class="card-content">
<span class="card-title">
Add Meal / Food Item
</span>
<form class="col">
<div class="row">
<div class="input-field col s6">
<input type="text" id="item-name" placeholder="Add item">
<label for="item-name">Meal</label>
</div>
<div class="input-field col s6">
<input type="text" id="item-calories" placeholder="Add calories">
<label for="item-calories">Calories</label>
</div>
<button class="add-btn btn blue darken-3"><i class="fa fa-plus"></i>
Add Meal</button>
<button style="display: none;" class="update-btn btn orange" display=><i class="fa fa-pencil-square-o"></i>
Update Meal</button>
<button style="display: none;" class="delete-btn btn red"><i class="fa fa-remove"></i>
Delete Meal</button>
<button class="back-btn btn grey pull-right"><i class="fa fa-chevron-circle-left"></i>
Back</button>
</div>
</form>
</div>
</div>
<!-- Calorie Count -->
<h3 class="center-align">Total Calories: <span class="total-calories">
0
</span></h3>
<!-- Item list -->
<ul id="item-list" class="collection">
</ul>
</div>
It seems like you add an eventListener to the delete button every single time a user clicks on the edit pencil. You never remove these eventListeners. So when the first edit is done, there is one delete event and one items gets deleted. The next time a user clicks on the edit button, a second event gets added to the same html element, thus two items gets deleted (both events will trigger one after the other). This becomes apparent when your hardcoded list would contain 10 items, you would see 1,2,3 and lastly 4 items disappear. I suggest you look into resetting/removing eventlisteners.

angular 8 - Error trying to diff '[object Object]'. Only arrays and iterables are allowed

I want to display search results, but whenever i am trying to type anything to search box it shows error in console. i am fetching data from api and according to type i am displaying results in tabs.
data is getting filtered according to nav-tabs type.
but now i want to search listed data,
so whenever i am trying to search is shows error
TS -
searchKeywords: string;
CoffeeItemList: any = [];
// tslint:disable-next-line:max-line-length
constructor(private getDataListingService: DataListingService){}
ngOnInit() {
this.getGlobalSearchList('');
}
getGlobalSearchList(type: string) {
this.CoffeeItemList = [];
this.getDataListingService.getAllDataLists().subscribe(value => {
let data = [];
data = value.data;
console.log(data);
for (let i = 0; i < data.length - 1; i++) {
if (data[i].type === type) {
this.CoffeeItemList.push(data[i]);
}
}
});
}
getSmartSearchValues(search: string) {
if (search === '' ) {
this.getGlobalSearchList('');
return false;
}
this.getDataListingService.searchList(search).subscribe((data: any) => {
this.CoffeeItemList = data;
});
HTML
<div class="container">
<div class="mt-4">
<input class="form-control" type="text" [(ngModel)]="searchKeywords" (keyup)="getSmartSearchValues(searchKeywords)" placeholder="Search here"/>
</div>
<br>
<!-- Nav tabs -->
<ul class="nav nav-tabs" role="tablist">
<li class="nav-item">
<a class="nav-link active" data-toggle="tab" href="#list" (click)="getGlobalSearchList('DancingGoatMvc-Coffee')">Coffee</a>
</li>
<li class="nav-item">
<a class="nav-link" data-toggle="tab" href="#list" (click)="getGlobalSearchList('DancingGoatMvc-Brewer')">Brewer</a>
</li>
</ul>
<!-- Tab panes -->
<div class="tab-content">
<div id="list" class="tab-pane container active in"><br>
<div class="row">
<div class="card col-3" *ngFor="let items of CoffeeItemList">
<div class="card-body">
<h5 class="card-title">{{items?.title }}</h5>
<img src="http://infogainpune.com{{items.image |slice:1}}" class="w-100"/>
<p class="card-text">{{items?.content}}</p>
<h4 class="card-text">${{items?.price}}</h4>
<h4 class="card-text">{{items?.type}}</h4>
</div>
</div>
</div>
</div>
</div>
</div>
The response of data
Try to change your code like this too see if it work for you
this.getDataListingService.getAllDataLists().subscribe(value => {
this.CoffeeItemList = value.data;
});
Let me know if you still have a problem.

Error with Bootstrap 3 Collapse

Well i have a page that shows products (entertaiment products) and a list of members of the products (a tango orchestra, or a dancing couple, for example). I want the info of the members to be displayed on accordions for each product. For example, if the "Tango Orchestra" have 3 members i want an accordion with 3 "tabs" to show those members, and the same for the rest of the products... I use AngularJS to generate dynamically the accordions and the id's of those accordions and the tabs associated to those accordions (i can't hardcode those id's because the list of products come from a database and i can't know how much products i will have) and the problem i have is that when i click a title tab it shows the content but hide the titles of all of the tabs, so i can't change tabs to see the others members info. I'll notice that for some reason a in class is beign added to my div with the panel-heading class and i don't know why.
I'll left you the html and js files im using:
productos.html (the part of the problem):
<!-- Contenido -->
<div id="main-content">
<div class="container">
<div class="row row-content" ng-repeat="r in rubros">
<h2 class="col-xs-12 col-lg-3 col-lg-push-5 rubro" id="{{r.rubro | lowercase}}" style="font-weight: 700;">{{r.rubro | uppercase}}</h2>
<div class="col-xs-12 wrapper" ng-repeat="t in tipos | filter: {rubro: r.rubro}">
<div class="row row-content">
<h3 id="{{t.tipo | lowercase}}" class="tipo">{{t.tipo | uppercase}}</h3>
<!-- Tabs -->
<ul class="nav nav-tabs">
<li ng-repeat="prod in productos | filter: {tipo: t.tipo}"><a data-toggle="tab" href="#{{prod.nombre | IdFilter}}">{{prod.nombre}}</a></li>
</ul>
<!-- Tabs Contenido -->
<div class="tab-content">
<div class="tab-pane fade row row-content" id="{{prod.nombre | IdFilter}}" ng-repeat="prod in productos | filter: {tipo: t.tipo}">
<!-- Videos -->
<div class="col-xs-12 col-sm-6 col-sm-push-6">
<h4>VIDEOS:</h4>
<iframe ng-repeat="video in prod.videos" ng-src="{{getIFrameSrc(video.link)}}" ng-show="prod.videos.length > 0" allowfullscreen></iframe>
<p ng-show="prod.videos.length == 0">No hay vídeos de este producto</p>
</div> <!-- Fin Videos -->
<h4 class="col-xs-12 col-sm-6 col-sm-pull-6">INTEGRANTES:</h4>
<!-- Accordion -->
<div id="accordion{{accordionId(prod.nombre)}}" class="panel-group col-xs-12 col-sm-6 col-sm-pull-6" role="tablist" aria-multiselectable="true">
<!-- Items -->
<div ng-repeat="integrante in prod.integrantes" class="panel panel-default">
<!-- Titulo del item -->
<div class="panel-heading" role="tab" id="heading-{{integrante.nombre | IdFilter}}{{accordionId(prod.nombre)}}">
<h3 class="panel-title">
<a class="collapsed" role="button" data-toggle="collapse" data-parent="#accordion{{accordionId(prod.nombre)}}" href="#{{integrante.nombre | IdFilter}}{{accordionId(prod.nombre)}}" aria-expanded="true" aria-controls="{{integrante.nombre | IdFilter}}">{{integrante.nombre}} {{integrante.apellido}}</a>
</h3>
</div> <!-- Fin Titulo -->
<!-- Contenido del item -->
<div id="{{integrante.nombre | IdFilter}}{{accordionId(prod.nombre)}}" class="panel-collapse collapse" aria-labelledby="heading-{{integrante.nombre | IdFilter}}{{accordionId(prod.nombre)}}" role="tabpanel">
<div class="panel-body">
<p>{{integrante.resenia}}</p>
</div>
</div> <!-- Fin Contenido -->
</div> <!-- Fin Item -->
</div> <!-- Fin Accordion -->
<p class="col-xs-12 col-sm-6" ng-class="{'col-sm-pull-6': prod.videos.length > 0}" style="padding-top: 10px;">{{prod.resenia}}</p>
</div>
</div>
</div>
</div>
</div>
</div>
</div>
ProductosController.js:
(function(){
var module = angular.module("tangoInfinito");
var ProductosController = function($scope, $sce, ProductosService) {
$scope.getIFrameSrc = function(link) {
return $sce.trustAsResourceUrl(link + "?controls=2");
};
function idAsignado(lista, producto) {
var listaLength = lista.length;
for (var i = 0; i < listaLength; i++) {
if (lista[i].producto === producto) {
return true;
}
}
return false;
};
var listaIdAccordions = [];
var accordionNumber = 0;
$scope.accordionId = function(prodNombre) {
if(!idAsignado(listaIdAccordions, prodNombre)) {
accordionNumber++;
listaIdAccordions.push({
producto: prodNombre,
id: ("accordion" + accordionNumber)
});
return accordionNumber;
}
else {
var largo = listaIdAccordions.length;
for(var i = 0; i < largo; i++) {
if(listaIdAccordions[i].producto === prodNombre) {
var temp = listaIdAccordions[i].id;
var id = temp.slice(temp.length - 1, temp.length);
return id;
}
}
}
};
var armarLista = function($rubros, $tipos) {
var lista = [];
var rubrosTemp = $rubros.slice(0);
var tiposTemp = $tipos.slice(0);
for(var i = 0; i < rubrosTemp.length; i++) {
var rubro = rubrosTemp[i].rubro.toUpperCase();
lista.push( {descripcion: rubro, isHeader: true} );
for(var j = 0; j < tiposTemp.length; j++) {
if(tiposTemp[j].rubro === rubrosTemp[i].rubro) {
lista.push( {descripcion: tiposTemp[j].tipo, isHeader: false} );
}
}
}
return lista;
};
var getDatosFromService = function() {
ProductosService.getDatos().success(function(response) {
$scope.navbarList = armarLista(response["rubros"], response["tipos"]);
$scope.productos = response["productos"];
$scope.rubros = response["rubros"];
$scope.tipos = response["tipos"];
});
}
getDatosFromService();
};
module.controller("ProductosController", ProductosController);
})();
IdFilter.js:
(function() {
var module = angular.module("tangoInfinito");
var IdFilter = function() {
return function(item) {
var id = "";
id = item.toLowerCase();
id = id.replace(/\s/g, "-");
return id;
};
};
module.filter("IdFilter", IdFilter);
})();
And the behavior i was talking about:
initial state
when i click on tabs titles
I would be very thankfull for any help that help me to debug or fix this error.
Thanks in advance.
Well i have found the answer... the incorrect behavior is because i have a script in the end of the page that add active in classes to the first div of the tabs section to get the first tab show but also add those classes to the div with the panel-heading class, and because of that the collapse script won't work fine... the solution i just found it just remove the class with the removeClass method from jQuery. Here is the code of the script:
<script>
$(document).ready(function() {
//Tomo el nodo al que luego le agrego li según correspondan
//<li class="dropdown-header">Rubro</li> Para los rubros
//<li>Tipo</li>
var lista = $("ul.dropdown-menu");
var navbarProductosLista = undefined;
//Chequea hasta que la variable navbarList de ProductosController esta asignada
function checkVariable() {
//Toma la variable navbarList del scope de ProductosController
//para agregar la lista de manera dinámica
navbarProductosLista = angular.element($("[ng-controller=ProductosController]")).scope().navbarList;
if(navbarProductosLista != undefined) {
for(var i = 0; i < navbarProductosLista.length; i++) {
if(navbarProductosLista[i].isHeader === true) {
var nodo = $("<li><a href='productos.html#" + navbarProductosLista[i].descripcion.toLowerCase() + "'>" + navbarProductosLista[i].descripcion + "</a></li>");
nodo.children().addClass("dropdown-header");
lista.append(nodo);
}
else {
var nodo = $("<li><a href='productos.html#" + navbarProductosLista[i].descripcion.toLowerCase() + "'>" + navbarProductosLista[i].descripcion + "</a></li>");
lista.append(nodo);
}
}
clearInterval(id);
}
$("ul li:first-child")
.addClass("active");
//This is the line that causes the problem
$(".tab-content div:first-child")
.addClass("in active");
//And this the line that fix it
$(".panel-heading")
.removeClass("in active");
};
var id = setInterval(checkVariable, 250);
});
</script>

Categories

Resources