Introduction: Bringing the Page to Life

Welcome back! In the last lesson, you built the main HTML template for your Cooking Helper landing page using Flask. You set up sections for searching recipes, displaying results, showing popular recipes, and a random recipe feature. You also linked your CSS and JavaScript files, preparing your page for interactivity.

In this lesson, you will learn how to use JavaScript to make your landing page interactive. By the end, you will be able to:

  • Capture user input from the search form and display matching recipes
  • Automatically show popular recipes when the page loads
  • Add a “Surprise Me” button that fetches a random recipe
  • Handle errors and give helpful feedback to users

Let’s get started and bring your Cooking Helper to life!

Quick Recall: Connecting JavaScript to Our Page

Before we dive in, let’s quickly remind ourselves how JavaScript connects to your HTML page. In the previous lesson, you linked a JavaScript file to your HTML using a <script> tag, like this:

<script src="{{ url_for('static', filename='js/search.js') }}"></script>

This line tells the browser to load and run your search.js file. Everything you write in that file can now interact with your HTML elements, such as forms, buttons, and lists.

Now, let’s see how we can use JavaScript to make your page interactive.

Handling Recipe Search by Ingredients

The first feature we’ll add is searching for recipes by ingredients. We want users to type ingredients into a form, submit it, and see matching recipes.

Step 1: Listening for Form Submission

We start by making sure our JavaScript waits until the page is fully loaded. Then, we find the search form and listen for when it is submitted.

document.addEventListener('DOMContentLoaded', () => {
  const searchForm = document.getElementById('search-form');
  // More code will go here
});
  • document.addEventListener('DOMContentLoaded', ...) waits until the HTML is loaded before running the code inside.
  • getElementById('search-form') finds the search form on the page.

Next, we want to listen for the form’s submit event:

searchForm.addEventListener('submit', async (e) => {
  e.preventDefault();
  // More code will go here
});
  • addEventListener('submit', ...) runs the function when the form is submitted.
  • e.preventDefault() stops the page from reloading, so we can handle the search with JavaScript.
Step 2: Getting the User’s Ingredients

Inside the submit event, we get the value the user typed:

const ingredientInput = document.getElementById('ingredient-input');
const ingredientsRaw = ingredientInput.value.trim();
if (!ingredientsRaw) return;

const ingredients = ingredientsRaw.split(',').map(i => i.trim()).filter(i => i);
  • ingredientInput.value.trim() gets the text from the input and removes extra spaces.
  • We split the text by commas, trim each ingredient, and remove any empty items.
Step 3: Sending the Search Request

Now, we send the ingredients to the server using fetch:

try {
  const res = await fetch('/api/recipes/by-ingredients', {
    method: 'POST',
    headers: { 'Content-Type': 'application/json' },
    body: JSON.stringify({ ingredients }),
  });
  const data = await res.json();
} catch (err) {
    // Error handling will go here. For now, we'll print the error
    console.error('Error loading recipe:', err);
}
  • fetch sends a POST request to /api/recipes/by-ingredients with the ingredients as JSON.
  • await res.json() gets the response data as a JavaScript object.
  • The try-catch block ensures we handle errors correctly.
Step 4: Showing the Search Results
Displaying Popular Recipes on Page Load

Next, let’s show popular recipes as soon as the page loads.

Step 1: Fetching Popular Recipes

We create a function to get popular recipes from the server:

async function loadPopularRecipes() {
  try {
    const res = await fetch('/api/recipes/popular');
    const data = await res.json();
    // More code will go here
  } catch (err) {
    // Error handling will go here. For now, we'll print the error
    console.error('Error loading recipe:', err);
  }
}
  • fetch('/api/recipes/popular') asks the server for popular recipes.
  • await res.json() gets the data.
Step 2: Displaying the Popular Recipes
Step 3: Calling the Function When the Page Loads

At the end of our main function, we call:

loadPopularRecipes();

This makes sure popular recipes appear as soon as the page is ready.

Example Output:

- Spaghetti Carbonara (⭐ 4.8)
- Chicken Alfredo (⭐ 4.7)
- Veggie Stir Fry (⭐ 4.6)
Adding the Random Recipe Feature

Now, let’s add a “Surprise Me” button that shows a random recipe.

Step 1: Listening for Button Clicks

First, we find the button and the container where we’ll show the recipe:

const randomBtn = document.getElementById('random-recipe-btn');
const randomContainer = document.getElementById('random-recipe');

Then, we listen for clicks:

randomBtn.addEventListener('click', async () => {
  // More code will go here
});
Step 2: Fetching and Showing a Random Recipe

Inside the click event, we fetch a random recipe and display it:

try {
  const res = await fetch('/api/recipes/random');
  const recipe = await res.json();

  if (recipe.error) {
    randomContainer.innerHTML = `<p>${recipe.error}</p>`;
    return;
  }

  randomContainer.innerHTML = `
    <h3>${recipe.name}</h3>
    <p><strong>Ingredients:</strong> ${recipe.ingredients.join(', ')}</p>
    <p><a href="/recipe/${recipe.id}">View full recipe</a></p>
  `;
} catch (err) {
  randomContainer.innerHTML = '<p>Error fetching random recipe.</p>';
}
  • We fetch from /api/recipes/random.
  • If there’s an error, we show a message.
  • Otherwise, we display the recipe’s name, ingredients, and a link.

Note: The links to individual recipes (/recipe/{id}) won’t work yet until we implement these pages in a later lesson.

Example Output:

Grilled Cheese Sandwich
Ingredients: bread, cheese, butter
View full recipe
Error Handling and User Feedback

It’s important to let users know if something goes wrong or if there are no results.

  • When searching, if no recipes are found, we must show:
    No matching recipes found.
  • If there’s a problem loading popular recipes, we must show:
    Error loading popular recipes.
  • If fetching a random recipe fails, we must show:
    Error fetching random recipe.

These messages help users understand what’s happening and what to do next.

Summary and Next Steps

In this lesson, you learned how to use JavaScript to make your Cooking Helper landing page interactive. You can now:

  • Handle recipe searches by ingredients and show results
  • Display popular recipes automatically when the page loads
  • Add a “Surprise Me” button for random recipes
  • Show helpful messages when things go wrong

Next, you’ll get to practice these skills with hands-on exercises. You’ll write and test your own code to reinforce what you’ve learned. Great job so far — let’s keep going!

Sign up
Join the 1M+ learners on CodeSignal
Be a part of our community of 1M+ users who develop and demonstrate their skills on CodeSignal