Why does JS stop rendering the 'Details" section when I assign the updateResults functions to use imported data?

I’m currently working on the WorkAround Explorer project of the Learn Intermediate JavaScript course and I’ve come across this issue which I cannot solve. I’m particularly stuck on step 9. which requires updating the variables inside the updateResults function so that they are assigned to the functions I imported from workAroundModule.js. Despite having succeeded in the previous steps (I think) when I changed the assigned values JS doesn’t render the last section of the table (Details) and instead shows ‘…’ only.

Here is what my code looks like in each file.

Index.html

<!DOCTYPE html> <html> <head> <meta charset="utf-8"> <title>WorkAround</title> <link rel="stylesheet" type="text/css" href="index.css" /> <script type="module" src="main.js" defer></script> </head> <body> <main> <!-- The roles and companies <section>s are dynamically created in main.js with renderInputButtons() --> <section id="resultsContainer"> <h3>Details:</h3> <p id="salarySelected"> ... </p> <p id="salaryAverageByRole"> ... </p> <p id="salaryAverageByCompany"> ... </p> <p id="salaryAverageIndustry"> ... </p> </section> </main> </body> </html>

mains.js

// Import statements import { getRoles, getCompanies } from "./modules/salaryData.js"; export { getAverageSalaryByRole, getAverageSalaryByCompany, getSalaryAtCompany, getIndustryAverageSalary } from "./modules/workAroundModule.js"; // TODO: Get the companies and roles using the salaryData module. const companies = getCompanies(); const roles = getRoles(); // Create input buttons for every company and role represented in the data. renderInputButtons(companies, 'company'); renderInputButtons(roles, 'role'); // This function will create a new <section> with radio // inputs based on the data provided in the labels array. function renderInputButtons(labels, groupName) { const container = document.createElement('section'); container.setAttribute('id', `${groupName}Inputs`); let header = document.createElement('h3'); header.innerText = `Select a ${groupName}`; container.appendChild(header); labels.forEach(label => { // For each label... // Create the radio input element. let divElement = document.createElement('div'); divElement.setAttribute('class', 'option'); let inputElement = document.createElement('input'); inputElement.setAttribute('type', 'radio'); inputElement.setAttribute('name', groupName); inputElement.setAttribute('value', label); divElement.appendChild(inputElement); // Create a label for that radio input element. let labelElement = document.createElement('label'); labelElement.setAttribute('for', label); labelElement.innerText = label; divElement.appendChild(labelElement); // Update the results when the input is selected. inputElement.addEventListener('click', updateResults); container.appendChild(divElement); }); document.querySelector('main').prepend(container); } function updateResults(){ // Get the current selected company and role from the radio button inputs. const company = document.querySelector("input[name='company']:checked").value; const role = document.querySelector("input[name='role']:checked").value; // If either the company or role is unselected, return. if (!company || !role) { return; } // TODO: Use the workAroundModule functions to calculate the needed data. const averageSalaryByRole = getAverageSalaryByRole(role); const averageSalaryByCompany = getAverageSalaryByCompany(company); const salary = getSalaryAtCompany(role, company); const industryAverageSalary = getIndustryAverageSalary(); // Render them to the screen. document.getElementById('salarySelected').innerText = `The salary for ${role}s at ${company} is \$${salary}`; document.getElementById('salaryAverageByRole').innerText = `The industry average salary for ${role} positions is \$${averageSalaryByRole}`; document.getElementById('salaryAverageByCompany').innerText = `The average salary at ${company} is \$${averageSalaryByCompany}`; document.getElementById('salaryAverageIndustry').innerText = `The average salary in the Tech industry is \$${industryAverageSalary}`; }

salaryData.js

