Search code examples
javascripttypescriptdomnavbar

How do I make HTML code using typescript?


I have no experience with javascript and typescript. When I used PHP I made a navbar into a function that would echo the html code. Is this also achievable using typescript? I have made a function that returns a string of html code, but I don't know how to actually make it render the html when I call the function on my html page (if the typescript code would even be correct). My school demands that I use typescript.

export function navbar(): string {
    const menuItems: MenuItems = {
        Home: "index.html",
        About: "about.html",
        FAQ: "faq.html",
        Contact: "contact.html",
    };
    let htmlCode: string = "<nav><ul>";

    for (const [key, value] of Object.entries(menuItems)) {
        htmlCode += `<li><a src="${key}">${value}</a></li>`;
    }
    htmlCode += "</nav></ul>";

    return htmlCode;
}

edit: I now have tried this

type MenuItems = {
    [key: string]: string;
};

export function createNavbar(): void {
    const navigation: HTMLElement = document.createElement("nav");
    const unorderedList: HTMLUListElement = document.createElement("ul");
    const menuItems: MenuItems = {
        Home: "index.html",
        About: "about.html",
        FAQ: "faq.html",
        Contact: "contact.html",
    };

    for (const [key, value] of Object.entries(menuItems)) {
        const listItem: HTMLElement = document.createElement("li");
        const anchor: HTMLAnchorElement = document.createElement("a");

        anchor.textContent = key;
        anchor.href = value;

        listItem.appendChild(anchor);
        unorderedList.appendChild(listItem);
    }

    navigation.appendChild(unorderedList);
    document.body.appendChild(navigation);
}

and this for my html

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <link rel="stylesheet" type="text/css" href="../assets/css/style.css" />
    <title>test</title>
</head>
<body>
    <script src="../src/common.ts"></script>
    <script>createNavbar()</script>
</body>
</html>

it still does not seem to work. I've got a blank page


Solution

  • You're almost there.

    There are a handful of ways to buld DOM Fragments but one way is to repeatedly use:

    • document.createElement() // to create the element before customising it
    • myParentElement.appendChild(myElement) // appends the new element to its parent

    Working Example

    const buildNavbar = () => {
    
      const menuItems = {
        Home: "index.html",
        About: "about.html",
        FAQ: "faq.html",
        Contact: "contact.html",
      };
      
      // BUILD <nav> ELEMENT
      const navbarNavigation = document.createElement('nav');
    
      // BUILD <ul> ELEMENT
      const navbarUnorderedList = document.createElement('ul');
    
      for (const [key, value] of Object.entries(menuItems)) {
    
        // BUILD <li> ELEMENT
        const navbarListItem = document.createElement('li');
        
        // BUILD <a> ELEMENT AND APPEND TO <li> ELEMENT
        const navbarAnchor = document.createElement('a');
        navbarAnchor.setAttribute('href', value);
        navbarAnchor.textContent = key;
        navbarListItem.appendChild(navbarAnchor);
    
        // APPEND <li> ELEMENT TO <ul> ELEMENT
        navbarUnorderedList.appendChild(navbarListItem);
      }
      
      // APPEND <ul> ELEMENT TO <nav> ELEMENT
      navbarNavigation.appendChild(navbarUnorderedList);
    
      // APPEND <nav> ELEMENT TO <body> ELEMENT
      document.body.appendChild(navbarNavigation);
    }
    
    buildNavbar();


    N.B. Not uncommonly you'll see approaches which concatenate strings / template literals and then utilise the innerHTML property, something like this:

      const menuItems = {
        Home: "index.html",
        About: "about.html",
        FAQ: "faq.html",
        Contact: "contact.html",
      };
    
    const navbarNavigation = document.createElement('nav');
    
    let navbarNavigationChildren = '<ul>';
    for (const [key, value] of Object.entries(menuItems)) {
      navbarNavigationChildren += `<li><a href="${value}">${key}</a></li>`;
    }
    navbarNavigationChildren += '</ul>';
    
    navbarNavigation.innerHTML = navbarNavigationChildren;
    document.appendChild(navbarNavigation);
    

    Which is much closer to how you'd approach the issue in PHP.

    However, my own experience is that as you get used to creating DOM Nodes and thinking in those terms, the approach where you build a string of markup and append it via .innerHTML loses quite a lot of its appeal.

    Although popular, the latter approach is something like building JSON via string concatenation and then converting that string into an object via JSON.parse(), rather than simply... building an object.