To Tutorials and Projects

IT 231 -- Tutorial 5

Goal: Create an Express website that displays vegetable seed for sale at the Urban Farmer company.

  1. Create an Express project in the folder tutorial5-robinson (replace robinson with your last name).
  2. Create an empty main.js script.
  3. Install Express, EJS, and Nodemon. Don't forget to modify the "scripts" object in the package.json file:
    "scripts": {
        "test": "echo \"Error: no test specified\" && exit 1",
        "start": "nodemon"
    },
    
  4. Create a folder named data that contains the file seeds.json with these contents:
    [{"vegetable":"Carrot", "variety":"Nantes", "organic":"Yes", 
        "numSeeds":1000, "sciName":"Dauens Carota", "price":"3.00", 
        "image":"carrot.jpg"},
     {"vegetable":"Brussels Sprouts", "variety":"Long Island", "organic":"No", 
        "numSeeds":"200", "sciName":"Brassica oleracea", "price":"3.00", 
        "image":"brussels_sprouts.jpg"},
     {"vegetable":"Broccoli", "variety":"Green Magic", "organic":"No", 
        "numSeeds":"100", "sciName":"Brassica oleracea", "price":"4.00", 
        "image":"broccoli.jpg"},
     {"vegetable":"Cucumber", "variety":"Double Yield", "organic":"Yes", 
        "numSeeds":"300", "sciName":"Cucumis sativis", "price":"4.00", 
        "image":"cucumber.jpg"}]
    
  5. Add these items to your main.js script:
    1. Require the express and fs modules, and create the Express server app:
      const app = express( );
      
    2. Set the view engine to ejs:
      app.set("view engine", "ejs");
      
    3. Declare the global variable seeds:
      var seeds;
      
    4. Using fs.readFile, read the data/seeds.json file, convert the JSON string to an array of object literals using JSON.parse, then assign the resuling array to the variable seeds.
  6. In your project folder, create a views subfolder. Then, in this views folder, create index.ejs that uses the elements array of objects to display a table of the seeds that are for sale according to the data in the seeds.json file. The index view should look something like this: index.ejs. Also in the index view, use a loop like this to display the rows of the index view:
     <table>
        <tr>
            <th>Vegetable</th>
            <th>Variety</th>
            <th>Number of Seeds</th>
            <th>Price</th>
        </tr>
        <% var n = 0;
           for(var s of seeds) { %>
           <tr>
               <td><%= s.vegetable %></td>
               <!-- Add <td> tags to also display the variety,
                    number of seeds, and price.
    
                    Add the following td tag to display a link to
                    the show.ejs view for each row. -->
              <td><a href="/seeds/show/<%= n %>">Show</a></td>
          </tr>
          <% n++; 
             } %>
    </table>
    
    The EJS files should have software headers that look like this:
    <!DOCTYPE html>
    <!-- Steve Robinson
         Tutorial 5
         Nov 12, 2023 -->
    
  7. In main.js, set up the get route /seeds using the method app.get that renders the index.ejs view, passing the data {seeds: seeds} to the index view:
    res.render("index", {seeds: seeds});
    
  8. Also in main.js, set the server app to listen on port 3000.
  9. Start Nodemon with npx nodemon and test your page with this URL:
    localhost:3000/seeds
    
    The browser should show an index page similar to: index.ejs
  10. Define a public folder with subfolders images and css for the images and stylesheet:
    app.use(express.static("public"));
    
    Link a stylesheet to the index.ejs page. You can use this stylesheet for the index, show, and new views:
    table { border-collapse: collapse; }
    td { border: 2px solid #004040; }
    td, th { padding: 8px; }
    img { width: 200px; }
    
    Also add body styles for background-color, color, and font-family. The stylesheet should have a software header that looks like this:
    /* Steve Robinson
       Tutorial 5
       Nov 12, 2023  */
    
  11. Your show.ejs view can look like this:
    <h1>Tutorial 5: Show View</h1>
    <p>ID: <%= n =><br>
       Vegetable: <%= seeds[n].vegetable %><br>
       Variety: <%= seeds[n].variety %><br>
       <!-- Add lines to display data for Organic (key=organic), Number of Seeds (key=numSeeds),
            Scientific Name (key=sciName), Price (key=price) -->
       </p>
    
  12. In main.js, add an app.get method call to set up the route /seeds/show with the parameter n that represents the index of the array of objects:
    app.get("/seeds/show/:n", callback);
    
    The callback function obtains the value of the parameter like this:
    var n = req.params.n;
    
    It should also check that n is between 0 and elements.length - 1, inclusive. If it is, render the show.ejs view, passing the data object { seeds: seeds, n: n} to the view:
    res.render("/seeds/show", { seeds: seeds, n: n });
    
    The show.ejs view should display the fields of nth item in the seeds array like this: show.ejs. If n is not an item in the array, use res.show to display the string "<p>Vegetable not found.</p>" in the browser. Wait until Item 14 to display the vegetable image. Here is the source code for the /seeds/show route in main.js:
    app.get("/seeds/show/:n", (req, res) => {
        var n = req.params.n;
        if (0 <= n && n < seeds.length) {
            res.render("show", { seeds: seeds, n: n });
        }
        else {
            res.send("<p>Vegetable not found.</p>");
        }
    });
    
  13. Test your route using this URL:
    localhost:3000/seeds/show/4
    
    You should see a page similar to this: show.ejs
  14. Download these images into the public/images folder.:
    broccoli.jpg  brussels_sprouts.jpg  carrot.jpg  cucumber.jpg
    green_pepper.jpg  onion.jpg  pumpkin.jpg
  15. In the show.ejs view, write code to display the image for the displayed vegetable item:
    <img src="/images/<%= s.image %>">
    
  16. Also in the views folder, implement a new.ejs view for entering a new entry in the table. Implement the form using HTML code like this:
    <form name="form1" action="/seeds/append" method="get">
        <label for="vegetable">Vegetable:</label><br>
        <input id="vegetable" name="vegetable"><br><br>
        <label for="variety">Variety:</label><br>
        <input id="variety" name="variety"><br><br>
        <label for="organic">Organic:</label><br>
        <input id="organic" name="organic"><br><br>
        <label for="numSeeds">Number of Seeds:</label><br>
        <input id="numSeeds" name="numSeeds"><br><br>
        <label for="sciName">Scientific Name:</label><br>
        <input id="sciName" name="sciName"><br><br>
        <label for="price">Price:</label><br>
        <input id="price" name="price"><br><br>
        <label for="image">Image:</label><br>
        <input id="image" name="image"><br><br>
    
        <input type="submit" value="Submit Data">
    </form>
    
  17. In main.js, add an app.get method with route /seeds/new that displays the new.ejs view.
  18. In main.js, add an app.get method with this code to implement the /seeds/append route:
    app.get("/seeds/append", (req, res) => {
        var newRow = req.query;
        seeds.push(newRow);
        res.render("index", { seeds: seeds });
    });
    
  19. Test the /seeds/new route by adding a new vegetable to the table.  You can use this data:
    {vegetable:"Pumpkin", variety: "Cinderella", organic: "No", numSeeds: 10; 
    sciName: "Cucurbita pepo", price: 4.00, image: "pumpkin.jpg"}
    
  20. Add hyperlinks to the index.ejs, show.ejs, and new.ejs views that navigate to the views that make sense. Here is source code for the hyperlinks:
    ---- index.ejs ---------------------------------
    <p><a href="/seeds/new">Add New Table Row</a></p>
    
    ---- show.ejs ----------------------------------
    <p><a href="/seeds">Back to Index> &nbsp; 
       <a href="/seeds/new">Add New Table Row</a></p>
    
    ---- new.ejs -----------------------------------
    <p><a href="/seeds">Back to Index></a></p>
    

Grading Breakdown: Functionality: 35; Source code comments: 5; Source code headers in main.js and EJS views: 5; Submitted: 5 (project folder name should be tutorial5-<Your Last Name>