const salaryData = [ { role: 'CTO', company: 'Big Data Inc.', salary: 320000}, { role: 'Technical Lead', company: 'Big Data Inc.', salary: 230000}, { role: 'Software Engineer II', company: 'Big Data Inc.', salary: 180000}, { role: 'Software Engineer I', company: 'Big Data Inc.', salary: 140000}, { role: 'CTO', company: 'Medium Data Inc.', salary: 215000}, { role: 'Technical Lead', company: 'Medium Data Inc.', salary: 165000}, { role: 'Software Engineer II', company: 'Medium Data Inc.', salary: 140000}, { role: 'Software Engineer I', company: 'Medium Data Inc.', salary: 115000}, { role: 'CTO', company: 'Small Data Inc.', salary: 175000}, { role: 'Technical Lead', company: 'Small Data Inc.', salary: 135000}, { role: 'Software Engineer II', company: 'Small Data Inc.', salary: 115000}, { role: 'Software Engineer I', company: 'Small Data Inc.', salary: 95000}, ]; const getRoles = () => { return ['CTO', 'Technical Lead', 'Software Engineer II', 'Software Engineer I']; } const getCompanies = () => { return ['Big Data Inc.', 'Medium Data Inc.', 'Small Data Inc.']; } const getDataByRole = role => { return salaryData.filter(obj => obj.role === role); } const getDataByCompany = company => { return salaryData.filter(obj => obj.company === company); } // Export functions export { getRoles, getCompanies, getDataByRole, getDataByCompany }; export default salaryData;

workAroundModule.js

// Add your imports here. import { getDataByRole, getDataByCompany } from "./salaryData.js"; import salaryData from "./salaryData.js"; // Replace the empty array with the appropriate imported function/value const getAverageSalaryByRole = role => { const roleData = getDataByRole(); const salariesOfRole = roleData.map(obj => obj.salary); return calculateAverage(salariesOfRole); } // Replace the empty array with the appropriate imported function/value const getAverageSalaryByCompany = company => { const companyData = getDataByCompany(); const salariesAtCompany = companyData.map(obj => obj.salary); return calculateAverage(salariesAtCompany); } // Replace the empty array with the appropriate imported function/value const getSalaryAtCompany = (role, company) => { const companyData = getDataByCompany(); const roleAtCompany = companyData.find(obj => obj.role === role); return roleAtCompany.salary; } // Replace the empty array with the appropriate imported function/value const getIndustryAverageSalary = () => { const allSalaries = salaryData.map(obj => obj.salary); return calculateAverage(allSalaries); } // Helper Function. Do not edit. // Note: This function does not need to be exported since it is only used by the functions contained within this module. function calculateAverage(arrayOfNumbers) { let total = 0; arrayOfNumbers.forEach(number => total += number); return (total / arrayOfNumbers.length).toFixed(2); } export { getAverageSalaryByRole, getAverageSalaryByCompany, getSalaryAtCompany, getIndustryAverageSalary };

Where is my mistake? I cannot find what is going wrong with my code.

You seem to have switched an import and export in main.js

I found it by checking the errors in the browser’s console … it said that there was an error in main.js because getIndustryAverageSalary wasn’t a function … but that could occur if the function wasn’t imported.

1 Like

Thanks for the reply. I corrected the import but have now a different error and still can’t render the salary expecations.

Here is what the console gives me:

Uncaught TypeError: document.querySelector(…) is null

Uncaught TypeError: roleAtCompany is undefined

It seems like getDataByCompany is nor being properly imported into workAroundModule.js, but why?

Okay, nevermind I figured it out! I was importing correctly but I forgot to add the arguments for getDataByRole and getDataByCompany.

const getAverageSalaryByCompany = (company) => { const companyData = getDataByCompany(company); const salariesAtCompany = companyData.map((obj) => obj.salary); return calculateAverage(salariesAtCompany); }; // Replace the empty array with the appropriate imported function/value const getSalaryAtCompany = (role, company) => { const companyData = getDataByCompany(company); const roleAtCompany = companyData.find((obj) => obj.role === role); return roleAtCompany.salary; };