1

I'm learning Angular. I've created a custom month-picker from the scratch. It selects a range of months, no dates and no weeks. I wanted to highlight the range of months that'd been selected. You can think of primeng month picker but with range. I tried this, this and many other solutions but I failed. Here is my code:

monthpicker.component.html

<div class="my-table-div dropdown-content">
  ...
  <br>
  <div *ngFor="let row of matrix" class="my-table">
    <span *ngFor="let x of row">
      <span class="month-name" (click)="onClick(x)" [class.extraStyle]="someProperty">
        {{ x }}
      </span>
    </span>
  </div>
</div>

monthpicker.component.ts

  ...
  clickCount: number =0; /*to determine lower bound and upper bound selection*/
  someProperty:boolean=false;
  flag:boolean= false;

  ...
  arr = [
    'Jan', 'Feb', 'Mar', 'Apr',
    'May', 'Jun', 'JuL', 'Aug',
    'Sep', 'Oct', 'Nov', 'Dec'
  ];
  ...

  n = 4;
  matrix = Array
    .from({ length: Math.ceil(this.arr.length / this.n) }, (_, i) => i)
    .map(i => this.arr.slice(i * this.n, i * this.n + this.n));

  ...

  onClick(x) {
    this.clickCount++;
    console.log("Month: " + x);
    if(this.clickCount%2!=0) {
      this.lowerMonth= x;
      this.lowerYear=this.year;
    }
    console.log("Year: " + this.lowerYear);
    console.log("Clicked "+this.clickCount +" times.");
    if(this.clickCount%2==0) {
      this.upperMonth=" "+x;
      this.upperYear =this.year;
      if(this.flag) {
        this.someProperty=true;
      }
      else {
        this.someProperty=false;
      }
    } 
  }

And here is the css I'm applying monthpicker.component.css

.extraStyle {
    background-color: #1474A4 !important;
    color: white !important;
    text-align: center !important;
}

And here is the result: enter image description here

See, CSS is applied to all the months even though the selection is from Jan to Jul only.

Is there any way that I can apply css to selected index numbers only. Because index is starting from 0 to 11 and is kind of fixed for each month. Ok, This is what I thought, I'm sorry I may be completely wrong. Please correct me and help me implement that.

Tanzeel
  • 4,174
  • 13
  • 57
  • 110
  • Why not using some built in angular date pickers – Awais Dec 03 '19 at 09:37
  • @Awais. I'm gald you actually asked me this question. This is a group project and I'm not allowed to even touch anything inside `package.json`. ;-) – Tanzeel Dec 03 '19 at 09:40
  • The team is using `primeng:^5.2.7` but the month-picker is available only after `Version: 6`. But as I told you. I should not upgrade any dependency. That's why I'm making it from the scratch. – Tanzeel Dec 03 '19 at 09:41
  • 1
    someProperty is a state of the component, not the state of the month span. So when you set ``someProperty = true`` it is applied to every element. – mat.hudak Dec 03 '19 at 09:42
  • @dallows. Good one Sir. is there any way to set that state for some specific index numbers only? – Tanzeel Dec 03 '19 at 09:44
  • Then may be in `click` function you can add the class as well and style it yourself – Awais Dec 03 '19 at 09:44
  • @Awais. Sorry I did not understand. Can you please explain a little bit in detail. – Tanzeel Dec 03 '19 at 09:46
  • May be this can help you https://stackoverflow.com/questions/40986464/angular-2-select-clicked-list-item-add-active-class-and-remove-from-sibling – Awais Dec 03 '19 at 09:48
  • The questions you tried are AngularJS (read version 1.x) and you are using Angular (AKA version 2+). You can use `[ngClass]` as per answers below – mxr7350 Dec 03 '19 at 09:58
  • @mxr7350. Yes you're right. And I also implemented below solutions but still having major issues. Can you please help. – Tanzeel Dec 03 '19 at 10:00

1 Answers1

1

You can add isSelected key in row array. Like this :

matrix: any = Array.from(
    { length: Math.ceil(this.arr.length / this.n) },
    (_, i) => i
  ).map(i =>
    this.arr.slice(i * this.n, i * this.n + this.n).map(x => ({
      monthName: x,
      isSelected: false
    }))
  );

than use the isSelected key in html like this :

<div *ngFor="let row of matrix" class="my-table">
    <span *ngFor="let x of row">
      <span class="month-name" (click)="onClick(x); x.isSelected = !x.isSelected" [ngClass]="{'extraStyle' : x.isSelected }">
        {{ x.monthName }}
      </span>
    </span>
</div>
Shashikant Devani
  • 2,298
  • 1
  • 12
  • 25
  • Can you please check your typescript once again. Because now i'm not even getting any month at all. Its just blank with `ERROR Error: "Cannot find a differ supporting object '[object Object]' of type 'object'. NgFor only supports binding to Iterables such as Arrays."` error on console. But a few red underlines on vscode editor. – Tanzeel Dec 03 '19 at 09:56
  • We had replace i with i.data. So try row to row.data in html. See updated answer. – Shashikant Devani Dec 04 '19 at 06:11
  • No Sir. Still cant see any month. Though console is clean. No errors. – Tanzeel Dec 04 '19 at 06:17
  • Ok give me few minuntes. i will create stackblitz for that – Shashikant Devani Dec 04 '19 at 06:18
  • 1
    Here is the stackblitz : https://stackblitz.com/edit/angular-rxfwfo. Also the answer is updated – Shashikant Devani Dec 04 '19 at 06:36
  • And that solved my problem. Wish you all the very best Sir. :-) – Tanzeel Dec 04 '19 at 07:33