Search code examples
javascriptfunctionparametersqueryselector

Practising on creating functions and passing params | Getting null when trying to use params on querySelectors


I'm newbie in Javascript, I was practising with functions & params and I "hit a wall" when tried to use functions to do some changes in DOM, by passing params in those functions that would do the job. in the browser's console I'm getting:

Uncaught TypeError: document.querySelector(...) is null
classAdder script.js:25
<anonymous> script.js:48

25th line is the line inside the classAdder function and 48th is the calling of classAdder.

Thank you in advance.

// Function decleration
function createArticle(h1, p) {
  let art = document.createElement("article");
  let data = document.createTextNode("<h1>" + [h1] + "</h1><p>" + [p] + "</p>");
  art.appendChild(data);
  return art;
}

// Arrow Function
const byTagElementAdder = (whereadd, whatadd) => {
  document.getElementsByTagName(CSS.escape(whereadd)).innerHTML = whatadd;
};

// Function expression
const classAdder = function (element, classname) {
  document
    .querySelector(CSS.escape(element))
    .setAttribute("class", CSS.escape(classname));
};

// Arrow function
const styleAdder = (element, style) => {
  document
    .querySelector(CSS.escape(element))
    .setAttribute("style", CSS.escape(style));
};

//
// Using the functions
// Creating new article
const firstArt = createArticle(
  "The H title",
  "The paragraph lorem ipsum bla bla"
);

// adding article in body
byTagElementAdder("body", firstArt);

// adding some style and class
classAdder(firstArt, "art");
styleAdder(firstArt, "width: 100%; margin: 0 auto; padding: 2rem 0 ;");

Solution

  • Here are some things I changed to make your code work:

    1. The reason you are getting this error Uncaught TypeError: document.querySelector(...) is null is because you are using CSS.escape which needs a string but you are passing in the dom element. So you can just use .setAttribute right on the element.
    2. Your byTagElementAdder function was trying to insert innerHTML to an array. I've switched it to reference the first element of the array and use appendChild function instead
    3. In your createArticle function, you are using a createTextNode but I think you would want to use creatElement for the h1 and p1 tag as you did for the article element.

    Here's a code snippet

    function createArticle(h1, p) {
      let art = document.createElement("article");
        // this creates text as opposed to the h1 and p elements, which is what I think yu want  
      let data = document.createTextNode("<h1>" + [h1] + "</h1><p>" + [p] + "</p>");
      art.appendChild(data);
      return art;
    }
    
    // Arrow Function
    const byTagElementAdder = (whereadd, whatadd) => {
        // getElementsByTagName returns an array so you want to choose a value within it
      document.getElementsByTagName(CSS.escape(whereadd))[0].appendChild(whatadd)
    };
    
    // Function expression
    const classAdder = function (element, classname) {
        //once you pass in an element you don't need to use document.querySelector, you already have the document   
      element
        .setAttribute("class", CSS.escape(classname));
    };
    
    // Arrow function
    const styleAdder = (element, style) => {
      //once you pass in an element you don't need to use document.querySelector, you already have the document 
      element
        .setAttribute("style", CSS.escape(style));
    };
    
    //
    // Using the functions
    // Creating new article
    const firstArt = createArticle(
      "The H title",
      "The paragraph lorem ipsum bla bla"
    );
    
    // adding article in body
    byTagElementAdder("body", firstArt);
    
    // adding some style and class
    classAdder(firstArt, "art");
    styleAdder(firstArt, "width: 100%; margin: 0 auto; padding: 2rem 0 ;");
    <body>
    
    </body>