角度模型中的属性装饰器

时间:2019-07-12 19:30:27

标签: angular typescript angular-decorator

我有一个Angular 8应用程序,该应用程序从后端检索一些数据并将其显示在前端。我有一个问题,即后端模型和前端模型不完全相同,例如后端模型具有SQL格式的date字段,而在前端我希望它采用javascript友好格式。

因此,我想到了为date属性创建一个装饰器,而不是在类中创建另一个属性并将其映射为正确的值。因此,可视化:

方法1:不太聪明:采用正确的日期格式引入新的创建的属性:

export class Message {
    id: number;
    message: string;
    visitor: Visitor;

    createdAt: string; /* Holds the backend model created date */
    created: Date; /* Holds the frontend javscript date */
}

/* API Call in Service */

  public getMessages(visitor_id: number) : Observable<Messages>  {
    return this.httpClient.get<Messages>(`${API_URL}/api/SampleData/Messages?visitor=${visitor_id}`).pipe(

      map(v => {
        v.model.map(i => {
          i.created = moment(i.createdAt.replace('T', ' '), 'YYYY-MM-DD HH:mm:ss').toDate() ;
          return i;
        })
        return v;
      })

    );
  }

方法2:使用属性装饰器的整洁方法:


export class Message {
    id: number;
    message: string;
    visitor: Visitor;

    @DateTransform()
    createdAt: string;
}

function DateTransform() {
  return function (target: any, key: string) {
    Object.defineProperty(target, key, { 
      configurable: false,
      get: () => {
        console.log('trying to get value:' + key); /* This line doesnt fire */
        return moment(key.replace('T', ' '), 'YYYY-MM-DD HH:mm:ss').toDate() 
      }
    });
  }
}

/* And in the component html */

<span class="kt-chat__datetime">{{ message.createdAt | amTimeAgo }}</span>

因此,第二种方法看起来像正确的方法,但是,getter函数被完全忽略,并且组件模板仍尝试呈现旧值。所以我的问题是,

  1. 什么可能导致吸气剂无法正常工作,
  2. getter是否可以返回不同的类型(日期)而不是原始字符串:
  3. 最重要的是,这里的装饰器是正确的方法吗?

谢谢

2 个答案:

答案 0 :(得分:0)

您可以使用class-transformer库而不是手动执行此操作,并将接收到的JSON自动转换为实际对象。它还允许您指定@Transform注释/修饰符,以进一步自定义普通value的转换方式。

这是一个例子:

import {plainToClass} from "class-transformer";

class User {
    id: number;
    firstName: string;
    lastName: string;

    @Type(() => Date)
    @Transform(value => moment(value), { toClassOnly: true })
    date: Moment;
}

const fromPlainUser = {
    unkownProp: 'hello there',
    firstName: 'Umed',
    lastName: 'Khudoiberdiev',
    date: '2013-02-08 09:30 '
}

console.log(plainToClass(User, fromPlainUser))

// User {
//   unkownProp: 'hello there',
//   firstName: 'Umed',
//   lastName: 'Khudoiberdiev',
//   date: Date Object
// }

您可以检出库的README部分-它具有使用方法的多个示例。

答案 1 :(得分:0)

您可以使用打字稿装饰器解决问题;

我认为您的问题已经回答,请签出。 How to Create a Simple Typescript Metadata Annotation