<commit_before>import {ColumnState} from './../column-state.class';
import {DefaultValuePipe} from './../../pipes/default-value/default-value.pipe';

import { Component, ElementRef, Input, OnInit, ViewChild } from '@angular/core';

@Component({
  selector: '[iw-td]',
  templateUrl: './td.component.html',
  styleUrls: ['./td.component.css'],
  providers: [DefaultValuePipe]
})
export class TdComponent implements OnInit {
  @Input() column: ColumnState;
  @Input() row: any;

  @ViewChild('contentDiv') contentDiv: ElementRef;

  constructor(private defaultValuePipe: DefaultValuePipe) { }

  ngOnInit() {
  }

  get cellValue(): any {
    return this.row[this.column.config.id];
  }

  get formattedValue() {
    if (!this.column) { return; }
    if (!this.column.config.formatters) {
      return this.defaultValuePipe.transform(this.cellValue);
    }
    return this.column.config.formatters.reduce((value, formatter) => {
      return formatter.transform(value, ...(formatter.arguments || []));
    }, this.cellValue);
  }

  get content(): string {
    return this.contentDiv.nativeElement.textContent;
  }

  get isChanged(): boolean {
    return this.contentDiv.nativeElement.textContent.trim() !== this.formattedValue;
  }

  get hasSubfields() {
    if (!this.column) { return; }
    return this.column.config.subFields && this.column.config.subFields.length > 0;
  }
}
<commit_msg>perf(td.component): dirty check formatters value<commit_after>import {ColumnState} from './../column-state.class';
import {DefaultValuePipe} from './../../pipes/default-value/default-value.pipe';

import { Component, ElementRef, Input, OnInit, ViewChild } from '@angular/core';

@Component({
  selector: '[iw-td]',
  templateUrl: './td.component.html',
  styleUrls: ['./td.component.css'],
  providers: [DefaultValuePipe]
})
export class TdComponent implements OnInit {
  @Input() column: ColumnState;
  @Input() row: any;


  @ViewChild('contentDiv') contentDiv: ElementRef;

  private _currentCellValue: any;
  private _currentFormattedValue: any;

  constructor(private defaultValuePipe: DefaultValuePipe) { }

  ngOnInit() {
  }

  get cellValue(): any {
    return this.row[this.column.config.id];
  }

  get formattedValue() {
    if (!this.column) { return; }
    if (this.cellValue === this._currentCellValue) {
      // TODO: use default value if both cellValue and currentCellValue are undefined
      return this._currentFormattedValue;
    }
    this._currentCellValue = this.cellValue;

    if (!this.column.config.formatters) {
      this._currentFormattedValue = this.defaultValuePipe.transform(this.cellValue);
    } else {
      this._currentFormattedValue = this.column.config.formatters.reduce((value, formatter) => {
        return formatter.transform(value, ...(formatter.arguments || []));
      }, this.cellValue);
    }
    return this._currentFormattedValue;
  }

  get content(): string {
    return this.contentDiv.nativeElement.textContent;
  }

  get isChanged(): boolean {
    return this.contentDiv.nativeElement.textContent.trim() !== this.formattedValue;
  }

  get hasSubfields() {
    if (!this.column) { return; }
    return this.column.config.subFields && this.column.config.subFields.length > 0;
  }
}

{'fraction_non_alphanumeric': 0.14665841584158415, 'fraction_numerical': 0.0006188118811881188, 'mean_word_length': 3.8325859491778775, 'pattern_counts': {'":': 0, '<': 3, '<?xml version=': 0, '>': 7, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '1535092', 'n_tokens_mistral': 1006, 'n_tokens_neox': 984, 'n_words': 199}