Aurelia动态绑定值转换器

Aurelia动态绑定值转换器,aurelia,Aurelia,我和奥雷莉亚发生了争执,我认为我遗漏了什么 我正在尝试创建一个“通用”网格。我删除了很多html以保持示例简短,但基本思想如下: <template> <require from="../value-converters"></require> <table show.bind="rows.length"> <thead> <tr> <th repeat.for="columnD

我和奥雷莉亚发生了争执,我认为我遗漏了什么

我正在尝试创建一个“通用”网格。我删除了很多html以保持示例简短,但基本思想如下:

<template>
<require from="../value-converters"></require>
  <table show.bind="rows.length">
    <thead>
      <tr>
        <th repeat.for="columnDefinition of columnDefinitions">
          ${columnDefinition.displayName}
        </th>
      </tr>
    </thead>
    <tbody>
      <tr repeat.for="row of rows">
        <td repeat.for="columnDefinition of columnDefinitions">
          <span if.bind="columnDefinition.isCurrency">${row[columnDefinition.propertyName] | numeralFormatter}</span>
          <span if.bind="columnDefinition.isDate">${row[columnDefinition.propertyName] | dateFormatter}</span>
          <span if.bind="!columnDefinition.isCurrency && !columnDefinition.isDate &&">${row[columnDefinition.propertyName]}</span>
        </td>
      </tr>
    </tbody>
  </table>
</template>
但是解析器在“.”上抛出了一个错误

有没有办法做到这一点?处理这类问题的“奥雷利亚方式”是什么


提前感谢您提供的任何帮助。

您是否考虑过将单个
与单个通用转换器一起使用,该转换器将列定义作为参数,并委托给正确的转换器?我认为这将使组件标记更简单

<span>${row[columnDefinition.propertyName] | formatCell:columnDefinition}</span>

您是否考虑过将单个
与单个通用转换器一起使用,该转换器将列定义作为参数并委托给右侧转换器?我认为这将使组件标记更简单

<span>${row[columnDefinition.propertyName] | formatCell:columnDefinition}</span>

最后,我采用了一种类似的方法,但有一点不同:

import {DateValueConverter} from './date';
import {NumberValueConverter} from './number';
import {autoinject} from 'aurelia-framework';

@autoinject()
export class MetaValueConverter {
    constructor(private date: DateValueConverter,
                private number: NumberValueConverter) {
    }

    public toView(value, valueConverter, format) {
        /* JUSTIFICATION: https://stackoverflow.com/questions/38898440/aurelia-dynamically-bound-value-converter#comment-65199423 */
        /* tslint:disable:no-string-literal */
        if (this[valueConverter] && this[valueConverter].toView) {
            return this[valueConverter].toView(value, format);
        } else {
            return value;
        }
    }

    public fromView(val, valueConverter, format) {
        if (this[valueConverter] && this[valueConverter].fromView) {
            return this[valueConverter].fromView(value, format);
        } else {
            return value;
        }
    }
}
可以找到原始代码


希望这能有所帮助。

我最终采用了与作者建议的方法类似的方法,但有一点不同:

import {DateValueConverter} from './date';
import {NumberValueConverter} from './number';
import {autoinject} from 'aurelia-framework';

@autoinject()
export class MetaValueConverter {
    constructor(private date: DateValueConverter,
                private number: NumberValueConverter) {
    }

    public toView(value, valueConverter, format) {
        /* JUSTIFICATION: https://stackoverflow.com/questions/38898440/aurelia-dynamically-bound-value-converter#comment-65199423 */
        /* tslint:disable:no-string-literal */
        if (this[valueConverter] && this[valueConverter].toView) {
            return this[valueConverter].toView(value, format);
        } else {
            return value;
        }
    }

    public fromView(val, valueConverter, format) {
        if (this[valueConverter] && this[valueConverter].fromView) {
            return this[valueConverter].fromView(value, format);
        } else {
            return value;
        }
    }
}
可以找到原始代码

希望这能有所帮助。

我遵循并进一步创建了一个完全动态的值转换器

用法如下
${myValue | dynamic:converterKey:converterArgs}
或者如果不需要额外的参数,只需
${myValue | dynamic:converterKey}
converterKey
用于请求应在容器中注册的值转换器
converterArgs
是传递给
toView
fromView
函数的参数数组

import { autoinject, Container } from 'aurelia-dependency-injection';

export type ValueConverterKey = new (...args: any[]) => object;

type ValueConverterFunc = (...args: any[]) => any;

interface ValueConverter {
  toView?: ValueConverterFunc;
  fromView?: ValueConverterFunc;
}

@autoinject()
export class DynamicValueConverter {
    constructor(
      private container: Container,
    ) { }

