【问题标题】:Change an input's ngModel value using a directive Angular 2使用指令 Angular 2 更改输入的 ngModel 值
【发布时间】:2016-10-02 14:32:52
【问题描述】:

我不知道如何使用指令访问和更改输入 ngModel 值。问题的结果是,当我选择所需的地址时,模型的地址值没有更新……它只是设置为我实际输入到输入中的内容,而不是输入的最终值。

我输入“830”:

我选择“8300 Fauntleroy Way Southwest, Seattle, WA, United States”:

结果值:

{
  address: '830'
}

期望值:

{
  address: '8300 Fauntleroy Way Southwest, Seattle, WA, United States'
}

在 AngularJS 中我可以这样做:

(function() {
  'use strict';

  angular
  .module('casemanagerApp')
  .directive('googleplace', googleplace);

  function googleplace() {

    var directive = {
      require: 'ngModel',
      link: link
    };

    return directive;

    function link(scope, element, attrs, model) {
      var options = {
        types: [],
        componentRestrictions: {}
      };
      scope.gPlace = new google.maps.places.Autocomplete(element[0], options); // jshint ignore:line

      google.maps.event.addListener(scope.gPlace, 'place_changed', function() { // jshint ignore:line
        scope.$apply(function() {
          model.$setViewValue(element.val());
        });
      });
    }
  }

})();

但现在我正在尝试将其转换为 Angular 2,我有点卡住了。以下是我目前对转换的了解:

/// <reference path="../../../../typings/browser/ambient/googlemaps/index.d.ts"/>

import { Directive, ElementRef, OnInit } from '@angular/core';

@Directive({
  selector: '[google-places]'
})
export class GooglePlaces implements OnInit {

  constructor(private _el: ElementRef) { }

  ngOnInit() {
    let gPlace = new google.maps.places.Autocomplete(this._el.nativeElement);
    google.maps.event.addListener(gPlace, 'place_changed', () => console.log(this._el.nativeElement));
  }

}

用法:

<input type="text"
       ngControl="address"
       placeholder="Enter a location"
       [(ngModel)]="subject.address"
       #address="ngForm"
       google-places
       required>

问题的核心是我不明白如何在 Angular 2 中做相当于 model.$setViewValue(element.val()); 的操作。

任何帮助将不胜感激。

Plunker

【问题讨论】:

  • 这看起来相关stackoverflow.com/questions/36106350/…也许你可以得到一些想法。
  • 嗨@GünterZöchbauer。不幸的是,这些解决方案对我不起作用。我创建了一个 Plunker 来更好地说明这个问题。 plnkr.co/edit/1xMjzo
  • Thierrys 的方法怎么样?
  • @GünterZöchbauer 是的,这也不起作用。它们都只是改变了输入的值而不更新模型的值。

标签: angular angular2-directives


【解决方案1】:

我最终让它工作了,虽然我不明白它为什么工作,因为我没有将 ngModelChange 绑定到元素......但它工作。

指令:

/// <reference path="../../../../typings/browser/ambient/googlemaps/index.d.ts"/>

import { Directive, ElementRef, Output, EventEmitter, OnInit, NgZone } from '@angular/core';

@Directive({
  selector: '[google-places]'
})
export class GooglePlaces implements OnInit {
  @Output() ngModelChange: EventEmitter<any> = new EventEmitter(false);

  options = {
    types: ['address'],
    componentRestrictions: { country: "us" }
  };

  constructor(
    private _el: ElementRef,
    private _ngZone: NgZone) { }

  ngOnInit() {
    let gPlace = new google.maps.places.Autocomplete(this._el.nativeElement, this.options);
    google.maps.event.addListener(gPlace, 'place_changed', () => {
      this._ngZone.run(() =>
        this.ngModelChange.emit(this._el.nativeElement.value));
    });
  }

}

组件模板:

<input type="text"
            class="form-control"
            ngControl="address"
            id="subjectAddress"
            placeholder="Enter a location"
            [(ngModel)]="subject.address"
            #address="ngForm"
            google-places
            required>

【讨论】:

  • 这对我不起作用。我假设它可能适用于 2.0.0-rc.1(6 月 2 日可用),但从那时起可能以 3 种不同的方式被破坏。
  • “我不明白它为什么会起作用,因为我没有将 ngModelChange 绑定到元素” - 实际上,当您使用 [(ngModel)]="subject.address" 时,它会被转换为 [ngModel]="subject.address" 和 @ 987654327@
【解决方案2】:

我会注入与您的输入相关的ControlValueAccessor。这是一个示例:

@Directive({
  selector: '[test]'
})
export class TestDirective {
  constructor(@Inject(NG_VALUE_ACCESSOR) private valueAccessor:ControlValueAccessor) {
    setTimeout(() => {
      this.valueAccessor[0].writeValue('test');
    }, 1000);
  }
}

请参阅此 plunkr,例如:https://plnkr.co/edit/owhBHdBncAxlzwJ8xkfq?p=preview

【讨论】:

  • 谢谢。但是,这会更新输入的值,但不会更新模型的值。我创建了一个 plunker 来进一步解释这个问题:plnkr.co/edit/1xMjzo
【解决方案3】:

这是我用 datepicker 做的,可能会有所帮助。

//Create a method in your component to change the model
dateChanged(date) {
   this.hero.bday = date;
}

public ngOnInit() {
    //CREATE A REFERERENCE TO YOUR COMPONENT
    var component:CreateEventComponent = this;
    $("#bday").datepicker({
        dateFormat: "dd-mm-yy",
        altFormat: "dd-mm-yy",
        onSelect: function (dateText, datePicker) {
            //UPDATE YOUR MODEL FORM JQUERY CODE.
            component.dateChanged(dateText);
        }
    });
}

【讨论】:

  • ngOnInit 在单独的指令中吗?指令如何访问组件?
猜你喜欢
  • 1970-01-01
  • 2019-06-29
  • 2017-06-27
  • 2023-03-31
  • 1970-01-01
  • 1970-01-01
  • 2017-04-02
  • 2021-09-12
  • 2016-06-23
相关资源
最近更新 更多