0

Hi I am trying to create a simple grid with sorting feature using Angular 2. Below is the structure of the component.

import {Component, Pipe} from 'angular2/core';
import {NgClass} from 'angular2/common';

    @Component({
        selector: "sorter",
        template: `
            <i class="indicator glyphicon glyphicon glyphicon-sort-by-alphabet"  [ngClass]="{'glyphicon-sort-by-alphabet-alt': isReverse}"></i>
            <span>{{isReverse}}</span>
        `,
        directives: [NgClass]
    })
    export class Sorter {
        isReverse = true;
        public sortData(key) {
            this.isReverse = !this.isReverse;
            console.log("Directection-->" + this.isReverse);
        }

    }

I have created a var isReverse and changing it in the the sortData() method. The console.log() prints the correct value when I click the column header but it is not affecting the template. I am unable to figure what is going wrong here.

Thanks

Vishal
  • 130
  • 1
  • 9
  • Where is `sortData()` called from? Do you call this from non-Angular code? – Günter Zöchbauer Jan 22 '16 at 11:47
  • 1
    Whats the issue? is there any problem with ngClass? If so, check in browser's console at runtime. Go to particular element and do your stuff and check weather class gets applied or not.... and make sure `glyphicon-sort-by-alphabet-alt` is correct class name. – micronyks Jan 22 '16 at 12:48
  • Yes the class name is correct. But I want that to be applied on the change of isReverse value. The sort data method is invoked form outside. That is on the click of element which works as a column. The Sorter is just a icon that needs to be changed when sorting applied. – Vishal Jan 25 '16 at 06:16

2 Answers2

3

If your view is not updating (e.g., {{isReverse}} doesn't change), you are probably calling sortData() from "outside" Angular, hence Angular is not automatically running change detection when your click handler finishes.

One way to solve this is to inject ChangeDetectorRef and force it to run change detection on this component:

import {Component, Pipe, ChangeDetectorRef} from 'angular2/core';
export class Sorter {
   constructor(_cdRef: ChangeDetectorRef) {}
   public sortData(key) {
    this.isReverse = !this.isReverse;
    console.log("Directection-->" + this.isReverse);
    this._cdRef.detectChanges();
  }
  ...

See also Triggering Angular2 change detection manually

Community
  • 1
  • 1
Mark Rajcok
  • 362,217
  • 114
  • 495
  • 492
1

From what I understand from your question and your code, it seems that you create a dedicated component to change sorting.

So the isReverse attribute is internally to this component and can't be used outside it. To make this possible and leveraging two way binding, I would suggest to refactor your component as described below:

@Component({
  selector: "sorter",
  template: `
    <i class="indicator glyphicon glyphicon glyphicon-sort-by-alphabet"  
       [ngClass]="{'glyphicon-sort-by-alphabet-alt': isReverse}"
       (click)="sortData()"></i>
    <span>{{isReverse}}</span>
  `,
  directives: [NgClass]
})
export class Sorter {
  @Input()
  isReverse = true;
  @Output()
  isReverseChanged:EventEmitter = new EventEmitter();

  public sortData(key) {
    this.isReverse = !this.isReverse;
    console.log("Directection-->" + this.isReverse);
    this.isReverseChanged.emit(this.isReverse);
  }
}

In the grid component you can now have access to the isReverse property, as described below:

<sorter [(isReverse)]="tableReverse"></sorter>

This way you can sort the grid according to the tableReverse property of this parent component.

Hope it helps you, Thierry

Thierry Templier
  • 198,364
  • 44
  • 396
  • 360