2

How do I access the value property of an element in the component in Angular2?

In the Template:

<input #myInput (keyup.enter)="onInput(myInput)"/> 

In the Component code:

import {ElementRef} from '@angular/core';
...
onInput(latLngInputElement: ElementRef) {
  // I want to access the value property of the <input> element here, and
  // modify it so that it is reflected back in the template.

I know that I can pass the myInput.value into the code, but I need the reference so that I can also use the function to update the .value property of the element.

I'd like to know if there is a way to do this that does not involve two way binding to a global variable, because I think it is cleaner to have as few globals as possible. Thanks!

JohnV
  • 31
  • 1
  • 4

1 Answers1

2

Angular's solution to this would be two-way binding of the input model to a variable in the component. This wouldn't involve dirtying up the global scope, expecially if you declare the var with a let as per Typescript's docs.

I'd like to know if there is a way to do this that does not involve two way binding to a global variable, because I think it is cleaner to have as few globals as possible. Thanks!

I understand this, but invoking ElementRef might be the worse of two evils here. The Angular docs greatly discourage using it as Angular already does so much to handle the DOM API.

However, you should be able to get the value from latLngInputElement.value.

If you're looking for a cleaner solution:

I would highly recommend checking out Angular's FormBuilder to build a model-driven form as opposed to a template-driven one. It's a very elegant way to control form values on a page programatically instead of on the template. Scotch.io has an excellent blog post on it. It's well worth learning.

Good luck!

joh04667
  • 7,159
  • 27
  • 34
  • I use ReactiveForms, so I can't use ngModel (throws error, I suppose it doesn't work when using reactive forms), and also I don't want to include one dummy input in any of my formGroup groups. I just need it for the user to type something, but not be part of the programatically created form (but it needs to be among the other, visually, so I can't just put it anywhere). And I also need to be able to set it's value after certain actions. – MrCroft May 10 '17 at 18:26
  • In my template I have ``. Then, I get the reference using `@ViewChild('myInput') inputElement: ElementRef;` If I console log `this.myInput.nativeElement.value` I get the value. But `this.myInput.nativeElement.setAttribute('value', 'xxx');` doesn't do anything. Am I doing something wrong? I assume `setAttribute` is a valid method, since there are no errors on build (and it's there to just pick from the autocomplete list). I've also tried `@ViewChild('myInput') inputElement: HTMLInputElement;`, there's no `value()` or `setValue()` method that can be used. – MrCroft May 10 '17 at 18:33
  • If you are using the `ReactiveFormsModule` and have a FormGroup set up, you would assign the input to a `FormControl` using `` You can interact with the field through the `FormGroup`, i.e `formGroupName.controls['controlName'].setValue(value)`. As arule of thumb, *always* avoid interacting with the DOM with Angular. The framework does it for you. – joh04667 May 10 '17 at 18:43
  • I know. But that's what I'm trying to avoid. If that input's data isn't relevant for sending to the server, I think it shouldn't be part of any form group, rather than having to "filter" it out before sending data to the server. I would prefer not to touch the DOM, yes... But how do I tell Angular to "empty" out that input at a time of my choosing, just by having the template reference #myInput? – MrCroft May 10 '17 at 21:45
  • You wouldn't have to use a template variable, and you wouldn't want to either, as Angular wouldn't call change detection on it. It would likely crash the page. You can clear the value with `formGroupName.controls['controlName'].reset()`. Either way, you can't clear an input value by setting an attribute on the element. If you don't want it in the FormGroup, take it out of the group and use two-way binding on it. – joh04667 May 10 '17 at 23:40
  • I did try to use two-way data binding, but it seems that using `[(ngModel)]` inside the template of a reactive form throws error. I suppose that I'd have to include the `FormsModule` to use `[(ngModel)]`. Never thought we could have both `FormsModule` and `ReactiveFormsModule` in our app, at the same time. Because of how elements flow (where it is positioned in the form), I have to have it within the
    tags (not to horse around with absolute positioning and such in a responsive app). I guess I have no choice but to include it in the form group, instead of adding another module
    – MrCroft May 11 '17 at 09:03