¿Cómo puedo usar el $ index dentro de un ng-repeat para habilitar una clase y mostrar un DIV?

166

Tengo un conjunto de <li>elementos.

<ul>
  <li ng-class="{current: selected == 100}">
     <a href ng:click="selected=100">ABC</a>
  </li>
  <li ng-class="{current: selected == 101}">
     <a href ng:click="selected=101">DEF</a>
  </li>
  <li ng-class="{current: selected == $index }" 
      ng-repeat="x in [4,5,6,7]">
     <a href ng:click="selected=$index">A{{$index}}</a>
  </li>
</ul>

Cuando un usuario hace clic en uno de los elementos de dirección de arriba, entonces debería, establecer el valor de seleccionado y mostrar uno de los <DIV>siguientes elementos:

<div  ng:show="selected == 100">100</div>
<div  ng:show="selected == 101">101</div>
<div ng-repeat="x in [4,5,6,7]" ng:show="selected == $index">{{ $index }}</div>

Esto funciona para los dos primeros casos.

  • Cuando el usuario hace clic en ABC, el primero <DIV>muestra 100 y cambia de color a rojo.
  • Cuando se hace clic en DEF, aparece 101 y DEF cambia a rojo.

Sin embargo, no funciona en absoluto para A0, A1, A2 y A3

  • Cuando un usuario hace clic en A0, A1, A2 o A3, entonces el correcto no se muestra, el valor seleccionado no se establece y el color de TODOS los n0-repetir A0, A1, A2 y A3 se vuelven rojos.

Esto se muestra mejor si nos fijamos en este Plunker:

http://plnkr.co/edit/7HMeObplaBkx5R0SntjY?p=preview

Tenga en cuenta que en la parte superior he agregado {{ selected }}como ayuda de depuración en la parte superior. También x in [4,5,6,7]están destinados a simular un bucle. En la vida real tengo esto como ng-repeat="answer in modal.data.answers".

¿Alguien sabe cómo puedo configurar esto para que la licorriente de la clase se configure en el momento correcto y los DIVespectáculos en el momento adecuado para A0, A1, A2 y A3 <li>y<DIV>

Alan2
fuente

Respuestas:

201

El problema aquí es que ng-repeatcrea su propio ámbito, por lo que cuando lo hace selected=$index, crea una nueva selectedpropiedad en ese ámbito en lugar de alterar la existente. Para arreglar esto tienes dos opciones:

Cambie la propiedad seleccionada a una no primitiva (es decir, objeto o matriz, lo que hace que JavaScript busque la cadena del prototipo) y luego establezca un valor en eso:

$scope.selected = {value: 0};

<a ng-click="selected.value = $index">A{{$index}}</a>

Ver saqueador

o

Use la $parentvariable para acceder a la propiedad correcta. Aunque es menos recomendable ya que aumenta el acoplamiento entre ámbitos

<a ng-click="$parent.selected = $index">A{{$index}}</a>

Ver saqueador

noj
fuente
2
Son dos enfoques separados del problema. La idea era que pudieras elegir cuál prefieres.
noj
29

Como johnnyynnoj mencionó, ng-repeat crea un nuevo alcance. De hecho, usaría una función para establecer el valor. Ver saqueador

JS :

$scope.setSelected = function(selected) {
  $scope.selected = selected;
}

HTML :

{{ selected }}

<ul>
  <li ng-class="{current: selected == 100}">
     <a href ng:click="setSelected(100)">ABC</a>
  </li>
  <li ng-class="{current: selected == 101}">
     <a href ng:click="setSelected(101)">DEF</a>
  </li>
  <li ng-class="{current: selected == $index }" 
      ng-repeat="x in [4,5,6,7]">
     <a href ng:click="setSelected($index)">A{{$index}}</a>
  </li>
</ul>

<div  
  ng:show="selected == 100">
  100        
</div>
<div  
  ng:show="selected == 101">
  101        
</div>
<div ng-repeat="x in [4,5,6,7]" 
  ng:show="selected == $index">
  {{ $index }}        
</div>
Liviu T.
fuente
1
¿ ng:clickRealmente funciona? Pensé que erang-click
Adam F