I have a page that I'm making with Bootstrap
and AngularJS
for the front-end and I dynamically generate multiple accordions on the same page with a ng-repeat
. The problem is that when I click on the names of the tabs to enlarge them, the title of the tab is hidden and the content is shown... that is, it doesn't work as it should, and I have another code that is the same and it works... I don't understand why that behavior. I leave the html that I am using and the AngularJS filter (Angular 1) that I use just in case...
products.html:
<!DOCTYPE html>
<html lang="es" ng-app="tangoInfinito">
<head>
<meta charset="UTF-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1">
<title>Tango Infinito - Productos</title>
<link rel="stylesheet" href="css/bootstrap.min.css">
<link rel="stylesheet" href="css/font-awesome.min.css">
<link rel="stylesheet" href="css/estilos.css">
<link rel="stylesheet" href="css/bootstrap-social.css">
<link href="https://fonts.googleapis.com/css?family=Roboto+Condensed" rel="stylesheet">
<link href="https://fonts.googleapis.com/css?family=Play:400,700" rel="stylesheet">
<link rel="icon" type="image/png" href="favicon32x32.png">
<link rel="shortcut icon" type="image/x-icon" href="favicon32x32.ico">
<script src="js/angular.min.js"></script>
<script src="js/angular-route.min.js"></script>
<script src="js/angular-resource.min.js"></script>
<script src="js/app.js"></script>
<script src="js/Controllers/ProductosController.js"></script>
<script src="js/Services/ProductosService.js"></script>
<script src="js/Filters/IdFilter.js"></script>
<!-- HTML5 shim and Respond.js for IE8 support of HTML5 elements and media queries -->
<!-- WARNING: Respond.js doesn't work if you view the page via file:// -->
<!--[if lt IE 9]>
<script src="https://oss.maxcdn.com/html5shiv/3.7.2/html5shiv.min.js"></script>
<script src="https://oss.maxcdn.com/respond/1.4.2/respond.min.js"></script>
<![endif]-->
</head>
<body ng-controller="ProductosController">
<nav class="navbar" role="navigation">
<div class="container">
<div class="navbar-header">
<button type="button" data-toggle="collapse" data-target="#navbar" aria-expanded="false" aria-controls="navbar" class="navbar-toggle collapsed">
<span class="sr-only">Toggle navigation</span>
<span class="icon-bar"></span>
<span class="icon-bar"></span>
<span class="icon-bar"></span>
</button>
<div class="col-xs-2 col-sm-3">
<a id="link-logo" class="navbar-brand" href="index.html"><img class="img-responsive" src="logos/logo.png"></a>
</div>
<div class="col-xs-6 col-sm-9">
<h1><a href="index.html"><span id="titulo-logo-1">TANGO INFINITO</span><span id="titulo-logo-2">.com.ar</span></a></h1>
</div>
</div>
<div id="navbar" class="navbar-collapse collapse">
<ul class="nav navbar-nav navbar-right">
<li class="active"><a href="index.html"><span class="glyphicon glyphicon-home" aria-hidden="true"></span> Inicio</a></li>
<li><a href="http://web.facebook.com/orquestatipicalayumba" target="_blank"><span class="glyphicon glyphicon-info-sign" aria-hidden="true"></span> Notitango</a></li>
<li class="dropdown">
<a href="#" class="dropdown-toggle" data-toggle="dropdown" role="button" aria-haspopup="true" aria-expanded="false"><span class="glyphicon glyphicon-list-alt"></span> Productos<span class="caret"></span></a>
<ul class="dropdown-menu">
<!-- Contenido generado dinámicamente -->
</ul>
</li>
<li><a href="index.html#contact-form"><i class="fa fa-envelope-o"></i> Contacto</a></li>
</ul>
</div>
</div>
</nav>
<!-- Contenido -->
<div id="main-content" style="padding-top: 80px; font-family: 'Play', sans-serif;">
<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" id="{{prod.nombre | IdFilter}}" ng-repeat="prod in productos | filter: {tipo: t.tipo}">
<p style="padding-top: 10px;">{{prod.resenia}}</p>
<h4>INTEGRANTES:</h4>
<!-- Accordion -->
<div id="{{accordionId(prod.nombre)}}" class="panel-group" role="tablist" aria-multiselectable="true">
<div ng-repeat="integrante in prod.integrantes" class="panel panel-default">
<div class="panel-heading" role="tab" id="heading-{{integrante.nombre | IdFilter}}">
<h3 class="panel-title">
<a role="button" data-toggle="collapse" data-parent="#{{accordionId(prod.nombre)}}" href="#{{integrante.nombre | IdFilter}}" aria-expanded="true" aria-controls="{{integrante.nombre | IdFilter}}">{{integrante.nombre}} {{integrante.apellido}}</a>
</h3>
</div>
<div role="tabpanel" aria-labelledby="heading-{{integrante.nombre | IdFilter}}" id="{{integrante.nombre | IdFilter}}" class="panel-collapse collapse">
<div class="panel-body">
<p>{{integrante.resenia}}</p>
</div>
</div>
</div>
</div> <!-- Fin Accordion -->
</div>
</div>
</div>
</div>
</div>
</div>
</div>
<footer class="row-footer">
<div class="container">
<div class="row">
<div class="col-xs-6 col-sm-5">
<h5 style="font-weight: bolder;">Contacto</h5>
<address>
<i class="fa fa-phone"></i>: +54 9 343-5064897<br>
<i class="fa fa-envelope"></i>: <a href="mailto:[email protected]">[email protected]</a>
</address>
</div>
<div id="social-icons" class="col-xs-6 col-sm-3 col-sm-push-4">
<div class="nav navbar-nav" style="padding: 10px 10px;">
<a class="btn btn-social-icon btn-facebbok" href="http://www.facebook.com/orquestatipicalayumba/?ref=bookmarks" target="_blank"><i class="fa fa-facebook"></i></a>
<a class="btn btn-social-icon btn-twitter" href="http://twitter.com/PetruccelliFac2" target="_blank"><i class="fa fa-twitter"></i></a>
<a class="btn btn-social-icon btn-youtube" href="https://www.youtube.com/channel/UCDz466X5LlESY5SJ_tlLmjA" target="_blank"><i class="fa fa-youtube"></i></a>
<a class="btn btn-social-icon" href="mailto:[email protected]"><i class="fa fa-envelope-o"></i></a>
</div>
</div>
<div class="col-xs-12">
<p style="text-align: center; font-weight: bolder;">© Copyright 2016 Tango Infinito</p>
</div>
</div>
</div>
</footer>
<script src="js/jquery-3.1.1.min.js"></script>
<script src="js/bootstrap.min.js"></script>
<script src="js/carousel.js"></script>
<script src="js/send-email.js"></script>
<script src="js/appear-navbar-productos.js"></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><a href="#tipo">Tipo</a></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");
$(".tab-content div:first-child")
.addClass("in active");
};
var id = setInterval(checkVariable, 250);
});
</script>
</body>
</html>
ProductsController.js:
(function(){
var module = angular.module("tangoInfinito");
var ProductosController = function($scope, ProductosService) {
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 = 1;
$scope.accordionId = function(prodNombre) {
if(!idAsignado(listaIdAccordions, prodNombre)) {
var accId = "accordion" + accordionNumber;
accordionNumber++;
listaIdAccordions.push({
producto: prodNombre,
id: accId
});
//console.log(listaIdAccordions);
//console.log("Nuevo id asignado");
return accId;
}
else {
var largo = listaIdAccordions.length;
for(var i = 0; i < largo; i++) {
if(listaIdAccordions[i].producto === prodNombre) {
//console.log(listaIdAccordions);
//console.log("Id devuelto");
return listaIdAccordions[i].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) {
//Lista para armar el menu desplegable (menu productos) de la barra de navegación
//Esta lista es tomada por index.html y productos.html
//(en un script al final de la página) para armar el menu dinamicamente
$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'm talking about:
EDIT: I was seeing that for some reason when I click on a title, the class panel-heading
is added to the div that has the class collapse
, but not the in
, so the property display
becomes none
, and a style="height: 20px;"
, which I assume must be be through JavaScript
, since at the beginning the element does not have it. But I can't figure out where these changes come from...
To make a div (in this case a tab) have unique hidden content they must have something in common. What I mean is that if you
producto
haveintegrantes
these theyintegrantes
have to have something in common with that product.Create the following example:
As you can see, each product has its own arrangement of members.
Also create a function called
$scope.mostrarHijos
and a$scope.isHijoShow
In the visual part simply:
I leave you a codepen of this code working codepen
Well, I found the reason for the error... The reason is a script that I made at the bottom of the page to make the dropdown-list of the navigation bar and to put the classes
active in
to the first tabs of each item but it turns out that it also add the classesactive in
to the div with the classpanel-heading
causing the plugin to behave wrongly. The solution was to remove the classesactive-in
from the div with the class withpanel-heading
the . I leave the solution:removeClass
jQuery