Como posso usar o índice $ dentro de um ng-repeat para ativar uma classe e mostrar um DIV?

166

Eu tenho um 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>

Quando um usuário clicar em um dos elementos de endereço acima, defina o valor de selecionado e mostre um dos <DIV>elementos abaixo:

<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>

Isso funciona para os dois primeiros casos.

  • Quando o usuário clica em ABC, o primeiro <DIV>mostra 100 e muda de cor para vermelho.
  • Quando a DEF é clicada, a 101 mostra e a DEF muda para vermelho.

No entanto, ele não funciona para A0, A1, A2 e A3

  • Quando um usuário clica em A0, A1, A2 ou A3, o correto não é exibido, o valor selecionado não é definido e a cor de TODAS as repetições de ng A0, A1, A2 e A3 fica vermelha.

Isso é melhor mostrado se você olhar para este Plunker:

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

Observe que no topo eu adicionei {{ selected }}como um auxiliar de depuração no topo. Além disso, o x in [4,5,6,7]objetivo é simular um loop. Na vida real eu tenho isso como ng-repeat="answer in modal.data.answers".

Alguém sabe como eu posso configurar isso para que a licorrente da classe seja definida no momento certo e os DIVprogramas no momento certo para A0, A1, A2 e A3 <li>e<DIV>

Alan2
fonte

Respostas:

201

O problema aqui é que ng-repeatcria seu próprio escopo; portanto, quando você faz selected=$indexisso, cria uma nova selectedpropriedade a nesse escopo, em vez de alterar a existente. Para corrigir isso, você tem duas opções:

Altere a propriedade selecionada para não primitiva (ou seja, objeto ou matriz, o que faz o javascript procurar a cadeia de protótipos) e defina um valor para:

$scope.selected = {value: 0};

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

Ver plunker

ou

Use a $parentvariável para acessar a propriedade correta. Embora menos recomendado, pois aumenta o acoplamento entre escopos

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

Ver plunker

noj
fonte
2
São duas abordagens separadas para o problema. A idéia era que você poderia escolher qual deles você preferir.
Noj
29

Como johnnyynnoj mencionou, ng-repeat cria um novo escopo. Na verdade, eu usaria uma função para definir o valor. Ver plunker

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.
fonte
1
Será que ng:clickrealmente funciona? Eu pensei que erang-click
Adam F