Moving the data from the views to the controllers

Part of this process includes moving the data back down the MVC flow, from the views into the controllers. The example in chapter 4 deals with this task in the Loc8r homepage, but it needs to be done for the other pages too. Start with the Details page.

Details page

The Details page is the largest and most complex of the pages, with the most data requirements. The first step is setting up the controller.

Setting up the controller

The controller for this page is called locationInfo and is in the locations.js file in app_server/controllers. When you’ve analyzed the data in the view and collated it into a JavaScript object, your controller will look something like the following listing.

Listing C.1. locationInfo controller
const locationInfo = function(req, res){
  res.render('location-info', {
    title: 'Starcups',
    pageHeader: {title: 'Starcups'},
    sidebar: {
      context: 'is on Loc8r because it has accessible wifi and space to sit
      down with your laptop and get some work done.',
      callToAction: 'If you've been and you like it - or if you don't -
      please leave a review to help other people just like you.'
    },
    location: {
      name: 'Starcups',
      address: '125 High Street, Reading, RG6 1PS',
      rating: 3,
      facilities: ['Hot drinks', 'Food', 'Premium wifi'],
      coords: {lat: 51.455041, lng: -0.9690884},           1
      openingTimes: [{                                     2
        days: 'Monday - Friday',
        opening: '7:00am',
        closing: '7:00pm',
        closed: false
      },{
        days: 'Saturday',
        opening: '8:00am',
        closing: '5:00pm',
        closed: false
      },{
        days: 'Sunday',
        closed: true
      }],
      reviews: [{                                          3
        author: 'Simon Holmes',
        rating: 5,
        timestamp: '16 July 2013',
        reviewText: 'What a great place. I can't say enough good things
        about it.'
      },{
        author: 'Charlie Chaplin',
        rating: 3,
        timestamp: '16 June 2013',
        reviewText: 'It was okay. Coffee wasn't great, but the wifi was
        fast.'
      }]
    }
  });
};

  • 1 Includes latitude and longitude coordinates to use in Google Map image
  • 2 Adds array of open times, allowing for different data on different days
  • 3 Array for reviews left by other users

Note the latitude and longitude being sent through. You can get your current latitude and longitude from https://www.where-am-i.net. You can geocode an address—that is, get the latitude and longitude of it—from https://www.latlong.net/convert-address-to-lat-long.html. Your views will be using the lat and lng to display a Google Map image of the correct location, so it’s worthwhile doing this for the prototype stage.

Updating the view

As this page is the most complex, data-rich page, it stands to reason that it will have the largest view template. You’ve already seen most of the technicalities in the homepage layout, such as looping through arrays, bringing in includes, and defining and calling mixins. You have a couple of extra things to look out for in this template, though, both of which are annotated and highlighted in bold.

First, this template uses an if-else conditional statement. This statement looks like JavaScript without the braces. Second, the template uses a JavaScript replace function to replace all line breaks in the text of reviews with <br/> tags. You do this by using a simple regular expression, looking for all occurrences of the characters in the text. The following listing shows the location-info.pug view template in full.

Listing C.2. location-info.pug view template in app_server/views
extends layout
include _includes/sharedHTMLfunctions                                   1
block content
  .row.banner
    .col-12
      h1= pageHeader.title
  .row
    .col-12.col-lg-9
      .row
        .col-12.col-md-6
          p.rating
            +outputRating(location.rating)                              2
          p 125 High Street, Reading, RG6 1PS
          .card.card-primary
            .card-block
              h2.card-title Opening hours
              each time in location.openingTimes                        3
                p.card-text                                             3
                  | #{time.days} :                                      3
                  if time.closed                                        3
                    | closed                                            3
                  else                                                  3
                    | #{time.opening} - #{time.closing}
          .card.card-primary
            .card-block
              h2.card-title Facilities
              each facility in location.facilities
                span.badge.badge-warning
                  i.fa.fa-check
                  | &nbsp;#{facility}
                | &nbsp;
        .col-12.col-md-6.location-map
          .card.card-primary
            .card-block
              h2.card-title Location map
              img.img-fluid.rounded(src=`http://maps.googleapis.com/
              maps/api/staticmap?center=${location.coords.lat},
              ${location.coords.lng}&zoom=17&size=400x350&sensor=
              false&markers=${location.coords.lat},${location.coords.
               lng}&key={googleAPIKey}&scale=2`)                      4
      .row
        .col-12
          .card.card-primary.review-card
            .card-block
              a.btn.btn-primary.float-right(href='/location/review/new')
              Add review
              h2.card-title Customer reviews
              each review in location.reviews                           5
                .row.review
                  .col-12.no-gutters.review-header
                    span.rating
                      +outputRating(review.rating)                      5
                    span.reviewAuthor #{review.author}
                    small.reviewTimestamp #{review.timestamp}
                  .col-12
                    p !{(review.reviewText).replace(/
/g, '<br/>')}    6
    .col-12.col-lg-3
      p.lead #{location.name} #{sidebar.context}
      p= sidebar.callToAction

  • 1 Brings in sharedHTMLfunctions include, which contains outputRating mixin
  • 2 Calls outputRating mixin, sending it the rating of the current location
  • 3 Loops through the array of open times, checking whether the location is closed by using an inline if-else statement
  • 4 Builds the URL for the Google Maps static image, inserting lat and lng by using an ES2015 template literal. Remember that you’ll need your Google Maps API Key.
  • 5 Loops through each review, calling the outputRating mixin again to generate markup for stars
  • 6 Replaces any line breaks in review text with the <br/> tag so it renders as intended by the author

