Change an input's ngModel value using a directive Angular 2
Solution 1
I ended up getting this to work, although I don't understand why it works because I'm not binding ngModelChange
to the element...but it works.
Directive:
/// <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));
});
}
}
Component Template:
<input type="text"
class="form-control"
ngControl="address"
id="subjectAddress"
placeholder="Enter a location"
[(ngModel)]="subject.address"
#address="ngForm"
google-places
required>
Solution 2
I would inject the ControlValueAccessor
associated with your input. Here is a sample:
@Directive({
selector: '[test]'
})
export class TestDirective {
constructor(@Inject(NG_VALUE_ACCESSOR) private valueAccessor:ControlValueAccessor) {
setTimeout(() => {
this.valueAccessor[0].writeValue('test');
}, 1000);
}
}
See this plunkr for example: https://plnkr.co/edit/owhBHdBncAxlzwJ8xkfq?p=preview.
Comments
-
sharpmachine over 1 year
I'm stuck on how to access and change an inputs
ngModel
value using a directive. The outcome of the issue is that the model's address value doesn't update when I select the desired address...it's just set to what I actually typed into the input, rather than final value of the input.I type '830':
I select '8300 Fauntleroy Way Southwest, Seattle, WA, United States':
Resulting value:
{ address: '830' }
Desired value:
{ address: '8300 Fauntleroy Way Southwest, Seattle, WA, United States' }
In AngularJS I could do this:
(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()); }); }); } } })();
But now that I'm trying to convert it Angular 2, I'm a little stuck. Here's what I have so far on the conversion:
/// <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)); } }
Usage:
<input type="text" ngControl="address" placeholder="Enter a location" [(ngModel)]="subject.address" #address="ngForm" google-places required>
The heart of the issue is I don't understand how to do the equivalent of
model.$setViewValue(element.val());
in Angular 2.Any assistance would be greatly appreciated.
-
sharpmachine almost 8 yearsThanks. However this updates the value of the input but not the value of the model. I've created a plunker to further explain the issue: plnkr.co/edit/1xMjzo
-
Brad Kent over 7 yearsis ngOnInit in a separate directive? How is the directive getting access to the component?
-
Brad Kent over 7 yearsThis does not work for me. I'm assuming it probably worked for 2.0.0-rc.1 (what was avail on June 2), but probably broken in 3 different ways since then.
-
Maxim Kuzmin almost 5 years"I don't understand why it works because I'm not binding
ngModelChange
to the element" - you actually do, whe you use[(ngModel)]="subject.address"
it is translated to[ngModel]="subject.address"
and(ngModelChange)="subject.address = $event"