Angular2中的解析器和格式化程序

时间:2016-09-12 20:02:09

标签: angular angular2-forms

在Angular2中执行解析器格式化程序的方式是什么?

在Angular1中,可以使用ngModelController进行此类操作:

//model -> view
ngModelController.$formatters.push(function(modelValue) {
  return modelValue.toUpperCase();
});

//view -> model
ngModelController.$parsers.push(function(viewValue) {
  return viewValue.toLowerCase();
});

你能给我一个如何用Angular2做的例子吗?

UPD 管道类似于Angular1中的过滤器,但我不是要寻找过滤器,而是寻找 ngModel 即可。所以“管道”不是正确答案。

4 个答案:

答案 0 :(得分:5)

根据我的说法,Angular 2中没有格式化程序或解析器的概念,但您可以使用以下代码实现它,非常简单

在HTML中

 <input type="text"  [ngModel] = "formatter(ex)"  (ngModelChange)="parser($event)">

代码

export class Component{
     data:string = 'data';
     constructor(){}

     formatter(value){
        value = value.toUpperCase();   //manipulate the data according to your need
        return value;
     }

     parser(value){
         this.data = value.toLowerCase();  //manipulate the data according to your need
     }



}

您还可以根据需要实现$ formatters和$ parsers。

答案 1 :(得分:3)

  

根据angular 2官方文档,管道被重命名为角度1过滤器。您不能在角度1中使用过滤器将viewModel转换为模型,反之亦然。大多数情况下,您使用过滤器来过滤或格式化模板的数据,而不是用于双向数据传递。

我从未与Angular1合作过,也不知道那些东西是如何运作的。

我认为您正在寻找的是ControlValueAccessor,它使自定义组件与ngModel和Angular2表单一起使用,并允许在值的显示和模型格式之间进行映射。

来自Plunker example

https://github.com/angular/angular/issues/10251#issuecomment-238737954

这是一个比你的问题更复杂的例子,其中一个组件包含一个子表单。组件也可以只是一个表单控件。

Plunker还没有使用现在需要的NgModule但是应该很容易迁移(我以后会再看看)

  

验证与管道有什么关系?如果用户更改无效,那么它是否会通过管道传输?这几乎不是什么。

验证与管道完全无关。

  

我希望看到一个带有验证的自定义组件。组件应具有用户可编辑值的不同表示形式,以及在组件外部传递的模型值的不同表示形式。

上面的Address组件也实现了自定义验证

来自https://github.com/angular/angular/issues/10251#issuecomment-238737954

中的评论
  

添加验证与值访问器具有类似的过程。您实现验证器接口(只是一个validate()函数)并在自定义窗体控件上将其作为NG_VALIDATOR提供。这是一个例子:

另见

答案 2 :(得分:0)

方法 writeValue(val: T)updateChanges 是您的解析器和格式化器

在 ng2+(老实说从 ng9 项目中获取)看起来更重的 ngModel 扩展,这里是简短的怪物示例(不可运行 - 堆栈溢出不支持 ng2+):

import { Component, forwardRef, Input } from '@angular/core';
import { NG_VALUE_ACCESSOR } from '@angular/forms';

@Component({
  selector: 'multi-text-input',
  styles: [``],
  template: `
    <div *ngFor="let val of inputs; let idx = index" style="display: flex">
      <input type="text" pInputText [(ngModel)]="val.val" (ngModelChange)="updateChanges()" (mousedown)="onTouched()" />
    </div>
  `,
  // thx to google for this providers section below
  providers: [
    {
      provide: NG_VALUE_ACCESSOR,
      useExisting: forwardRef(() => MultiTextInput),
      multi: true,
    },
  ],
})
export class MultiTextInput<T = string | string[]> {
  inputs: { val: string }[] = [];
  @Input() separator = ',';

  writeValue(value): void {
    value = value || '';
    const val: string[] = Array.isArray(value) ? value : value.split(this.separator);
    this.inputs = val.filter((val) => val.trim()).map((val) => ({ val }));

    this.value = value;
  }

  updateChanges() {
    const arr = this.inputs.map(({ val }) => val.trim()).filter(Boolean);
    // ts-ignore to match T, but u don't even need it
    // @ts-ignore
    this.onChange(Array.isArray(this.value) ? arr : arr.join(this.separator));
  }

  // thx to google for all generic lines below
  value: T;

  registerOnChange(fn): void {
    this.onChange = fn;
  }

  registerOnTouched(fn): void {
    this.onTouched = fn;
  }

  onChange: (_: T) => void = (_: T) => {};
  onTouched: () => void = () => {};
}

导入,然后 <multi-text-input [(ngModel)]="variable"/> 代替 ngModel 也可以是 formControl 属性。如果这对您不起作用,请发表评论,我会提供更好的样本。

答案 3 :(得分:-2)

在Angular2中,您使用管道。 请参阅文档:https://angular.io/docs/ts/latest/guide/pipes.html