2016-08-11 76 views
1

我遇到了Aurelia的問題,並且假設我缺少某些東西。Aurelia動態綁定價值轉換器

我正在嘗試創建一個'通用'網格。我已刪除了很多的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> 

我希望能夠使用ValueConverters的幫助下正確顯示某些類型的列中的數據。以上是目前的工作,但我想有更多的價值轉換器的其他列和條件將變得笨拙。迄今爲止,我對Aurelia的經歷是它提供了相當優雅的解決方案,但至今我一直無法弄清這一點。

我嘗試添加另一個屬性的columnDefinition類這樣formatter:string = undefined,然後嘗試創建跨度如下所示:

<span if.bind="columnDefinition.formatter">${row[columnDefinition.propertyName] | columnDefinition.formatter}</span> 
<span if.bind="!columnDefinition.formatter">${row[columnDefinition.propertyName]}</span> 

但是解析器上扔了一個錯誤「」。

有什麼辦法可以達到這個目的嗎?處理這類問題的'aurelia-way'是什麼?

在此先感謝您提供的任何幫助。

回答

1

你有沒有使用單個<span>有一個通用的轉換器,採用列定義爲參數,並委託給合適的轉換器考慮?我認爲這會使組件標記更簡單。

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

而且該格式內:

export class FormatCell { 
    toView(value, columnDefinition){ 
    if(columnDefinition.isCurrency) 
     return new CurrencyConverter().toView(value); 

    if(columnDefinition.isDate) 
     return new DateConverter().toView(value); 

    return value; 
    } 
} 
+1

我肯定可以做到這一點,但如果我再與另一種類型的轉換器來了,說我有一個枚舉,我想將它轉換爲文本,我不能只是創建轉換器和columnDefinition並將其只是工作,我不得不在這裏添加另一個if語句。它對於可擴展性來說似乎並不理想。 – peinearydevelopment

+1

1 - 每次新的if語句或每次標記中的新行都非常接近。 2 - 你每次都不需要新的if語句。這只是爲了表明您可以將轉換器選擇外化。你可以有一個約定'type +「Converter」'並動態創建轉換器。或者您可以在應用程序啓動時向DI容器註冊命名轉換器,並且在此轉換器中向容器請求該名稱的轉換器。如果發現有人使用它,否則返回'value'。 – Sylvain

+0

@peinearydevelopment您是否找到不同的解決方案或者這是最好的方法?我現在正在嘗試做同樣的事情,Sylvain的解決方案似乎是從我目前的角度來看它的最好方式,但我不像其他開發人員那樣熟悉Aurelia。 – LStarky

1

我最終採取了類似的做法,以一個由@Slyvain用有點不同的扭絞的建議:

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; 
     } 
    } 
} 

原始代碼被發現here

希望這會有所幫助。

+0

這看起來太棒了!非常感謝分享! – LStarky

2

我跟着@peinearydevelopment進一步再進了一步,以創建一個完全動態的值轉換器。

用法如下${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; 
    } 
} 
+1

FWIW我們有一個用例,我們創建了一個包含顯示值的自定義元素的包,但我們希望爲包的用戶提供根據需要轉換顯示值的功能。 –