A question that may arise is, why replace line breaks with <br/> tags every time? Why don’t you save the data with <br/> tags in? That way, you have to run the replace function only once, when the data is saved. The answer is that HTML is only one method of rendering text; it happens to be the one you’re using here. Down the line, you may want to pull this information into a native mobile application. You don’t want the source data tainted with HTML markup that you don’t use in that environment. The way to handle that is to keep the data clean.

Add Review page

The Add Review page is simple at the moment, with only one piece of data in it: the title in the page header. Updating the controller shouldn’t pose much of a problem. See the following listing for the full code of the addReview controller, in locations.js in the app_server/controllers folder.

Listing C.3. addReview controller
const addReview = function(req, res){
  res.render('location-review-form', {
    title: 'Review Starcups on Loc8r',
    pageHeader: { title: 'Review Starcups' }
  });
};

There’s not much to talk about here; you’ve updated the text inside the titles. The following listing shows the corresponding view, location-review-form.pug, in app_server/views.

Listing C.4. location-review-form.pug template
extends layout
block content
  .row.banner
    .col-12
      h1= pageHeader.title
  .row
    .col-12.col-md-8
      form(action="/location", method="get", role="form")
        .form-group.row
          label.col-10.col-sm-2.col-form-label(for="name") Name
          .col-12.col-sm-10
            input#name.form-control(name="name")
        .form-group.row
          label.col-10.col-sm-2.col-form-label(for="rating") Rating
          .col-12.col-sm-2
            select#rating.form-control.input-sm(name="rating")
              option 5
              option 4
              option 3
              option 2
              option 1
        .form-group.row
          label.col-sm-2.col-form-label(for="review") Review
          .col-sm-10
            textarea#review.form-control(name="review", rows="5")
        button.btn.btn-primary.float-right Add my review
    .col-12.col-md-4

Again, there’s nothing complicated or new here, so you can move on to the About page.

About page

The About page doesn’t contain a huge amount of data, either, only a title and some content. Pull it out of the view and into the controller. Note that the content in the view currently has some <br/> tags in it, so replace each <br/> tag with when you put it into the controller. These tags are highlighted in bold in the following listing. The about controller is in app_server/controllers/others.js.

Listing C.5. about controller
const about = function(req, res){
  res.render('generic-text', {
    title: 'About Loc8r',
    content: 'Loc8r was created to help people find places to sit down
    and get a bit of work done.<br/><br/>Lorem ipsum dolor sit
    amet, consectetur adipiscing elit. Nunc sed lorem ac nisi digni
    ssim accumsan. Nullam sit amet interdum magna. Morbi quis
    faucibus nisi. Vestibulum mollis purus quis eros adipiscing
    tristique. Proin posuere semper tellus, id placerat augue dapibus
    ornare. Aenean leo metus, tempus in nisl eget, accumsan interdum
    dui. Pellentesque sollicitudin volutpat ullamcorper.'
  });
};

Aside from removing the HTML from the content, not much is going on here. Take a quick look at the view, and you’ll be done. The following listing shows the final generic-text view used for the About page in app_server/views. The view has to use the same piece of code as the reviews section to replace the line breaks with HTML <br/> tags.

Listing C.6. generic-text.pug template
extends layout
  .row.banner
    .col-12
      h1= title
  .row
    .col-12.col-lg-8
      p !{(content).replace(/
/g, '<br/>')}      1

  • 1 Replaces all line breaks with <br/> tags when rendering HTML

This template is a simple, small, reusable one to use whenever you want to output some text on a page.

..................Content has been hidden....................

You can't read the all page of ebook, please click here login for view all page.
Reset
18.221.85.33