Chandrakant
Chandrakant

Reputation: 1981

Next and Previous elements angular2

Hey guys I'm new to angular2

tried several ways to achieve this kind of functionality (look at jsfiddle).

What I need is on click it add active class to next element and removes from current element same vice-versa for Prev btn.so that next element will be shown and prev one will be hided. add/remove class or add remove style could work for me..or anything else that can achieve this kind of thing

I have just achieved it with jQuery.

But I just want to implement it with Angular2, anything can work for me

html:

<ul>
  <li class="active">item1</li>
  <li>item2</li>
  <li>item3</li>
</ul>

<button  class="prev">prev</button> <button class="next">Next</button>

jQuery:

$('.next').click( function(){
    $('.active').next().addClass('active').prev().removeClass('active')
})
$('.prev').click( function(){
    $('.active').prev().addClass('active').next().removeClass('active')
})

https://jsfiddle.net/svgmc125/

Edit:

code updated using help of @pixelbits help

now HTML will be

  <li>
      <my-component></my-component>
  </li>
  <li>
      <my-component-1></my-component-1>
  </li>

  <li [class]="slides[selectedIndex] == slide ? 'active': ''" 
                 *ngFor="let slide of slides">
    <img src="../../assets/images/onboarding/slides/{{slide}}.png" alt="">
  </li>
  <li>
      <my-component-2></my-component-2>
  </li>
  <li>
      <my-component-3></my-component-3>
  </li>

ts:

export class SlidesComponent{

  slides: any[];
    selectedIndex: number;
    constructor() {
        this.selectedIndex = 0;
        this.slides = [1,2,3,4,5,6,7,8,9,10,11,12,13,14,15];
    }

    next() {
       ++this.selectedIndex;
    }

    previous() {
        --this.selectedIndex;
    }

 }

its all working fine for looped <li> but still have issue with remaining <li>

Upvotes: 1

Views: 10340

Answers (5)

snorkpete
snorkpete

Reputation: 14564

Your thinking around the problem needs to be different when dealing with Angular vs jQuery. In Angular, it's helpful to think of the HTML/View as a visual reflection of your data model in code.

So, for example, let's say you have a component like:

@Component({
  template: `
    <ul>
      <li [class.active]="current == 0">item1</li>
      <li [class.active]="current == 1">item2</li>
      <li [class.active]="current == 2">item3</li>
    </ul>

    <button class="prev" (click)="previous()">prev</button> 
    <button class="next" (click)="next()">Next</button>
  `
})
export class ListComponent {
   current = 0;

   next() {
     if (current == 0) {
       current = 2;
     } else {
       current = current - 1;
     }
   }

   next() {
     current = (current + 1) % 3;
   }
}

The above component will implement the functionality as you described. But more importantly is to understand what Angular is about. You should always try to envision the raw data that you're trying to display in your component, and implement logic in your component to change that data as you need. Then your template simply becomes a visual representation of your data, along with hooks to the logic to change that data based on user input.

So, in the example given, [class.active]="current == 0" says to either add or remove the active class based on whether the current variable is zero or not.

And (click)="previous()" means to call the previous method in your class whenever a click event is fired from that button.

Upvotes: 2

driconmax
driconmax

Reputation: 942

You can use ng-class to apply the class active based on the current index of the li item.

The HTML

<div ng-controller="MainController as main">
  <ul>
    <li ng-class="{'active' : main.active == 1}">item1</li>
    <li ng-class="{'active' : main.active == 2}">item2</li>
    <li ng-class="{'active' : main.active == 3}">item3</li>
  </ul>

  <button class="prev" ng-click="main.back()">prev</button>
  <button class="next" ng-click="main.next()">Next</button>
</div>

The Controller

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

app.controller('MainController', function() {

  this.active = 1;

  this.max = 3;

  this.next = function(){
    this.active++;
    if(this.active > this.max) this.active = this.max;
  }

  this.back = function(){
    this.active--;
    if(this.active < 1) this.active = 1;
  }
});

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

Upvotes: -2

Michael Kang
Michael Kang

Reputation: 52837

You need two models in your component class: items array and the selectedIndex. Bind class based on whether the item at the selectedIndex equals the item.

@Component({
   selector: 'list',
   template: `
      <ul>
          <li [class]="items[selectedIndex] == item ? 'active': ''" 
                 *ngFor="let item of items">{{ item }}</li>
      </ul>
   `
})
class MyComponent {
    items: string[];
    selectedIndex: number;
    constructor() {
        this.selectedIndex = 0;
        this.items = ["item1", "item2","item3"];
    }

    next() {
       ++this.selectedIndex;
    }

    previous() {
        --this.selectedIndex;
    }

}

Upvotes: 3

JB Nizet
JB Nizet

Reputation: 691625

All you need is to have, in your component, a field referencing the active item (or its index):

items: Array<string> = ['first', 'second', 'third'];
activeItem: string = items[0];

previous() {
    const currentIndex = this.items.indexOf(this.activeItem);
    const newIndex = currentIndex === 0 ? this.items.length - 1 : currentIndex - 1;
    this.activeItem = this.items[newIndex];
}

next() {
    const currentIndex = this.items.indexOf(this.activeItem);
    const newIndex = currentIndex === this.items.length - 1 ? 0 : currentIndex + 1;
    this.activeItem = this.items[newIndex];
}

and in the view:

<div *ngFor="let item of items" [class.active]="item === activeItem">{{ item }}</div>

Upvotes: 6

G&#252;nter Z&#246;chbauer
G&#252;nter Z&#246;chbauer

Reputation: 657048

<ul>
  <li #item class="active">item1</li>
  <li #item>item2</li>
  <li #item>item3</li>
</ul>
@ViewChildren('item') items:QueryList<ElementRef>;

ngAfterViewInit() {
  var active = this.items.toArray()
      .filter(i => i.nativeElement.classList.contains('active'));
  console.log(active[0].nativeElement);
}

Upvotes: 4

Related Questions