2

In Angular 2 I'm using ngStyle to change the background and text color of a button. My ngStyle is using a function as it's expression.

<input type="button" value="Go" [ngStyle]="getButtonStyle()">

Here is the function:

getButtonStyle() {
    console.log("Hit the function");

    if(this.serialListCount == 1) { 
      console.log("Option #1 triggered")
      return { background: ''#cc0000', color: 'white' }; 
    }
    else if(&& this.serialListCount > 1) {
      console.log("Option #2 triggered")
      return { background: '#23b900', color: 'black' }; 
    }
  }

I noticed the function is being called hundreds of times within a short period of time on the form. The guys who wrote the initial code are using ngCompleter which is a type-ahead component used to help the user complete their search criteria on other fields and those changes to the data set is what I am trying to keep track of and do things style wise based on the list having "one" vs "more than one" items in it's collection.

The property that I am checking to decide if I should run the If or If Else block is a .length property on a list of serial numbers. That list is an observable under the hood, I know because when I look at the property it is getting the serialNumberList.length of, it is defined as such:

  serialNumberList: CompleterData; 

If we F12 on that completerData we see this:

import { EventEmitter } from "@angular/core";
import { Observable } from "rxjs/Observable";
import { CompleterItem } from "../components/completer-item";
export interface CompleterData extends Observable<CompleterItem[] | null> {
    dataSourceChange?: EventEmitter<void>;
    search(term: string): void;
    cancel(): void;
    convertToItem?(data: any): CompleterItem | null;
}

I get the length of the collection and set it inside of my GetSerialNumbers() method like so:

import { Component, OnInit } from '@angular/core';
import { Observable } from 'rxjs/Rx';
//...
import { CompleterService, CompleterData } from 'ng2-completer';
//...

@Component({
  //...
}) 

export class XxxDetailComponent implements OnInit {
  serialNumberList: CompleterData; 
  serialListCount: number = 0

  constructor(private completerService: CompleterService) { }

  getSerialNumber(): void {
     this.commonService.getSerialNumbers(this.getSerialNumberInput)
      .then((response) => {
        (response && response.length == 1)
          ? this.xx.serialNumber = response[0].serialNumber
          : this.serialNumberList = response;

        //THIS IS WHERE I GET THE LENGTH OF THE LIST
        this.serialListCount = response.length;
  }

Since this method is being called so many times it must be because I have set it up to evaluate a property that is connected to an observable. And since that list it is representing the length of changes with every focus or few keystrokes in other input fields, that data source has a lot of activity modifying it's number of items contained.

So far this is nothing that is going to production, I want a better grasp of Angular and I'm pulling rookie moves as I have been out of front end for two years and just getting back into Angular. Observables are new to me, I was unaware what I was doing until I slapped a debugger in the function.

So I have asked myself..

Is this function and the change to the style happening so often a real issue? I could keep track of what evaluation that triggers the style change in the else statement that is being set and not set it again if it's already set, but it would still hit the method just as many times, just not set the background over and over with the same value. Someone mentioned change detection, that sounds promising. Would it be better to check a value that is somehow not connected to that observable, but gets updated with the correct data list length on a much less basis? Is this normal to evaluate something that changes so often and will I see performance issues from this?

Actual Question: What is the more desirable way to structure this method that returns the styles and is there something I can do with an Rx Pattern that would help?

A good link or resource if answered would be awesome for me to help understand more deeply.

Eric Bishard
  • 5,201
  • 7
  • 51
  • 75
  • I would also love any comments just on what I'm doing and does this seem normal. If you can't give an answer, maybe you can add some wisdom for a newbie Anglereer! – Eric Bishard Aug 12 '17 at 06:00
  • 1
    Can you tell how are you getting the value of serialListCount – Vamshi Aug 12 '17 at 06:09
  • lol, yeah I sure can, even though I struggled with it for some reason for quite a while, it was pretty easy. I'll add it to the post in a few minutes. – Eric Bishard Aug 12 '17 at 06:36
  • 1
    @EricB if you are worried about the observable getting called and the change detection happen so frequently on the component , then try to go a `changeDetectionStategy:onPush` here you need to manually update all your actions for detection – Rahul Singh Aug 12 '17 at 06:42
  • @Rahul, That sounds promising, I would assume that I would be watching this list and detecting only when it changes and then subscribing to that event? Sorry if my terminology is off... Any links that you would recommend I am seeing several... – Eric Bishard Aug 12 '17 at 06:50
  • This answer on stack might help https://stackoverflow.com/a/39802466/2708210 – Rahul Singh Aug 12 '17 at 06:53
  • @Skeptor .. Why were you trying to figure out how to get length from an observable that was related to some type of data list? I was in that situation a few days ago. I'm not sure if this is the best way, but it works for my needs. – Eric Bishard Aug 12 '17 at 06:54
  • @Rahul, perfect. I will try to make my Question more specific here too so someone can take a stab. – Eric Bishard Aug 12 '17 at 06:55
  • Use the `Observable` with `async` so that the background changes only when data changes . – Vamshi Aug 12 '17 at 07:54
  • If you can create a plnkr or stackblitz, it would be straightforward to provide a solution – Vamshi Aug 12 '17 at 08:10

0 Answers0