File

projects/lib/src/conditions/conditions.service.ts

Index

Properties

Properties

data
data: string
Type : string
Optional
field
field: string
Type : string
or
or: boolean
Type : boolean
Optional
type
type: "equals" | "regexp"
Type : "equals" | "regexp"
values
values: ConditionValue[]
Type : ConditionValue[]
import { Injectable } from "@angular/core";


export interface Condition {
  data?: string; // conditionsData selector (or undefined for the main data object)
  field: string; // The field to select from the data object
  type: 'equals' | 'regexp';
  values: ConditionValue[];
  or?: boolean;
}

export interface ConditionValue {
  value: string;
  not?: boolean;
  $regexp?: RegExp;
}


@Injectable({providedIn: 'root'})
export class ConditionsService {

  public selectData(condition: Condition, conditionsData?: Record<string, any>, data?: any): any {
    return condition.data? conditionsData?.[condition.data] : data;
  }

  public check(condition: Condition | undefined, conditionsData?: Record<string, any>, data?: any): boolean {
    if(!condition) return true;
    const selectData = this.selectData(condition, conditionsData, data);
    return this.checkData(condition, selectData);
  }

  public writeCondition(condition: Condition) {
    const operator = condition.or? ') OR (' : ') AND (';
    return '('+condition.values.map(v => this.writeValue(condition, v)).join(operator)+')';
  }

  public writeValue(condition: Condition, value: ConditionValue) {
    if(condition.type === 'regexp') {
      const operator = value.not? '!' : '';
      return `${operator}${condition.data || 'data'}['${condition.field}'].match(/${value.value}/)'`;
    }
    else if (condition.type === 'equals') {
      const operator = value.not? '!==' : '==='
      return `${condition.data || 'data'}['${condition.field}'] ${operator} '${value.value}'`;
    }
    return '';
  }
  
  public checkData(condition: Condition, data?: any) {
    const value = data?.[condition.field]?.toString() || '';
    return this.checkCondition(condition, value);
  }

  private checkCondition(condition: Condition, data: string): boolean {
    if(condition.or) {
      return !!condition.values.find(v => this.checkSingleValue(condition, v, data));
    }
    else {
      return condition.values.every(v => this.checkSingleValue(condition, v, data));
    }
  }

  private checkSingleValue(condition: Condition, value: ConditionValue, data: string) {
    let test;
    if(condition.type === 'regexp') {
      test = this.checkRegexp(value, data);
    }
    else if(condition.type === 'equals') {
      test = this.checkEquals(value, data);
    }
    return test? !value.not : !!value.not;
  }

  
  private checkEquals(condition: ConditionValue, value: string): boolean {
    return condition.value.toLowerCase() === value.toLowerCase();
  }


  private checkRegexp(condition: ConditionValue, value: string) {
    if(!condition.$regexp) {
      try {
        condition.$regexp = new RegExp(condition.value, 'i');
      }
      catch(e) {
        console.warn("Incorrect regular expression ", condition.value);
        return true;
      }
    }
    return value.match(condition.$regexp);
  }

}

results matching ""

    No results matching ""