27

I'm currently trying to get the values a user would insert into an input form. In vanilla javascript, I can just target the element by id or class, etc, and then I can just use the .value method to actually get in use that method. For some reason, typescript cannot do that, which I do not understand because typescript is a superset of javascript. Is there a specific way to get a value from an input element in pure typescript or do I have to use angular or something?

Typescript code:

interface IUserFoodOptions {
    food: string;
    calories: number;
    foodDate: any;
}

class Food implements IUserFoodOptions {
    food: string;
    calories: number;
    foodDate: any;

    // store all the calories in an array and calculate the total amount of calories
    caloriesArray: number[] = [];

    // constructor
    constructor(food: string, calories: number, foodDate: any) {
        this.food = food;
        this.calories = calories;
        this.foodDate = foodDate;
    }
}

// event listener for when the add food button is clicked
let addFood = document.getElementById("add-food-button").addEventListener("click", () => {
    // get the values from inputs and store them in an array
    let foodName = document.getElementById("food-name-val");
    let foodCalories = document.getElementById("calories-val");
    let dateVal = document.getElementById("date-val");

    // store these values in a list and display them below
    // user will have the ability to edit and delete them
    // am I create event listeners within event listeners
});
AfternoonTiger
  • 357
  • 1
  • 4
  • 10
  • 1
    Using `as HTMLInputElement` worked for me: https://stackoverflow.com/a/52495421/470749 – Ryan Apr 11 '20 at 15:34

4 Answers4

43

If you are using an editor like VSCode to write Typescript, I've found the ability to inspect code very valuable in learning more about what's occurring in the typing system. In VSCode you can right click on the method(or type) and choose Go to definition.

Inspecting the method in your question, getElementById, you can see it returns an HTMLElement. This type doesn't have a value property on it. This makes sense as getElementById can return any HTMLElement on the page as long as it has an id attribute. Not every HTMLElement though has a value property(for instance a div/span/p, etc).

Since you know what type you are expecting, but the type system can't, to get this to work, you have to tell Typescript what type of element you expect to be selecting. You would do that through casting the type of the selected element as follows: const inputElement = <HTMLInputElement> document.getElementById("food-name-val"); or const inputElement = document.getElementById("food-name-val") as HTMLInputElement;

Now, since Typescript recognizes the selected element as an HTMLInputElement, it won't error when you access the value property on it.

In your case that would look like: let foodName = (document.getElementById("food-name-val") as HTMLInputElement).value;

peinearydevelopment
  • 11,042
  • 5
  • 48
  • 76
19

Yeah, TypeScript has this "little issue", but it is for safety.
You can get the input value doing something like this:

var inputValue = (<HTMLInputElement>document.getElementById(elementId)).value;

You can see more about this casting <> thing here: TypeScript: casting HTMLElement

Hope it works!

Richard Nikolas
  • 505
  • 4
  • 11
8

You can get the value of an input in TypeScript. For a number,

var num = parseFloat((<HTMLInputElement>document.getElementById("myValue")).value);
                                 or 
let num : number = parseFloat((<HTMLInputElement>document.getElementById("myValue")).value);

Strings;

var str = (<HTMLInputElement>document.getElementById("myUnit")).value; 
         or
let str : string = (<HTMLInputElement>document.getElementById("myUnit")).value; 

It's important to cast HTMLElement to HTMLInputElement, otherwise 'value' property doesn't exist for HTMLElement in TypeScript and TypeScript compiler will show an error.

// event listener for when the add food button is clicked
let addFood = document.getElementById("add-food-button").addEventListener("click", () => {
  // get the values from inputs and store them in an array
  let foodName = (<HTMLInputElement>document.getElementById("food-name-val")).value;
  let foodCalories = parseFloat((<HTMLInputElement>document.getElementById("calories-val")).value);
  let dateVal = (<HTMLInputElement>document.getElementById("date-val")).value;
  // And so on ...
});
Akolade Adesanmi
  • 1,152
  • 11
  • 15
3

I find the following code more readable:

const user: string = document.querySelector<HTMLInputElement>('input[name="user"]').value;
andylib93
  • 133
  • 8
  • The only thing this "new" answer does is to repeat what half of the other answers are already saying, including the accepted answer. – Tyler2P Nov 07 '21 at 10:58
  • 1
    Well yes but casting with brackets, for me, is not that instantly understandable. Personal preference is all. – andylib93 Nov 07 '21 at 12:47
  • 1
    This helped me understand that there was a different way to write it, so +1. From a .NET/Java background, this style feels more familiar – dst3p Feb 17 '22 at 02:46
  • 1
    This is actually better than the other answers because it allows the result to still be undefined according to the type system if it can't find the element. – Devon Rutledge Jun 09 '22 at 22:26