Fixing "Cannot read property 'data1' of null" 5 different ways

I am getting the error: “Uncaught TypeError: Cannot read property ‘data1’ of null”

This page tells me what is wrong:

I have implemented the suggestions and still the error persists. I need another set of eyes:

First, here’s the essential setup:

    <form id="userInput" action ="" method="GET"> 
        <input class="buttonClass" type="button" id="importIt" value="Save Data" onclick="persistData(this.form)"> 
        <!-- No response with this: <input type="button" class="buttonClass" id="importIt" value="Save Data"> -->
        <input class="inputClass" id="data2" type="text" value="" placeholder="Body">

At bottom of page:

        <script src="../js/setups-import.js" defer></script>
        <!-- <script>importIt.addEventListener('click', persistData);</script> -->
        <script>dropDatabase.addEventListener('click', dropDb);</script>

External setups-import.js:

function persistData(data1, data2) {
// get form entries
var form = document.querySelector("#userInput");
   // OLD: var form = document.getElementById("userInput");
    var formdata1 = form.data1.value;   // ERROR POINTS TO THIS LINE
    var formdata2 = form.data2.value;

Steps I’ve taken:

  1. Make sure the userInput ID is spelled correctly everywhere.
  2. Put the JS after the HTML, just before /body, then as an external script.
  3. Added “defer” to the script at bottom of the page.
  4. Used eventListener at bottom of page instead of onclick on the buttons.
  5. Changed getElementById to querySelector.

What am I missing? I think I covered all the bases. I’m sure it is something ridiculously simple.

Where in your form is the data1 field?

Form looks like this now. Still gets the error, though:

<form id="userInput" action ="" method="GET"> 
  <input class="filled-in" id="data1" type="text" value="" placeholder="Title"> 
  <input class="filled-in" id="data2" type="text" value="" placeholder="Body"> 
  <a href="#" class="black-text light-blue accent-1 btn left" id="importIt" onclick="persistData(this.form)">Save Data</a> 

I had neglected to show the data1 input earlier. Sorry about that.

I have a little more progress, but hitting a different roadblock. I successfully got around the error message with:

function persistData(data1, data2) {
// get form entries
   var formdata1 = document.getElementById("data1").value;
   var formdata2 = document.getElementById("data2").value;

I can successfully add them to localStorage with:

// key, value pair into localStorage
    localStorage.setItem('formdata1Set', formdata1); 
    localStorage.setItem('formdata2Set', formdata2); 
// set the current time as the id to make it unique id
    var d = new Date();
    var new_id = d.getTime();
    localStorage.setItem('new_idSet', new_id);
// check form entries on console
    console.log("formdata1Set = " + formdata1); 
    console.log("formdata2Set = " + formdata2);
    console.log("new_idSet = " + new_id);
// proceed to next function

These values show in the console. But then then it goes to startDB:

function startDB() {
    var db = window.openDatabase("Database", "1.0", "DEMO", 2000000);
    db.transaction(populateDB, errorCB, successCB);

and console displays the errorCB (instead of populateDB, which would insert data into DB):

    if (err.code == "5") {
        console.log("5 - SYNTAX_ERR: The statement failed because of a syntax error, or the number of arguments did not match the number of ? placeholders in the statement, or the statement tried to use a statement that is not allowed, such as BEGIN, COMMIT, or ROLLBACK, or the statement tried to use a verb that could modify the database but the transaction was read-only.");

I’ve changed the inputs in different ways, but they are currently:

<input    id="data1" type="text" value="" maxlength="40" class="filled-in"> 
<textarea id="data2" type="text" value="" rows="200"></textarea>

I don’t enter much content in the fields, so it can’t be the length of the content setting off the error. I get this error when contents are all numbers or all letters.

Okay, let’s start with the persistData() function.

What values does it receive?

When your onclick event is triggered, it passes a form reference to the persistData() function, so you really should change the (data1, data2) parameters to (form) instead.

But, that doesn’t change how your existing code works. So far as I can tell from a jsfiddle test, it seems to work as expected.

I would make some structural changes though so that it’s more in line with expected coding conventions.

For example, I would remove the inline onclick attribute and use the addEventListener that you had in the first post. It’s best though to not rely on the global reference to id atributes, as those can be easily overwritten resulting in unexpected behaviour. Use getElementById or querySelector instead.

var saveLink = document.getElementById("importIt");
savelink.addEventListener("click", persistData);

The persistData function will be given an event object, so it’s best to be ready for that too.

function persistData(evt) {

You can then leverage the information from that event object to obtain a reference to the form.
Normally if it’s an input field or a button you can just get their form property for access to the form, but a link doesn’t work that way.

When using links, I find it best to walk up the DOM looking for a form tag instead.

function getForm(el) {
  var form;
  if (el.form) {
    return el.form;
  form = el;
  while (form.nodeName !== "FORM") {
    form = form.parentNode;
    if (form.nodeName === "HTML") {
    	return false;
  return form;
function persistData(evt) {
    var form = getForm(;

Then you can move on to the rest of the code from there, using the elements collection to obtain form fields.

  var formdata1 = form.elements.data1.value;
  var formdata2 = form.elements.data2.value;

The important thing here is that less assumptions are being made, which results in code that is easier to maintain and troubleshoot.

The updated code can be found at

Wow, what an education! I know that HTML5/CSS is moving along too fast to keep up – it makes sense that JS is doing the same.

“What values does it receive?” you asked. Answer: anything typed or pasted into the input fields. I still need to clean/validate the fields. One thing at a time there.

I am getting the same output as before – it’s saved in localStorage but getting an errorCB of status 5. So it is failing at the point of the database entry. I suspect I’ve got to bone up on SQLite. I grabbed this code from webSQL from an earlier app I made. WebSQL is deprecated now, but worked fine initially.

I’ve been testing using that test code on Chrome and found no error. This could be because we are not using the same code as you, or the same browser.

Which browser are you using? If the error cannot be duplicated in the same browser, then we may need to have you put together the code on a page somewhere so that we can experience and troubleshoot the error.

Thanks, Paul. There are a variety of things happening in the code, which I have been previewing on Chrome in a Mac:
User adds content to input fields.
Save button is pushed, which starts this cascade of events:

  1. Input is saved to DB.
  2. DB outputs data as a table with a delete button for each row.
  3. DB outputs all data in the DB in a larger field to display the contents. (There is no editing of the field contents, but I should add that functionality.)

I had earlier created this and made an article on it here: It includes screenshots at the bottom to illustrate.

I had packaged this recent version as a Cordova app for Android and viewed it in my Android phone, and I see only the word null showing as outputs, which Chrome did not show, probably because it can’t parse the cordova.js file or plugin that’s made for devices.

I have a account, but I’m not sure it would work outside of the Cordova environment, since I’m trying to integrate the SQLite Cordova plugin. I can put it all on the pen anyway and see what happens.

Here is the codepen:

Currently that’s not working because window.sqlitePlugin is undefined.
Is that supposed to be a library that you’re trying to reference?

Yes, the plugin requires that. But we might be able to make it work without it for an HTML5 database.

This topic was automatically closed 91 days after the last reply. New replies are no longer allowed.