Angular 2:Typescript:根据提供的过滤条件过滤网格数据

时间:2017-03-20 09:03:55

标签: javascript angular typescript eval

我在网格(列表)中使用动态列过滤。如果我要应用静态过滤条件,它按预期工作。但是当我尝试使用动态列时,它不起作用,我需要调用动态列,因为同一列上的多个条件也应该存在多列。它不会给我任何错误,但不会过滤任何记录

过滤面板:

enter image description here

静态过滤器(工作):

this.GridData.filter(a => a.Scope == 'Framework');

动态过滤器(不工作):

let _condition = "a.Scope == 'Framework'";
this.GridData.filter(a => _condition ); 

需要动态条件才能工作。

2 个答案:

答案 0 :(得分:5)

您必须在过滤器功能中调用方法,如下所示。

script

答案 1 :(得分:2)

这不会起作用,字符串不会自动转换为JavaScript表达式并进行评估。

函数a => "a.Scope == 'Framework'"始终匹配所有项,因为它返回非空/非空白字符串,这是一个真值。

我建议创建一个相当简单的谓词构建器,而不是使用动态评估(eval),从而承担这种方法所暗示的严重安全性,可读性和可破坏性。

除了更可靠,可扩展且更易于维护之外,它还提供了一个愉快的机会来突出JavaScript启用的一些优雅的编码模式,以及哪些TypeScript反过来允许我们雄辩地指定。

这是一个例子

export interface MemberInvocationExpression {
  kind: 'memberInvocation';
  memberKey: keyof Project; // project is row type
  args?: {}[];
  negated?: true;
  conjunction: 'and' | 'or';
};

export interface MemberComparisonExpression {
  kind: 'memberComparison';
  memberKey: keyof Project;
  compareWith: {};
  negated?: true;
  comparison: 'equal' | 'notEqual' | 'greater' | 'lesser';
  conjunction: 'and' | 'or';
}

export type GridFilterExpression =
 | MemberInvocationExpression 
 | MemberComparisonExpression;

export default class {
  gridFilterExpressions: GridFilterExpression[] = [];

  composeFilters(): (p: Project) => boolean {

    return this.gridFilterExpressions.reduce((composed, expression) => {
      // every element except the first element, must specify this.
      const conjunction = expression.conjunction;

      const predicate = predicateFromExpression(expression);

      switch (conjunction) {
        case 'and':
          return p => composed(p) && predicate(p);
        case 'or':
          return p => composed(p) || predicate(p);
        default: 
          throw Error('Invalid composition');
      }
    }, _ => true);
  }
}

function predicateFromExpression(expression: GridFilterExpression) {
  switch (expression.kind) {
    case 'memberInvocation':
      return predicateFromMemberInvocationExpression(expression);
    case 'memberComparison':
      return predicateFromMemberComparisonExpression(expression);
    case // other filter expression kinds....
      default: throw Error('invalid filter');
  }
}

function predicateFromMemberInvocationExpression(expression: MemberInvocationExpression) {
  const {memberKey, args, negated} = expression;

  const predicate = (p: Project) => p[memberKey](...args);

  return negated ? (p: Project) => !predicate(p) : predicate;
}

function predicateFromMemberComparisonExpression(expression: MemberComparisonExpression) {
  const {memberKey, compareWith, comparison, negated} = expression;

  const predicate = (p: Project) => {
    switch (comparison) {
      case 'equal': return p[memberKey] === compareWith;
      case 'notEqual': return p[memberKey] !== compareWith;
      case 'greater': return p[memberKey] > compareWith;
      case 'lesser': return p[memberKey] < compareWith;
      default: throw Error('Invalid comparison in filter');
    }
  };

  return negated ? (p: Project) => !predicate(p) : predicate;
}

填充数组gridFilterExpressions或您选择调用的任何内容,留给读者一个练习,但这是一个简单的部分。 好吧,这是一个基于您的一个可见过滤器的示例:

gridFilterExpressions
  .push({
    memberKey: 'Scope',
    compareWith: 'framework',
    comparison: 'equal',
    conjunction: 'and'
  },
  {
    kind: 'memberInvocation',
    memberKey: 'endsWith',
    args: ['test'],
    conjunction: 'or'
  });
相关问题