6

Using Angular 4 (typescript), I have the below HTML code:

 <div *ngIf="dataService.selected_markers.length == 0" id="tsnPasteContainer">
      <form style="width: 100%; height: 100%">
        <textarea id="tsn_list" style="width: 100%; height: 100%" type="text" name="tsn_list" placeholder="e.g. 2001311,2425302,2153542,2435974"></textarea>
      </form>
    </div>

I am trying to get the data that the user is typing into the textarea using:

public parseTSNs(){
    let tsnString = document.getElementById("tsn_list").value;
    console.log("User inputted string: " + tsnString);
}

This function is called by a button.

The code is not compiling due to:

Property 'value' does not exist on type 'HTMLElement'

This should be a simple function. What am I doing wrong? W3schools "getting values from textarea" shows '.value' as the required function!

Jeremy Thille
  • 26,047
  • 12
  • 43
  • 63
dandev91
  • 1,691
  • 3
  • 22
  • 34

4 Answers4

37

You just have to assert that the type of your element is HTMLTextAreaElement. Because document.getElementById returns HTMLElement and not all html elements have the value property:

let tsnString = (document.getElementById("tsn_list") as HTMLTextAreaElement).value;

But seeing as you use Angular, you should probably be using data binding instead of querying the values yourself

Saravana
  • 37,852
  • 18
  • 100
  • 108
  • This is the answer I was looking for. Although I can (and will) just use data binding, I couldn't figure out why the vanilla JS code wasn't working when I've done this in the past without any issue. I have never used "as" to assert something before - nor did I think it was necessary. So out of curiosity, why did I have to do the "assert" to get this working in this scenario when @Ionut 's snippet worked perfectly without having to assert anything. – dandev91 Jul 16 '17 at 23:36
  • I just found this extract somewhere by Googling typescript compiling and HTMLElements: The "problem" is that typescript is typesafe. So the document.getElementById() returns the type HTMLElement which does not contain a value property. The subtype HTMLInputElement does however contain the value property. – dandev91 Jul 16 '17 at 23:47
  • @fila You are correct. lonut's code is plain JS. TypeScript provides additional type checking. – Saravana Jul 17 '17 at 00:25
3

I had faced a similar issue while setting the value of a cell in the table.

I was adding the data as follows:

document.getElementById("table_id").rows[0].cells[0].innerHTML = "data_to_be_added";

And I was getting the following error:

error TS2339: Property 'rows' does not exist on type 'HTMLElement'

Property 'cells' does not exist on type 'HTMLElement'

So I added the following tag and the ERROR got resolved.

(document.getElementById("table_id") as any).rows[0].cells[0].innerHTML = "data_to_be_added";

Here, you are expicitly changing the type of the variable as any.

Community
  • 1
  • 1
pppai
  • 71
  • 5
0

You should use: [(ngModel)]='yourValue' to bind data to your controller. Textarea doesn't use value parameters.

Pleas read more information about HTML tag and its attributes hire.

kris_IV
  • 2,396
  • 21
  • 42
  • Oh, yes it does use value. It's just a bit different from other inputs, because it's between ``. – Ionut Necula Jul 11 '17 at 07:41
  • Oh, yes it is. Is a multi-line text input. But I get the `[(ngModel)]='yourValue'`. That you are right. – Ionut Necula Jul 11 '17 at 07:47
  • In accordance with definition - true. But generally it's completely different than input in support attributes. – kris_IV Jul 11 '17 at 07:49
  • 1
    In terms of `HTML` attributes, yes. But that does not mean you can't use `$('textarea').val()` or `document.getElementById('some_textarea_id').value` to get the **value** of it. – Ionut Necula Jul 11 '17 at 07:52
  • This is what my confusion was. ".val()" and ".value()" were not compiling at all and your snippet extract above (which has worked for me in the past) worked fine. But @Saravana 's code to make the assert as HTMLTextAreaElement worked perfectly... I never thought that was necessary. – dandev91 Jul 16 '17 at 23:44
0

Although it's not supposed to work like that, If you want to do it like this, first give your tag a reference with a # :

<div *ngIf="dataService.selected_markers.length == 0" id="tsnPasteContainer">
    <form style="width: 100%; height: 100%">
        <textarea #myTA style="width: 100%; height: 100%" type="text" name="tsn_list" placeholder="e.g. 2001311,2425302,2153542,2435974"></textarea>
    </form>
</div>

Then, in your component, import this :

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

Declare a variable matching your reference :

@ViewChild('myTA') myTextArea: ElementRef;

In your method :

parseTSNs() {
    let el = this.myTextArea.nativeElement as HTMLElement;
    console.log(el.value);
}
  • I should have specified in the question that I was specifically looking for the reason why the vanilla JavaScript code wasn't working in Angular. Although I agree entirely that this is the better method. – dandev91 Jul 21 '17 at 06:03
  • Well no, the best method is to use `ngModel`, the solution you want is just plain nasty. There's no need to use Angular if you use native JS ! –  Jul 21 '17 at 11:19