    public toView(value: any, converterKey?: ValueConverterKey, ...converterArgs: any[]) {
      if (!converterKey) {
        return value;
      }

      return this.convertValueIfPossible(value, converterKey, converterArgs, 'toView');
    }

    public fromView(value: any, converterKey?: ValueConverterKey, ...converterArgs: any[]) {
      if (!converterKey) {
        return value;
      }

      return this.convertValueIfPossible(value, converterKey, converterArgs, 'fromView');
    }

    private convertValueIfPossible(value: any, converterKey: ValueConverterKey, converterArgs: any[], func: keyof ValueConverter) {
      let converter = this.container.get(converterKey);

      if (converter) {
        let converterFunc = converter[func];

        if (converterFunc) {
          return converterFunc.call(converter, value, ...converterArgs);
        }
      }

      return value;
    }
}
我随后又进一步创建了一个完全动态的值转换器

用法如下
${myValue | dynamic:converterKey:converterArgs}
或者如果不需要额外的参数,只需
${myValue | dynamic:converterKey}
converterKey
用于请求应在容器中注册的值转换器
converterArgs
是传递给
toView
fromView
函数的参数数组

import { autoinject, Container } from 'aurelia-dependency-injection';

export type ValueConverterKey = new (...args: any[]) => object;

type ValueConverterFunc = (...args: any[]) => any;

interface ValueConverter {
  toView?: ValueConverterFunc;
  fromView?: ValueConverterFunc;
}

@autoinject()
export class DynamicValueConverter {
    constructor(
      private container: Container,
    ) { }

    public toView(value: any, converterKey?: ValueConverterKey, ...converterArgs: any[]) {
      if (!converterKey) {
        return value;
      }

      return this.convertValueIfPossible(value, converterKey, converterArgs, 'toView');
    }

    public fromView(value: any, converterKey?: ValueConverterKey, ...converterArgs: any[]) {
      if (!converterKey) {
        return value;
      }

      return this.convertValueIfPossible(value, converterKey, converterArgs, 'fromView');
    }

    private convertValueIfPossible(value: any, converterKey: ValueConverterKey, converterArgs: any[], func: keyof ValueConverter) {
      let converter = this.container.get(converterKey);

      if (converter) {
        let converterFunc = converter[func];

        if (converterFunc) {
          return converterFunc.call(converter, value, ...converterArgs);
        }
      }

      return value;
    }
}

我当然可以这样做,但如果我再想出另一个类型转换器,比如说我有一个枚举,我想把它转换成文本,我不能只创建转换器和列定义,让它正常工作,我必须在这里添加另一个if语句。它似乎不适合扩展性。1-每次都有一个新的if语句,或者每次都有一行新行出现在标记中。2-你并不需要每次都有一个新的if语句。这只是为了表明您可以将转换器选择外部化。您可以使用约定
type+“Converter”
并动态创建转换器。或者,您可以在应用程序启动时向DI容器注册命名转换器,并在该转换器中向容器请求该名称的转换器。如果找到一个,您就使用它,否则返回
value
@peinearydevelopment您是否找到了不同的解决方案,或者这是最好的方法?我现在正试图做完全相同的事情,从我目前的角度来看,Sylvain的解决方案似乎是最好的方法,但我对Aurelia的经验不如其他开发人员。@LStarky。我在下面发布了我的方法,它类似于Sylvain建议的方法,但我认为更具扩展性。我仍然非常有兴趣听到其他人的不同方法。我当然可以这样做,但如果我提出另一个类型转换器,比如说我有一个枚举,我想将它转换为文本,我不能只创建转换器和列定义,让它正常工作,我必须在这里添加另一个if语句。它似乎不适合扩展性。1-每次都有一个新的if语句,或者每次都有一行新行出现在标记中。2-你并不需要每次都有一个新的if语句。这只是为了表明您可以将转换器选择外部化。您可以使用约定
type+“Converter”
并动态创建转换器。或者,您可以在应用程序启动时向DI容器注册命名转换器,并在该转换器中向容器请求该名称的转换器。如果找到一个,您就使用它,否则返回
value
@peinearydevelopment您是否找到了不同的解决方案,或者这是最好的方法?我现在正试图做完全相同的事情,从我目前的角度来看,Sylvain的解决方案似乎是最好的方法,但我对Aurelia的经验不如其他开发人员。@LStarky。我在下面发布了我的方法,它类似于Sylvain建议的方法,但我认为更具扩展性。我仍然很有兴趣听到其他人的不同方法。这看起来太棒了!非常感谢分享!这看起来太棒了!非常感谢分享!FWIW我们有一个用例,其中我们创建了一个包含显示值的自定义元素的包,但是我们希望为包的用户提供根据需要转换显示值的能力。FWIW我们有一个用例,其中我们创建了一个包含显示值的自定义元素的包,但是我们希望提供软件包用户根据需要转换显示值的能力。