2012-09-26 62 views
21

Estoy tratando de encontrar una manera de expandir y colapsar usando angular js. No he podido encontrar una forma elegante de hacerlo sin manipular objetos dom en el controlador (que no es la forma angular). Actualmente tengo una buena manera de hacerlo para expandir y colapsar una capa. Sin embargo, cuando empiezo a anidar, las cosas se vuelven complicadas y no funcionan del modo que yo quiero (expandir y colapsar varias áreas cuando no deberían). El problema viene cuando no sé cómo enviar un identificador único con un ng-click para expandir/contraer solo el contenido correcto. Debo mencionar que estos elementos están en una repetición ng, así que puedo personalizar necesariamente los parámetros que se envían.Expandir y contraer con js angular

Pude usar este jsfiddle para ayudarme a expandir y colapsar una capa para que funcione. Sin embargo, esta es una forma de alternar para hacerlo y quiero que el usuario pueda mantener las cosas expandidas mientras expande otras. Entonces, lo que hice para arreglar esto fue usar una matriz de y cada vez que se hace clic en algo, el índice del elemento en el que se hizo clic se agregaría a la matriz y la clase se expandiría. Cuando el usuario hizo clic de nuevo, el índice se eliminó de la matriz y el área se colapsó.

Otra forma en que descubrí que puedes hacerlo es mediante el uso de directivas. Pero no puedo encontrar ningún ejemplo para entender cómo funcionan las directivas. No estoy seguro de cómo comenzar cuando se trata de escribir directivas.

Mi configuración actual es la siguiente:

function Dexspander($scope) { 
    $scope.ExpandArray = []; 

    //Push or pop necessary elements for tracking 
    $scope.DespopulatArray = function (identifier, element) { 
    if (_.indexOf($scope.ExpandArray, identifier + element) != -1) { 
      $scope.ExpandArray.splice(_.indexOf($scope.ExpandArray, identifier + element), 1); 
     } else { 
      $scope.ExpandArray.push(identifier + element); 
     } 
    } 

    //Change class of necessary elements 
    $scope.Dexspand = function (identifier, element) { 
     if (_.indexOf($scope.ExpandArray, identifier + element) != -1) { 
      return "expand"; 
     } else { 
      return "collapse"; 
     } 
    } 
} 

<div class="user-header" ng-repeat="user in users"> 
    <h1 ng-click="DespopulatArray('user', $index)">Expand</h1> 
</div> 
<div class="user-content" ng:class="Dexspand('user', $index)"> 
    <div class="content"> 
     <div class="user-information"> 
      <div class="info-header"> 
       <h1 ng-click="DespopulatArray('info', $index)>Some Information</h1> 
      </div> 
      <div class="info-contents" ng:class="Dexspand('info', $index)"> 
       stuff stuff stuff stuff... 
      </div> 
     </div> 
    </div> 
</div> 

El problema con esta configuración es que si tengo que divs padres ampliado y los dos tienen algo debajo de ellos para ampliar, haga clic en el expanda texto se expandirá en Ambas áreas, ya que no son únicas.

+0

Podría poner un ejemplo de esto en plunker? Entonces podría ayudarte con una directiva. use esto como base: http://plnkr.co/edit/gist:3662656 –

Respuesta

14

Me surge el problema de no saber cómo enviar un identificador único con un ng-clic para expandir/contraer únicamente el contenido correcto.

Puede pasar $event con ng clic (ng-dblclick y eventos ñg- ratón), entonces se puede determinar qué elemento causó el evento:

<a ng-click="doSomething($event)">do something</a> 

controlador:

$scope.doSomething = function(ev) { 
    var element = ev.srcElement ? ev.srcElement : ev.target; 
    console.log(element, angular.element(element)) 
    ... 
} 

Ver también http://angular-ui.github.com/bootstrap/#/accordion

+0

Puede ser útil para alguien. Aquí hay un tutorial. http://www.aneejian.com/angular-js-custom-directive-expand-collapse/ – Ian

3

Acabo de escribir un simple zippy/colapsable usando Angular usando ng-show, ng-click y ng-init. Se implementa en un nivel, pero se puede ampliar a varios niveles fácilmente.

Asigne una variable booleana a ng-show y actívela al hacer clic en el encabezado.

