如何在 Angular 世界之外发生更改时更新 Angular 2 Reactive 表单字段

Posted

技术标签:

【中文标题】如何在 Angular 世界之外发生更改时更新 Angular 2 Reactive 表单字段【英文标题】:How to update Angular 2 Reactive form field when changes occurred outside of Angular world 【发布时间】:2017-11-17 10:19:01 【问题描述】:

我最近开始学习 Angular 2,我正在努力理解如何正确地将外部世界发生的变化与 Angular 反应式表单联系起来。

具体来说,我对以下示例有疑问: 我想创建一个指令,通过预先输入的 jQuery 插件提供的自动完成功能来增强输入。我的指令如下所示:

@Directive(
  selector: '[myTypeahead]'
)
class TypeAheadDirective implements AfterViewInit 

  constructor(private el: ElementRef) 
  
  //this will be used as a parameter to source, it is not important for this example
  @Input() myTypeahead: string;
  ngAfterViewInit() 
    let source = new Bloodhound(
      datumTokenizer: Bloodhound.tokenizers.obj.whitespace('value'),
      queryTokenizer: Bloodhound.tokenizers.whitespace,
      prefetch: 'http://twitter.github.io/typeahead.js/data/films/post_1960.json'
    );
    $(this.el.nativeElement).typeahead(null, source, display: 'value');
  

然后我将它绑定到我的组件中的输入元素中,如下所示:

@Component(
  selector: 'my-app',
  template: `
    <form (ngSubmit)="save()" [formGroup]="someForm">
      <h2>Hello name</h2>
      <input formControlName="name" myTypeahead="'http://someRemoteUrl'"/>
    </form>

    <div class="example">Form model: someForm.value | json</div>
  `,
)
export class App implements OnInit 
  someForm: FormGroup;
  name:string;
  constructor(private fb: FormBuilder) 
    this.name = `Angular! v$VERSION.full`
  

  ngOnInit() 
    this.someForm = this.fb.group(
      name: ''
    );
  

  save()

  

Here is a plunker with my example

当我开始在输入中输入内容时 - 我的FormGroup 的绑定按预期工作。但是当我从自动完成中选择一些提示时 - 它会更新输入,但不会将更新后的值传播到我的表单组。

所以我的问题是,是否可以向表单组发出指令中发生的更改的信号?

一个可能的解决方案是制作一个实现 ControlValueAccessor 的组件来通知更改,但我想通过一个接受数据源 URL 的指令来保持这个简单。

【问题讨论】:

plnkr.co/edit/LYrkgUfb3BMFOSXRAcHk?p=preview @yurzui,感谢您发布此信息。因此,它将是一个专门用于响应式表单元素的指令。我认为它回答了我的问题,所以我愿意在它发布时接受它。 【参考方案1】:

内部指令:

您可以使用@Output 发送事件并在表单中捕获它

@Output typeaheadResult = new EventEmitter(); 

...

// Whenever user selects a result dispatch the event 
this.typeaheadResult.emit(changedInput);

在您的 html 中,您可以捕获它

 <input formControlName="name"
          myTypeahead="'http://someRemoteUrl'"
          (typeaheadResult)="doSomething()"
           />

【讨论】:

感谢您的回答,这是一个选项,但我想省略它,因为它使指令的使用变得复杂,可能是在外部触发事件的情况下 - 最好创建一个组件. 我不明白,这就是 Angular 官方对事件的建议吧? 在搜索我的情况大约 3 小时后,我没有看到 angular 的任何官方建议,所以这只是我的意见。我只是说我认为这个解决方案将字段值设置为指令的使用者,这在我需要在整个页面中进行大量自动完成时并不理想,因此最好编写一个组件而不是输出事件指令。 好的,我明白你的意思了。我猜你已经得到了解决方案,否则我们可以检查它在 NgModel 实现中是如何完成的。

以上是关于如何在 Angular 世界之外发生更改时更新 Angular 2 Reactive 表单字段的主要内容,如果未能解决你的问题,请参考以下文章

有没有办法观察从 AngularJS 世界之外触发的属性更改?

Angular2:观察角度之外的外部变量

Angular 2 - 在 Promise 中更改模型时 GUI 不会更新

Angular2中的属性更改时数据绑定不更新

Angular:防止资产文件夹发生更改时自动重新编译

在Angular中更改模型后如何更新视图?