Check it out here enter image description here

7

Ver http://angular-ui.github.io/bootstrap/#/collapse

function CollapseDemoCtrl($scope) { 
    $scope.isCollapsed = false; 
} 



<div ng-controller="CollapseDemoCtrl"> 
    <button class="btn" ng-click="isCollapsed = !isCollapsed">Toggle collapse</button> 
    <hr> 
    <div collapse="isCollapsed"> 
     <div class="well well-large">Some content</div> 
    </div> 
</div> 
26

Puede resolver este totalmente en el html:

<div> 
    <input ng-model=collapse type=checkbox>Title 
    <div ng-show=collapse> 
    Only shown when checkbox is clicked 
    </div> 
</div> 

Esto también funciona bien con ng-repetición, ya que se crea un alcance local para cada miembro.

<table> 
    <tbody ng-repeat='m in members'> 
    <tr> 
     <td><input type=checkbox ng-model=collapse></td> 
     <td>{{m.title}}</td> 
    </tr> 
    <tr ng-show=collapse> 
     <td> </td> 
     <td>{{ m.content }}</td> 
    </tr> 
    </tbody> 
</table> 

Tenga en cuenta que a pesar de que se repita tiene su propio ámbito, en un principio se heredará el valor del colapso de súper ámbitos. Esto le permite establecer el valor inicial en un lugar, pero puede ser sorprendente.

Por supuesto, puede restyle la casilla de verificación. Ver http://jsfiddle.net/azD5m/5/

violín Actualizado:http://jsfiddle.net/azD5m/374/ violín original utiliza el cierre </input> etiquetas para agregar la etiqueta de texto HTML en lugar de utilizar <label> etiquetas.

+0

¿por qué crees que hay directivas en todas partes para este tipo de cosas? poco curioso. – Sridhar

+0

@Sridhar ¿de qué directivas estás hablando? no entiendo la pregunta – Blauhirn

2

Aquí una solución simple y fácil en Angular JS usando ng-repeat que podría ayudar.

var app = angular.module('myapp', []); 
 

 
app.controller('MainCtrl', function($scope) { 
 

 
    $scope.arr= [ 
 
    {name:"Head1",desc:"Head1Desc"}, 
 
    {name:"Head2",desc:"Head2Desc"}, 
 
    {name:"Head3",desc:"Head3Desc"}, 
 
    {name:"Head4",desc:"Head4Desc"} 
 
    ]; 
 
    
 
    $scope.collapseIt = function(id){ 
 
     $scope.collapseId = ($scope.collapseId==id)?-1:id; 
 
    } 
 
});
/* Put your css in here */ 
 
li { 
 
    list-style:none; 
 
    padding:5px; 
 
    color:red; 
 
} 
 
div{ 
 
    padding:10px; 
 
    background:#ddd; 
 
}
<!DOCTYPE html> 
 
<html ng-app="myapp"> 
 
    <head> 
 
    <meta charset="utf-8" /> 
 
    <title>AngularJS Simple Collapse</title> 
 
    <script data-require="[email protected]" src="https://cdnjs.cloudflare.com/ajax/libs/angular.js/1.5.11/angular.min.js" data-semver="1.5.11"></script> 
 
</head> 
 
<body ng-controller="MainCtrl"> 
 
<ul> 
 
    <li ng-repeat='ret in arr track by $index'> 
 
    <div ng-click="collapseIt($index)">{{ret.name}}</div> 
 
    <div ng-if="collapseId==$index"> 
 
     {{ret.desc}} 
 
    </div> 
 
    </li> 
 
</ul> 
 
</body> 
 
</html>

Esto debe cumplir con sus requerimientos. Aquí hay un código de trabajo.

Plunkr Enlace http://plnkr.co/edit/n5DZxluYHi8FI3OmzFq2?p=preview

Github: https://github.com/deepakkoirala/SimpleAngularCollapse

0

en HTML

button ng-click="myMethod()">Videos</button> 

En angular

$scope.myMethod = function() { 
     $(".collapse").collapse('hide'); //if you want to hide 
     $(".collapse").collapse('toggle'); //if you want toggle 
     $(".collapse").collapse('show'); //if you want to show 
} 
Cuestiones relacionadas