Node.js – 9bit Studios https://9bitstudios.com Web Design, Themes, & Applications Tue, 04 Jul 2017 13:09:04 +0000 en-US hourly 1 https://wordpress.org/?v=4.8 To Do: Create Your First React Application – Part I https://9bitstudios.com/2016/10/to-do-create-your-first-react-application-part-i/ https://9bitstudios.com/2016/10/to-do-create-your-first-react-application-part-i/#respond Thu, 06 Oct 2016 20:09:02 +0000 https://9bitstudios.com/?p=1176 React is a JavaScript library that is primarily responsible for handling the “view” component of a JavaScript single-page application. As it describes itself of the React homepage…

Lots of people use React as the V in MVC. Since React makes no assumptions about the rest of your technology stack, it’s easy to try it out on a small feature in an existing project.

React’s focus, first and foremost, has to do with rendering dynamic UIs in a manner that is visually appealing to the user. It is flexible enough that it can be used in a diversity of capacities and contexts. We have looked at React in previous entries. In what follows we will look at creating an introductory application using React and React related tools and libraries. One of the more ubiquitous tutorial applications that developers build when learning a new language or framework is the TO DO (To do) app. In terms of prevalence, it is probably second only to the “Hello, World” app which has been around since the dawn of programming. But the “To Do” application is popular because it covers a lot of the basics of how a language or framework handles a number of things. There must be a way to add a new “to do” so handling user input is involved. The same is true for displaying data, editing and saving data, and changing display state when data updates. All of these things are going to be important implementations in any application.

In what follows we will create the iconic “To Do” application in React and discuss some of the inner workings as we go along. We will take a deeper look into React components and how we can add some dynamic interactivity to our React applications in response to user actions — things like clicks and entering text in a text box — and updating our views accordingly.

JSX Compilation with Babel & Browserify

As we will see, React has its own programming language called JSX. It has been described as sort of like a mixture of JavaScript and XML and it is React’s own special easy-to-read abstracted syntax. JSX is not required to create React applications and you can write your React components in native JavaScript if you prefer. Because browsers do not natively understand JSX in order for your react application to run JSX needs get converted to native JavaScript.

The React website suggests that you utilize tools like Babel and/or Browserify (both of which run on Node.js). Babel is what is known as a transpiler. It mostly functions as a tool that takes code written in ECMAScript 6 (ES6) and converts it to ES5. As of 2015 this is still necessary because support for ES6 across all browsers is not widespread yet. Until support for ES6 is implemented across all browsers, tools like Babel will still be needed. Although many people think of Babel primarily as an ES6 to ES5 transpiler, Babel also comes with JSX support as well. You can merely run the Babel transpiler on your JSX files and they will be converted to native JavaScript that will be recognized by any browser circa 2015.

Browserify allows for Node.js style module loading in your client-side JavaScript. Like with Node, it allows you to import code in certain JavaScript files into other JavaScript files for better organization of your code.

Task Runners / Module Bundlers

For our sample code, we will be using task runners to handle our JSX conversion to native JavaScript. You may have heard of task runners like Grunt or Gulp, or module bundlers like webpack. We will be using webpack because it has, at least for the time being, become the utility of choice among the React community. If you are not entirely familiar with JavaScript task runners it would definitely be worthwhile to read the webpack documentation (or watch a few videos) on what it is and why you would want to use it. The more recent versions of React essentially require you to set up your tools before you work with JSX in React. In previous versions of React there was an easy extra <script> tag that you could add in your HTML to make it easy to implement JSX. However this has since been deprecated. If this seems daunting and you are already feeling overwhelmed, not to worry! We will walk through how to set everything up before we dive into React coding.

Setting Up

To start we need to set up our package.json and webpack.config.js files so that we can set up our tools to do JSXcompilation to native JavaScript. Create a new directory and then create a package.json file and add the following…

{
    "name": "React",
    "version": "0.0.1",
    "description": "A React application...",
    "license": "MIT",
    "repository": {
        "type": "",
        "url": ""
    },
    "homepage": "https://9bitstudios.com",
    "scripts": {
        "start": "webpack-dev-server --progress"
    },    
    "dependencies": {
        "react": "15.3.0"
    },
    "devDependencies": {
        "webpack": "1.13.1",
        "webpack-dev-server": "1.14.1",
        "babel-core": "6.13.0",
        "babel-loader": "6.2.4",
        "babel-preset-es2015": "6.13.0",
        "babel-preset-react": "6.11.1"
    }
}

Next, in this same directory, create a webpack.config.js file and add the following…

var webpack = require('webpack');

module.exports = {
    devtool: 'source-map',
    entry: __dirname + "/src/App.js",
    output: {
        path: __dirname + "/dist",
        filename: "App.js"
    },
    watch: true,
    module: {
        loaders: [
            {
                test: /\.jsx?$/,
                exclude: /node_modules/,
                loader: 'babel',
                query:{
                    presets: ['es2015', 'react']
                }
            }
        ]
    },
    devServer: {
        colors: true,
        inline: true
    },     
    plugins:[
        new webpack.optimize.UglifyJsPlugin(),
    ]
};

After this, let’s open a command prompt and run the following…

$ npm install

to install all of our modules that we will need for compiling ES6 and JSX. And that is all there is to it. Now that we have our tools installed and configured, we can dive into writing our application.

Writing a “To Do” Application

So let’s get started creating our “To Do” app. We will start out by creating our index.html file…

<!DOCTYPE html>
<html>
<head>
    <title>React</title>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
</head>
<body>
    <div id="content"></div>
    
    <script src="https://cdnjs.cloudflare.com/ajax/libs/react/15.3.0/react.js"></script>
    <script src="https://cdnjs.cloudflare.com/ajax/libs/react/15.3.0/react-dom.js"></script>
    <script type="text/javascript" src="dist/App.js"></script>      
    
</body>
</html>

As we can see, we are going to include App.js, which will be a file that we generate in our task runner. Note too we are creating a

with the id of “content.”

Next, create a folder called “src” and create a file called App.js in this folder. For this tutorial we are going to be breaking our components up into different modules so in our App.js file all we need to add for now is the following.

import {react} from 'react';

In the same directory as your App.js file, next create a file called “Todo.js”. In this file, we are going to need to create a React component/class that will represent each individual “to do.” Add the following code to this file…

import {react} from 'react';

class Todo extends React.Component {
    
    render() {
        return(<div>I am a to do</div>)  
    }
};

Pretty straightforward. This should look familiar as it is similar to our other earlier examples.

Now what we’re going to do is import this module into our App.js file. How do we do this? In our App.js file we just need to add the following…

import {react} from 'react';
import {Todo} from './Todo';

This will tell our code to import the “Todo” module from the “Todo” file relative to where “App.js” is located. With module loading in ES6 you can omit the “.js” from the file when you are importing modules.

So we are definitely well on our way but if we were to run this code as it is right now we would get an error. Why is this? Well, because we are importing a module from our “Todo.js” file we need to specify what this file exports. To do this we need to add the “export” keyword in front of what we want to make available from the “Todo.js” file. Thus, we need to change our code in our “Todo.js” file to the following…

import {react} from 'react';

export class Todo extends React.Component {
    
    render() {
        return(<div>I am a to do</div>) 
    }
};

Notice how we have added the “export” keyword in front of our class. Now there is something that can be imported from the “Todo.js” file. We will get into more complex combinations of what various files can export and import later on, but for now this simple example shows the basic setup of how it is done.

Now in our App.js file add the “render” method so we can confirm that everything is working…

 import {react} from 'react';
import {Todo} from './Todo';

ReactDOM.render(<Todo />, document.getElementById('content'));

Let’s build our App.js file by running “webpack” by opening up a terminal window typing the following…

$ webpack

Doing the above will build the App.js file and place it in our “dist” folder. Now if we open up another terminal window and run our server with…

$ npm start

and we go to https://localhost:8080 in our browser, if all has gone well we should be able to see the text “I am a to do.”

Component Composition

For our application we will be rendering a list of “to do” items inside of our “to do” list. Thus, we will also need to create a component that represents our “to do” list. So create a “TodoList.js” file in the same directory as the others and add the following code…

import {react} from 'react';
import {Todo} from './Todo';

export class TodoList extends React.Component {
    
    render() {
        return(<div>To do list here...</div>)  
    }
};

“TodoList” is the component that will serve as our “root” container component for our React application. It is just returning some placeholder text for now, but we will be adding more complexity to it very soon. Because the “TodoList” top-level component for this particular application, it is this one that will be the one that we want to render in our App.js file (not the individual “Todo” components). So change the code in our App.js file to the following…

import {react} from 'react';
import {TodoList} from './TodoList';

ReactDOM.render(<TodoList />, document.getElementById('content'));

Notice now how we are now rendering the “TodoList” component now and not the “Todo” components.

Now let’s take a look at how we could add some “depth” to our components (i.e. nesting components within components). In this case we will be nesting individual “Todo” components inside of our “TodoList” component. So in our “TodoList.js” file we can update our code to the following…

import {react} from 'react';
import {Todo} from './Todo';

export class TodoList extends React.Component {
    
    render() {
        return (<Todo />);
    }
};

It is as simple as that! You can include other components in what you return in your render method. This can include multiple components if you so desire…

 import {react} from 'react';
import {Todo} from './Todo';

export class TodoList extends React.Component {
    
    render() {
        return (
            <div>
                <Todo />
                <Todo />
                <Todo />
            </div>
        );
    }
};

This example will render the text in our “Todo” component 3 times.

In a real-world application, what you render in any given React component will often include multiple components of many different types. This is what we refer to when we explain React components as being composable. They can be composed of multiple components of different types.

Our example is very plain right now. Let’s take a look and see if we can make things more dynamic by rendering out some variable data and adding some interactivity by wiring up some events (clicks, hovers, etc.)

Properties With this.props

We discussed the importance of this.props and this.state a bit earlier and we will expand upon this in the upcoming sections. To start let’s use some sample data. This data will again be an array of objects and will be somewhat similar to what we used earlier in our introduction to React. So update the App.js file to look like the following…

import {react} from 'react';
import {TodoList} from './TodoList';

let todos = [
    {
        id: 1,
        title: "Eat Breakfast",
        summary: "Toast and scrambled eggs would be nice.",
        done: true
    },
    {
         id: 2,
         title: "Walk Dog",
         summary: "Dress for wet weather.",
         done: false
    },
    {
         id: 3,
         title: "Learn React",
         summary: "I am making great progress!",
         done: false
         
     }
];

ReactDOM.render(<TodoList data={todos} />, document.getElementById('content'));

Here we have an array of objects that we are going to pass in to our “TodoList” component. Inside of our component the data will be accessible by using this.props.data. The name “data” is just the name that I picked. You can choose any name that you want for your property attributes.

Continuing on, update the code in our TodoList.js file to the following…

import {react} from 'react';
import {Todo} from './Todo';

export class TodoList extends React.Component {
    
    render() {
        
        let items = this.props.data.map(function(item){
            return (<Todo title={item.title} summary={item.summary} completed={item.done} />);        
        });
        
        return(<ul>{items}</ul>)
    }
};

As we can see, we are accessing the data that is passed into our component with this.props.data. We iterate through the array and for each item, we pass the data in the item one level deeper into a “Todo” component. We create a collection of these components and return each one.

And then finally, let’s update our Todo.js file to the following…

 import {react} from 'react';

export class Todo extends React.Component {
    
    render() {
        return(
            <li>
                <h2>{this.props.title}</h2>
                <p>{this.props.summary}</p>
                <input type="checkbox" checked={this.props.completed} />
            </li>
        )  
    }
};

So as we can see here, the title, the summary, and the flag on whether or not the item is marked as completed that we are passing into the component will be available with this.props.completed because we passed the done property in the object on each item into this slot.

Now if we build our files with $ webpack we can see the listing of our “to do” items. The ones that have the “done” property set to true have the checkbox checked.

Handling Events & State

One of the important parts that React applications handle for you is management of “state.” What is state? State is basically the current values that any given component holds that is often reflected in the way that the UI displays and represents its values. In our example above some of the items in our “to do” list hold a current state of being “completed” and some hold a current state of being “not completed.” State is the current collection of properties holding a set of values within a component. When the state updates, that is, when the value of one of these properties in a component changes, the component re-renders itself. We hinted at this piece of React briefly before and this one of React’s awesome features. Components re-render themselves when there is any change. We do not have to try to update things manually ourselves within the UI!

There are a number of different ways that a component’s state can change, but one of the more common ways is via events. Events are things such as mouse clicks and hovers that are usually instigated by a user but they can also be triggered in code as well. Wiring up events in React is similar to how it is done inline with JavaScript in HTML. You may have seen code like this before in vanilla JavaScript…

<script type="text/javascript">
function showMessage(){
   alert("Hello world!");
}
</script>
<input type="button" id="messageButton" value="Submit" onclick="showMessage()" />

In the “onclick” attribute, we run the showMessage() function which will alert a message “Hello world!”. React takes a similar approach to this when it comes to hooking up events. Let’s see what this looks like. Update the code in “Todo.js” to the following…

import {react} from 'react';

export class Todo extends React.Component {
    
    constructor(){
        super(...arguments);
        this.state = {
            completed: this.props.completed
        }
    }
    
    toggleCompleted(){
        this.setState({completed: !this.state.completed})
    }
    
    render() {
        return(
            <li>
                <h2>{this.props.title}</h2>
                <p>{this.props.summary}</p>
                <input type="checkbox" checked={this.state.completed} onChange={() => this.toggleCompleted()} />
            </li>
        )  
    }
};

You may have noticed the “…arguments” in the constructor. This is the spread operator that is a new feature in ES6 and in JSX. You also might notice our use of an arrow function that we discussed earlier in the “onChange” attribute. This is actually a necessity with regard to the scope of the component. If we did not use an arrow function here, the function in the attribute would create its own scope. Therefore we would have had to use “bind” and write something like onChange={this.toggleCompleted.bind(this)}. However, because arrow functions operate in the context of the parent scope, “bind” becomes unnecessary and the scope of the attribute operates under the scope of the component.

For the checkbox, we could attach and “onClick” event here if we wanted to and it would work fine, but instead of using the “onClick” event, we will use the “onChange” event because it is a bit more all-encompassing. In the future we will work with input textboxes, select boxes, and a number of other form elements. The “onChange” event will cover that a bit more comprehensively and we will be using it more regularly as we go along. There will be a time and a place for “onClick” specifically as well but in this case, onChange is a better fit.

If we build our code and ran this code as it is, we would get a warning message in the console saying…

Warning: Each child in an array or iterator should have a unique "key" prop. Check the render method of `TodoList`. See https://fb.me/react-warning-keys for more information.

What is going on here? As we can see from the suggested page in the React docs there is a description of why this warning is appearing…

The situation gets more complicated when the children are shuffled around (as in search results) or if new components are added onto the front of the list (as in streams). In these cases where the identity and state of each child must be maintained across render passes, you can uniquely identify each child by assigning it a key… When React reconciles the keyed children, it will ensure that any child with key will be reordered (instead of clobbered) or destroyed (instead of reused).

So when dealing with events and state React requires a unique ID “key” to be attached for child components within a set. React uses this internally to allow for efficient reordering and identifying a specific item within the set. This is especially important when items are added to or removed from the set. So let’s update the code in our TodoList.js file…

import {react} from 'react';
import {Todo} from './Todo';

export class TodoList extends React.Component {
    
    render() {
        
        var items = this.props.data.map(function(item){
            return (<Todo key={item.id} title={item.title} summary={item.summary} completed={item.done} />);        
        });
        
        return(<ul>{items}</ul>)
    }
};

As we can see, we have passed in the item ID as the key property. That’s all we have to do! Once we do this and then rebuild our JavaScript this error message will go away. React is very helpful in giving us information with regard to how we need to change our code to set things up properly.

Now if we open our browser and go to our https://localhost:8080 site (run $npm start) we can see the items in our list rendered. The ones that have the “done” property set to true will have the checkbox checked. If we check/uncheck the checkboxes, the underlying data for the component underneath will be toggled as the “toggleCompleted” method will be running each time we do this. This brings us to the concept of state, something that is inexorably linked with events.

As we have mentioned earlier, state is the current collection of properties holding a set of values within a component. Collectively it is the status of the component at any given time and is subject to change at any time. This change will trigger React to do a “rerender” of the UI. In our example we are displaying the title and the summary with this.props.title and this.props.summary. In React, this.props is read-only and cannot be changed. Trying to set this.props.title = ‘Something Else’ will result in an error. Contrary to this.props, this.state is mutable. Because the “completed” property will change we will set an initial value for it in the constructor. Note that even though we cannot change anything on this.props we can still read the values in this.props to set an initial state. When certain events happen or certain functions execute, we can update the state of the component with this.setState and pass in an object containing all the properties we want to update. We will also do this for the title and summary properties later on when we get into writing our functions to edit our “to do” components. But for now we are just doing this with our “completed” flag.

That about does it for part 1. In part 2 we will work on filling out the application a bit more and adding in some validation. Until next time…

]]> https://9bitstudios.com/2016/10/to-do-create-your-first-react-application-part-i/feed/ 0 Submit Apache Cordova Applications for iOS and Android to the Apple App Store & Google Play https://9bitstudios.com/2016/01/submit-apache-cordova-applications-for-ios-and-android-to-the-apple-app-store-google-play/ https://9bitstudios.com/2016/01/submit-apache-cordova-applications-for-ios-and-android-to-the-apple-app-store-google-play/#comments Tue, 12 Jan 2016 00:08:00 +0000 https://9bitstudios.com/?p=1118 In the past, we have looked at setting up Apache Cordova mobile applications for iOS and Android with HTML5, JavaScript and how to develop for this versatile platform. In what follows we will look at how to submit your application to the app stores of the respective platforms once you have finished developing your application.

As we looked at before, you will need a computer with the SDKs of the platform(s) you want to release on. If you want to release for Android devices, you will need to grab the Android SDK. I actually recommend you install Android Studio as this will download everything you need for this and future releases. If you want to release for iOS devices, you will of course need a Mac computer with Xcode installed. Unfortunately, you cannot develop iOS applications without a Mac. So if you want to build and release for iOS you will have to find some way to get access to one.

You will also need to sign up for developer accounts for the platforms you want to release on. These developer accounts do cost money. For Google Play (Android) there is a one time developer fee of $25. For an iOS developer account the fee is $99/per year.

Once you have signed up for your developer accounts, we can build our applications for release on the iOS and Android platforms.

Submitting to Your Cordova App for iOS to the Apple App Store


Once you are satisfied with how your app functions on all of the devices that you want your application to run on, you can start the process of preparing your project for submitting your app to the Apple App Store.

To submit your Apache Cordova application for sale (or free download) on the App Store you will need to go through the normal process that all apps must go through before they are submitted to the store. Building an app for release on iOS is a fairly straightforward process. You need to compile the release file by running the following command in the root of your Cordova project…

$ cordova build --release ios

This will build your application for release. There will be a generated Xcode project in the platforms/ios directory

Next, you’ll need go to https://developer.apple.com and click on “member center.” Sign in with your developer account if you have not already.

Creating an iOS Distribution Certificate

Click on “Certificates Identifiers and Profiles” and then on the next screen click on “Certificates.”

Click on the “+” button on the certificates page and scroll down in the production section and choose the “App Store and Ad Hoc” option and click “Continue”

iOS

We will want to create a new certificate so we will need to open up Keychain Access. The easiest way to do this is in your Mac click on the search bar in the top right and search for “Keychain Access” and open this application, Click on Keychain Access in the menu in the top left, and in the dropdown hover over “Certificate Assistant” and choose “Request a Certificate From a Certificate Authority”

iOS

This will open up a modal which you can then fill out the e-mail address with your developer account e-mail and then a common name which can usually just be the same of your organization. After you have filled these out choose the “Save to disk” option and save the certificate to wherever you want on your computer.

iOS

After we do this back in our developer account we will click “Continue” again and on the next page we will upload the CSR file we just created and saved to our computer. Attach the file via the “Choose file…” button, attach the file and click the “Generate” button.

iOS

In the next screen you will be able to download the generated file (which is an iOS distribution .cer file) by clicking on the “Download” button.

iOS

Download this file and save it somewhere on your computer (probably the “Downloads” folder).

After this, we need to again open up the “Keychain Access” application and we need to drag and drop this certificate into the section in the top left of the “Keychain Access” window called “logins.” Note that this information is also present on the download screen we were just at in the Developer Center.

That is all that we need to do for creating an iOS Distribution Certificate

Creating an App ID in Developer Center

Now that we have created our distribution certificate. we need to create an App ID. The App ID is a unique identifier key that the App Store will use to differentiate it from other apps.

Back in our developer account at https://developer.apple.com, click on the on the “Certificates Identifiers and Profiles” link. On the next screen click on the “App IDs” link under the “Identifiers” section. Click on the “+” button at the top to create a new App ID.

On the next screen, you fill in the name with whatever you want, but it is probably best to just put the name of your app in there. You need to be able to tell which App ID belongs to which app and the name is probably the easiest. So however you want to do that, it is totally up to you.

You will also need to enter your bundle ID in the “App ID Suffix” section. To find your bundle ID you will need to open up Xcode and open your project. In Xcode you will need to highlight your project file and then select your project in the dropdown in the upper-left corner of the window you need to select your application name under “Targets.” You need to navigate over to the “Info” tab and look at the Bundle Identifier value on this screen. You can change this to whatever you like. I like the reverse domain notation. If it were me doing this I would put com.ninebitstudios.name where “name” is the name of my application. So it would be something like com.ninebitstudios.fishblaster or something like that. But you can put whatever you want in here. Once you have this set, you need to also enter this in the “App ID Suffix” section in the App IDs section in your developer account. After you do this scroll down to the bottom of the page and click “Continue.”

There will be a confirmation screen on the next screen where you can click “Submit” and then on the next screen click “Done.” You should now see your App ID in the table view of iOS app IDs.

Creating an iOS Provisioning Profile in Developer Center

Back in the developer center, Under the “Provisioning Profiles” section in the “Certificates, Identifiers & Profiles” screen click on “Distribution.” Click on the “+” button to create a new provisioning profile. In the next section scroll down and choose “App Store” to create a distribution provisioning profile to submit your app to the App Store and click on “Continue”.

iOS

In the next section from the you can choose your app ID in the dropdown and click “Continue”.

Next you can create a name for the profile. You can put whatever you want in here, the name of your organization or the name of your application.

iOS

After you have chosen something click on the “Generate” button. This will take you to a screen where you can download your iOS Provisioning Profile. Download this .mobileprovision file and save it somewhere on your computer.

Now go to the location where you downloaded this provisioning profile. Double click on it and choose the “Add to Library” option to add this profile to the iPhone configuration utility.

Creating an App in iTunes Connect

Now you need to go to back to your developer center at developer.apple.com. From here you will need to select “iTunes Connect” and once you are in iTunes Connect you need to select the “My Apps” option. You will need to click on the “+” button to add a new app.

From here there is a lot of information that you will need to fill out for your application. This is basically a way of creating a new application portal where everything that will be used by Apple to publish your app will go. You will need to add some screenshots of the proper dimensions that will be used for the App Store previews. The tools and notifications provided there should give you indicators as to what items or information you need to provide. You can do this now or you can wait until after your application file has been uploaded and you are ready to finalize your submission to Apple for review.

Configuring & Packaging Project in Xcode

After you have done the above steps you will need to open Xcode if it is not already open. For an Apache Cordova project you can open the project by going to /platforms/ios and double clicking on the “.xcodeproj” file. You will then need to highlight your project in the left pane in Xcode and select your project under “Projects” in the upper left (i.e. do not select your project under “Targets”)

iOS

Click on the “Info” tab and in the “Configurations” section click on the “+” button and choose the “Duplicate Release Configuration” option. Double-click the newly created/duplicated configuration and rename it to “Distribution.” You should only have “Debug”, “Release”, and “Distribution.”

Next select your project under “Targets” in the upper left (i.e. do not select your project under “Project”). Next highlight the “Build Settings” tab. In the “Code Signing” section change all of the options under “Code Signing Identity” to the name of your certificate that you created earlier. Next change all of the options under “Provisioning Profile” to the value of the provisioning profile that you created earlier.

You will then need to do the exact same steps only this time you need to highlight your project in the left pane in Xcode and select your project under “Projects” in the upper left (i.e. do not select your project under “Targets”). After you do this highlight the “Build Settings” tab. In the “Code Signing” section change all of the options under “Code Signing Identity” to the name of your certificate that you created earlier. Next change all of the options under “Provisioning Profile” to the value of the provisioning profile that you created earlier. So it is a repeat of the same process that you just did for when you had your project selected under “Targets”

iOS

Next highlight your simulator at the top of your screen and choose the “iOS Device” option.

iOS

Then select “Product” in the top menu and choose “Archive.”

iOS

If all goes well, you should get a “Build Succeeded” notification.

Submitting to App Store Option #1 – Submit to App Store Button

You now have your finished product that you will submit to the App Store. You should see something like the following screen…

iOS

To submit your app to Apple’s App Store all that you have to do is click the “Submit to App Store…” button. If you want you can use some of the tools to validate your project if you like to make sure that there are no errors.

If all goes well you should see the following…

iOS

If you run into any issues doing things by this process, you can try the approach below.

Submitting to App Store Option #2 – Uploading your Archive (.ipa file)

If you run into an issue that says “Unable to validate your application. The application you have selected does not exist” or recieve other error messages of any sort, you might have to try to use an alternate method of submitting your app. Apparently this is an issue that occurs for some developers in some environments. If you run into this issue you can still submit your application manually. You can use the “Application Loader” utility to upload your app to the App Store. Select this utility by choosing Xcode > Open Developer Tool > Application Loader from the top menu

iOS

With the Application Loader utility open, click the “Export” button on this screen. In the prompt, select the “Save for iOS App Store Deployment” option.

iOS

Click on the “Next” button. You will be prompted choose your developer account. Then click “OK.” This will create a .ipa file for you on your computer. You can then go add this file in iTunes Connect by signing in to your account and uploading it there.

Finalizing your Submission in iTunes Connect

Once you have uploaded your application, you need to go back to iTunes Connect and finalize your submission to Apple. You can finish uploading the required icons and screenshots at this time if you have not done so already. Once you have everything set, click on the “Submit for Review” button and follow the prompts. There is a review process that every app submitted to Apple undergoes to ensure quality assurance and that the app follows all of Apple’s requirements and guidelines for selling apps. It will take about 10 days for Apple to get around to reviewing your app and they will notify you on whether it is approved for sale or rejected.

If your app is rejected, do not be discouraged. Nearly every app developer has had an app rejected at some point or another. You just need to fix the issues that are outlined by the review team and resubmit. Fortunately the resubmission process goes pretty quickly because you already have all of the bits in your project set up. You’ll just need to fix what needs to be fixed in your Cordova project and rebuild and follow all of the same steps as outlined above. Fortunately, most of the hard work of filling out all the forms and creating the provisioning and distribution files is already done.

Sometimes it takes one or two tries to get your app approved, but if you keep at it, you’ll get there!

Submitting to Your Cordova App for Android to Google Play


To submit your Apache Cordova application for sale (or free download) on Google Play you will need to go through the normal process that all Android apps must go through before they are submitted to Google Play. In many ways the process of distributing applications on Android via Google Play is a lot more streamlined, quicker, and developer-friendly (i.e. easier) when compared to submitting apps to Apple’s App Store.

Creating an Application in the Google Play Developer Console

The first thing that we will need to do in order to prepare for distributing our application on Android is to create a new application within this Google Play Developer console. You will need to sign into you Google Play Developer Console and then you’ll need to click on the “Add New Application” button and fill out the details for your app. You will need to upload some screenshots, icons and also answer some questions to get your app a rating to indicate the “age appropriateness” of you app and the degree to which it contains mature/adult content. You will also see that that there is a button to upload an “APK” file. This is your app file for Android which we will create next.

Creating an APK File

In the following sections we will build an APK file (which is shorthand for Android application package) that we submit to Google Play. You need to compile the release file by running the following command in the root of your Cordova project…

$ cordova build android --release

This will create a file in the /platforms/android/build/outputs/apk directory called android-release-unsigned.apk (or something like that). Hang on to this file (or make a copy of it) because we will need it later.

The “unsigned” designation just means that it has not been signed with a certificate of authenticity. Later on we will be adding the credentials from our developer account for security purposes. We will need to do that by using a number of the tools provided by Java to “sign” our application. The first utility we will utilize is the “keytool.” The keytool utility is part of what ships with the Java Development Kit (JDK). So on my windows machine it was located at C:\Program Files\Java\jdk1.7.0_51\bin\keytool.exe. The location might be different for different operating systems. It’s basically wherever your JDK is installed in the “bin” directory. Wherever it is on you computer, run the keytool utility with the following command (or its equivalent)…

$ keytool -genkey -v -keystore ninebitapp.keystore -alias ninebitapp -keyalg RSA -keysize 2048 -validity 10000

You can change the name of your keystore file in the -keystore flag to whatever you want. All that specifies is the name of the file that gets output after running this command.

Next we will take the .keystore file that was created with the keytool utility and sign it using another utility that ships with the JDK called “jarsigner.exe.” Get the android-release-unsigned.apk file that we grabbed from our Cordova project. Using this file and the generated .keystore file we created from the previous command and run the following…

"C:\Program Files\Java\jdk1.7.0_51\bin\jarsigner.exe" -verbose -sigalg SHA1withRSA -digestalg SHA1 -keystore ninebitapp.keystore app.apk ninebitapp

NOTE: I actually renamed the .apk file to “app.apk.” Reason being, I encountered an error when trying to use jarsigner tool when the filename was left as “android-release-unsigned.apk” I guess the tool doesn’t like hyphens?

When you run this command you will have to enter some credentials to password protect this file for your Google Play developer account with this certificate of authenticity.

Now that we have signed the .apk file we will use the “zipalign” tool to prepare our application for release. The “ZipAlaign” tool can be found in the Android SDK directory. We can utilize it by running the following command on our signed .apk file.

"C:\Users\IanC\AppData\Local\Android\sdk\build-tools\22.0.1\zipalign" -v 4 app.apk ninebit_out.apk

This will create a zip aligned .apk file. It is this file we will submit to the Google Play store via the Google developer console. Just follow the prompts there and submit. Google Play apparently does have a brief review process, but really it’s probably just to confirm that the app launches and does not contain any malware. Unlike with the App Store, your app will almost certainly be approved if it passes these 2 smoke tests. Also, you expect your app to be available for download on Google Play within a few hours. This is a much shorter duration than the 10 days it takes for the iOS review process.

Summary

In the preceeding discussions we went through and looked at the process for building your apps for release on iOS and Android and submitting your applications to the Apple App Store and Google Play. Hopefully, in reading this you have found this at least somewhat helpful. Until next time, happy developing! Go create great apps!

]]>
https://9bitstudios.com/2016/01/submit-apache-cordova-applications-for-ios-and-android-to-the-apple-app-store-google-play/feed/ 1
Develop Apache Cordova Applications with HTML5 & JavaScript https://9bitstudios.com/2015/12/develop-apache-cordova-applications-with-html5-javascript/ https://9bitstudios.com/2015/12/develop-apache-cordova-applications-with-html5-javascript/#respond Sat, 19 Dec 2015 22:59:14 +0000 https://9bitstudios.com/?p=1124 In a prior discussion we looked at how to set up a project so that we could develop an Apache Cordova application using HTML5 and JavaScript. In that section we mostly covered how to set up, build, and run the project — which consisted of the same application in the www folder that Apache Crodova bootstraps when you create a new project. In what follows we will look at the approach for actually writing own code for our app and will look at how an app in Apache Cordova gets initialized. We will also look at how we can extend the Apache Cordova platform by using plugins to give ourselves additional features and functionality that will make for an all around better user-experience (UX) for the users of our app.

Now that we have our project set up and all our platforms added all that we have left to do now is create our application by creating what basically amounts to a website that runs HTML and JavaScript in the “www” folder. How should one develop for Apache Cordova? Personally, I would delete all of the boilerplate files and folders and start from scratch. That is what we will do here. Just take a quick note of how things are referenced in the index.html file and do the same for your own files.

In doing this, I have modified the index.html file in the “www” folder to the following…

<!DOCTYPE html>
<html>
    <head>
        <meta http-equiv="Content-Security-Policy" content="default-src 'self' data: gap: https://ssl.gstatic.com 'unsafe-eval'; style-src 'self' 'unsafe-inline'; media-src *">
        <meta name="format-detection" content="telephone=no">
        <meta name="msapplication-tap-highlight" content="no">
        <meta name="viewport" content="user-scalable=no, initial-scale=1, maximum-scale=1, minimum-scale=1, width=device-width">
        <link rel="stylesheet" type="text/css" href="css/index.css">
        <title>Cordova Application</title>
    </head>
    <body>
        
        <div id="main">Initializing...</div>
        
        <script type="text/javascript" src="cordova.js"></script>
        <script type="text/javascript" src="js/index.js"></script>
    </body>
</html>

Note: Do not worry about that “cordova.js” reference or the fact that this file is nowhere to be found in our “www” folder. Apache Cordova will utilize this in the proper context when the app runs (so leave it in there).

So as far as the index.html goes, there is nothing too fancy. I have a css file (index.css) and a js file (index.js). That is all you need to get started.

Next, let’s look at our JavaScript in the index.js file. There is really only one thing you need to make note of when you develop Apache Cordova applications in JavaScript. There is a special event that Apache Cordova uses to tell the platform that the everything is loaded and the device you are using is ready to start running JavaScript in your Cordova application. This is what is known as the “deviceready” event. It only fires when you are running an app within a Cordova context (i.e. on a device or an emulator of a device). In a lean version of JavaScript for a cordova application would look like the following (in index.js)…

var app = {
    init: function() {
        document.addEventListener('deviceready', this.main, false);
    },
    main: function() {
        document.getElementById('main').innerText = 'App is ready...'
    }
};

app.init();

Here we are calling the “init” function which will add a listener for the “deviceready” event. When this event fires the “main” function will run, which in this case just changes the inner text of a div element So if we run this using

$ cordova emulate android

or

$ cordova emulate ios

from the root of our project we will see our device boot up, our app launch, and if all goes well we will see the text “App is ready…” so we know that our event is firing.

But it gets kind of annoying to have to fire up the emulator every time we want to test something out or make small changes in doing development. So it would be easier to be able to open the index.html file in the browser. But the problem with this is that the browser does not natively support the “deviceready” event. If you try to open index.html in a browser you see that the text remains as “Initializing…” The “deviceready” event does not get fired by the browser. So to get around this we have to set a flag so that we conditionally check if we are trying to run our app in a browser. So update the code in index.js to the following…

var config = {
    DEV: true    
};

var app = {
    init: function() {
        if(config.DEV) {
            this.main();
        } else {
            document.addEventListener('deviceready', this.main, false);
        }
    },
    main: function() {
        document.getElementById('main').innerText = 'App is ready...'
    }
};

app.init();

Now that we have set a flag in config to check whether we are just intending to run in “dev mode” in the browser, we will just call the main function directly and that will be the place that we kick off our application. We essentially bypass the “deviceready” step.

Now if you run this in the browser, we see that the “App is ready…” text is rendered to the page. If we change the config.DEV flag to “false” and run

$ cordova emulate android

or

$ cordova emulate ios

we can see that our main function is still running to kick off our app.

Even though the “deviceready” event is kind of the official Apache Cordova way of making sure that everything is initialized, if you forget to change the “DEV” flag to “false” and directly call the “main” function while running on a device, things will probably still work.

Splash Screens, Icons, & Using Plugins

Apache Cordova gives you a great framework out of the box to create a mobile app that can run on different platforms (as we have seen). But as great as it is, often there are things that you run into that may not be as easy to implement as they would be if you were creating an app using the native tools and languages. Fortunately, if you run into something that is not natively supported in Apache Cordova, there is a vibrant plugin ecosystem (and community behind it) that has worked to extend the support and functionality of the framework. You may have noted that there was a “plugins” folder in our Apache Cordova project. This is where installed plugins go.

Let’s take a look at a plugin that allows us to display a “splash screen” while our app launches. This is a common feature that you may have seen in many apps. We will use the cordova-plugin-splashscreen plugin. This plugin will allow us to specify paths to images that we will use as our splash screens. Because there are so many different resolutions across iOS and Android phones and tablets, we are going to have to specify a number of different resolutions of images that we will use for our splash screens. It will also allow you to show the Rather than list out what each of these resolutions need to be I have included a sample Apache Cordova project here as a download with some blank images of the sizes that they need to be to support this feature on most (nearly all) modern devices (iPhones, iPads, Android phones, and Android tablets). You can find these in the “res” folder in the “www” directory.

This cordova-plugin-splashscreen plugin will also allow us to specify the images that will be used for the icon of our app that shows up on the user’s home screen when the app gets installed. Up until now, Apache Cordova has just been using its own default image (that little robot looking thingy). But with this plugin we can change the icon, to what we want it to be! Awesome!

To install our plugin we just need to run the following from the root of our Apache Cordova project…

$ cordova plugin add cordova-plugin-splashscreen

If for some reason that does not work for you, you can try running the following

$ cordova plugin add https://github.com/apache/cordova-plugin-splashscreen.git

Once the plugin is installed we can now specify the paths to our splash screens and icons. We will do this in the config.xml that resides in the root of our project. As mentioned prior I have posted a sample Apache Cordova project that is available for download. In that project we can see the config.xml file that looks like the following…

<?xml version='1.0' encoding='utf-8'?>
<widget id="com.sample.sampleapp" version="0.0.1" xmlns="https://w3.org/ns/widgets" xmlns:cdv="https://cordova.apache.org/ns/1.0">
    <name>SampleApp</name>
    <description>
        A sample Apache Cordova application...
    </description>
    <author email="dev@cordova.apache.org" href="https://cordova.io">
        Apache Cordova Team
    </author>
    <content src="index.html" />
    <plugin name="cordova-plugin-whitelist" spec="1" />
    <access origin="*" />
    <allow-intent href="https://*/*" />
    <allow-intent href="https://*/*" />
    <allow-intent href="tel:*" />
    <allow-intent href="sms:*" />
    <allow-intent href="mailto:*" />
    <allow-intent href="geo:*" />
    <platform name="android">
        <allow-intent href="market:*" />
        <!-- Android Icons -->
        <icon src="www/res/android/icons/ldpi.png" density="ldpi" />
        <icon src="www/res/android/icons/mdpi.png" density="mdpi" />
        <icon src="www/res/android/icons/hdpi.png" density="hdpi" />
        <icon src="www/res/android/icons/xhdpi.png" density="xhdpi" />
        
        <!-- Android Splash Screens -->
        <splash src="www/res/android/screen/splash-land-hdpi.png" density="land-hdpi"/>
        <splash src="www/res/android/screen/splash-land-ldpi.png" density="land-ldpi"/>
        <splash src="www/res/android/screen/splash-land-mdpi.png" density="land-mdpi"/>
        <splash src="www/res/android/screen/splash-land-xhdpi.png" density="land-xhdpi"/>
        <splash src="www/res/android/screen/splash-port-hdpi.png" density="port-hdpi"/>
        <splash src="www/res/android/screen/splash-port-ldpi.png" density="port-ldpi"/>
        <splash src="www/res/android/screen/splash-port-mdpi.png" density="port-mdpi"/>
        <splash src="www/res/android/screen/splash-port-xhdpi.png" density="port-xhdpi"/>   		
    </platform>
    <platform name="ios">
        <allow-intent href="itms:*" />
        <allow-intent href="itms-apps:*" />
        <!-- iOS Icons -->
        <icon src="www/res/ios/icons/icon-60@3x.png" width="180" height="180" />
        <icon src="www/res/ios/icons/icon-57.png" width="57" height="57" />
        <icon src="www/res/ios/icons/icon-57@2x.png" width="114" height="114" />
        <icon src="www/res/ios/icons/icon-60.png" width="60" height="60" />
        <icon src="www/res/ios/icons/icon-60@2x.png" width="120" height="120" />
        <icon src="www/res/ios/icons/icon-76.png" width="76" height="76" />
        <icon src="www/res/ios/icons/icon-76@2x.png" width="152" height="152" />
        <icon src="www/res/ios/icons/icon-40.png" width="40" height="40" />
        <icon src="www/res/ios/icons/icon-40@2x.png" width="80" height="80" />
        <icon src="www/res/ios/icons/icon.png" width="57" height="57" />
        <icon src="www/res/ios/icons/icon@2x.png" width="114" height="114" />
        <icon src="www/res/ios/icons/icon-72.png" width="72" height="72" />
        <icon src="www/res/ios/icons/icon-72@2x.png" width="144" height="144" />
        <icon src="www/res/ios/icons/icon-small.png" width="29" height="29" />
        <icon src="www/res/ios/icons/icon-small@2x.png" width="58" height="58" />
        <icon src="www/res/ios/icons/icon-50.png" width="50" height="50" />
        <icon src="www/res/ios/icons/icon-50@2x.png" width="100" height="100" />
        
        <!-- iOS Splash Screens -->
        <splash src="www/res/ios/screen/Default~iphone.png" width="320" height="480"/>
        <splash src="www/res/ios/screen/Default@2x~iphone.png" width="640" height="960"/>
        <splash src="www/res/ios/screen/Default-Portrait~ipad.png" width="768" height="1024"/>
        <splash src="www/res/ios/screen/Default-Portrait@2x~ipad.png" width="1536" height="2048"/>
        <splash src="www/res/ios/screen/Default-Landscape~ipad.png" width="1024" height="768"/>
        <splash src="www/res/ios/screen/Default-Landscape@2x~ipad.png" width="2048" height="1536"/>
        <splash src="www/res/ios/screen/Default-568h@2x~iphone.png" width="640" height="1136"/>
        <splash src="www/res/ios/screen/Default-667h.png" width="750" height="1334"/>
        <splash src="www/res/ios/screen/Default-736h.png" width="1242" height="2208"/>
        <splash src="www/res/ios/screen/Default-Landscape-736h.png" width="2208" height="1242"/>  		
		
    </platform>
    <preference name="SplashScreen" value="screen" />
    <preference name="SplashScreenDelay" value="4000" />
</widget>

As we can see, we have specified paths to a number of different images of different resolutions. with these settings the cordova-plugin-splashscreen Apache Cordova plugin will automatically figure out which is the best resolution to use depending on the

We can also see that in the <preference> elements down at the bottom we have specified “SplashScreenDelay” preference down at the bottom of the config.xml file. This specifies to show the splash screen for 4 seconds (4000 milliseconds). You can change this value to the one that you prefer.

Now if you run your application with

$ cordova emulate android

or

$ cordova emulate ios

You will see a splash screen displayed before the app launches. It’s blank for now until you bust out your graphic designer skills and create a nice looking one. If you click on the “home” button on the emulator device you can see on the home screen that the icon we have in our project is now used as the app icon. Like with the splash screen, obviously for a production app we would want to make nice looking icons consistent with the theme of our app. But the functionality is there and all you have to do is replace the icons and splash screens in the sample project with your own app branding.

So sample project and try it out. Note: After downloading the project you will need to 1) add the platform(s) that you want to work with with $ cordova platform add and 2) install the splash screen plugin with $ cordova plugin add cordova-plugin-splashscreen.

Summary

Now that we have walked through how to set up some app initialization code from here, everything that you want to do is entirely up to you. There are really no limitations on what you can do here. Apart from the unique “deviceready” event there is nothing special that you need to do to code for Apache Cordova (and even hooking into the “deviceready” event probably isn’t even absolutely essential). You can just create things in the same way that you would if you were going to put this web application on the web and have users run it in their browsers. There is no special magic needed. You can add more CSS files, images, other JavaScript files, or whatever else you want to and start building. You can use popular front-end frameworks like Bootstrap or Foundation. Or, if you prefer, you can import a framework specifically designed for mobile such as jQuery Mobile. You can use popular JavaScript development frameworks like Backbone.js, Ember.js, AngularJS, or React. Ultimately the choice is entirely up to you. I cannot choose for you.

From there, the sky’s the limit. You can do whatever you like to create whatever kind of app you want. But since there are so many different types of applications for so many different purposes, it is ultimately up to you to decide on what technologies you want to use and what is the best way to implement your app. So get out there and develop it up. Until next time, cheers and happy developing!

]]>
https://9bitstudios.com/2015/12/develop-apache-cordova-applications-with-html5-javascript/feed/ 0
Create Mobile Applications for iOS and Android with HTML5, JavaScript, and Apache Cordova https://9bitstudios.com/2015/12/create-mobile-applications-for-ios-and-android-with-html5-javascript-and-apache-cordova/ https://9bitstudios.com/2015/12/create-mobile-applications-for-ios-and-android-with-html5-javascript-and-apache-cordova/#respond Sat, 12 Dec 2015 22:49:53 +0000 https://9bitstudios.com/?p=1101 Obviously at the time of this writing in the 2nd decade of the 21st century, you are no doubt well acquainted with the immense proliferation and impact that mobile apps have had in and on our world. It was not long ago that we were all sitting at our computers at our desks for the large majority of the time we spent in our various avenues of technological communications over the Internet — complete with our with our giant monitors, whirring computer fans, buzzing drives, and the garbled noise of dial-up modems. Now, mobile phones and tablets probably make up as much, if not more, of our time spent working, playing, and communicating online. Everyone has a ~$100 to $600 smartphone (i.e. computer) in their pocket. And with this rise of mobile, apps found on the popular stores — like Apple’s iOS App Store, Google Play (Android), Amazon and a host of others — have completely transformed the way that we do anything and everything because well, there is an app for anything and everything. Every single facet of life probably has an app to manage some aspect of it. Need to remember to breathe? There is an app for that! Yeah, that is a joke (probably)… but there are plenty of “real” apps out there (e.g. iBeer) that are just as pointless. Fun and goofy, yes, but pointless. And they all post their pointlessness to Facebook and/or Twitter.

Whether you want to develop an app to manage some minute aspect of life or just create a fun game, or whatever else, you can download the SDK for the platform(s) that you want to release your app on, do some tutorials, and start building. That’s all well and good, but if you want to port your application to another platform (e.g. release an iOS app also for Android), you will essentially have to try rebuild the same app using the languages in tools of a different platform. For example, iOS apps for iPhone and iPad have traditionally been developed on a Mac in the Xcode IDE using the Objective-C programming language (though Apple has recently released a new language called Swift that can also be used to build iOS apps). Android apps, by contrast are built using Java and Eclipse or the more recently released Android Studio. Native Windows Phone apps are built using C# and XAML in Visual Studio. Other platforms have their own setups. If you want to take this approach you definitely can, but it should be fairly apparent that developing and maintaining a number of different codebases for multiple platforms quickly adds up to a lot of time, effort, and often money as the sizes and complexity of your apps increase.

At the same time as the rise of mobile in the past decade, something else has occurred: the rise of HTML5 and JavaScript web applications. Beginning at around 2009 – 2010 one of the more noticeable developments was the rise of websites and web applications making use of more open technologies such as HTML5 and JavaScript to bring interactivity and 2-way communication between clients (usually browsers) and servers. With Flash on the way out due its proprietary nature, resource hogging, security issues, poor SEO — along with its being snubbed by Apple for support on iPhones and iPads for basically all these reasons — meant that something had to fill the void. HTML5 and JavaScript moved into this space and developers started turning to it for creating interactive “app-like” experiences.

Wouldn’t it be awesome if there were a way to write a single application in HTML and JavaScript with a single codebase and have a way to port this application to all of the different mobile platforms? I am so glad you asked.

Apache Cordova — also commonly known as “PhoneGap” (the only difference between the two is propriety) — allows us combine combine these open technologies together with the SDKs of the various mobile application platforms to make native mobile applications using technologies such as HTML and JavaScript. You can basically create a small static HTML and JavaScript website or web application and this code will be imported into native iOS, Android, Windows Phone projects and configured specifically for the respective platforms. Thus, you *do* still have to have the SDK of the platform installed to build, run, and release the apps. So to create an iOS app you will still need a Mac and Xcode. To create Android apps you will need to install the Android SDK (which comes with the Android Studio IDE). But the important aspect of using Cordova is that the HTML and JavaScript that each project will pull in and build will be the same across all platforms. Want to release an update with some slick new features or fix some bugs that have been reported by your users? You need only change your code in your HTML and JavaScript. You don’t have to try and rewrite the same code and/or functionality in a different language on each platform. From there all you need to do is run a few simple commands from the command lines and your HTML and JavaScript will get built and converted into an application that can run on the platform(s) you are targeting.

In what follows we will explore what it looks like to use Cordova to create a mobile application in HTML and JavaScript that can run on a number of different platform. For our examples, we will build our app for iOS and Android, but the process is essentially the same for building for other platforms (e.g. Microsoft Windows Phone, Amazon Kindle Fire). You would just need to download the SDKs for those platforms if you wanted to run your app on those types of devices as well.

So let’s get to it…

Installing Node.js

The first thing that we will need to do before we do anything else is install Node.js. Apache Cordova runs on Node.js so it is a prerequisite. If you’re not entirely familiar with Node.js there is a primer on Node.js here. It has become a huge part of JavaScript development in the last half-decade and is only becoming more and more prominent.

To install Node.js all you have to do is head on over to their website and follow the directions for your operating system (Windows, Mac, or Linux).

Installing Apache Cordova

Once we have Node.js installed, next we will need to install Apache Cordova. We just do this over npm. npm comes with the Node.js installation, so you already have it on your machine from installing Node.

To install Cordova open up a command window or terminal and run the following…

$ npm install -g cordova

In case you are not familiar with it, the “-g” flag means “global.” You will want to do this so that you can run Cordova commands from any directory on your system.

Creating an Apache Cordova Project

Now you can go to a directory where you want to create your Cordova project and open a command window/terminal. We will be initializing a new Cordova application here with the Cordova “create” command. For more information on the configuration options you can choose when installing and setting up your project, please see the Apache Cordova documentation here. Run the following command from your command line…

$ cordova create ninebit com.ninebitstudios.ninebitapp NinebitApp

The command above will create a vanilla Cordova project called “NinebitApp” and ocnfiguring it with a unique ID that uses reverse domain name notation in a directory named “ninebit.” What you will want to do is change these values to what you want for your own application.

$ cordova create   

For example…

$ cordova create yourdirectory com.yourdomain.yourapp YourAppName

but just plug your own values that you want in there.

You should see the directory with the name you specified created with with a number of files and directories in there like “platforms,” “plugins,” “www”, and a “config.xml” file. The config.xml file will have some of the values that you specified in your mobile. The actual location where you will write your HTML and JavaScript is in the “www” directory. If you explore that directory and open the index.html file you will see a boilerplate web application which basically just displays an image on the page. Even though it does not do much, this is an app that can run on any of the platforms we want to specify. We will add these platforms next.

Adding Support for Android Devices to the Project

Now that we have our project created we need to “add” the platforms that we want to release on to our project. Open a command window in the root directory of the project (the one with the config.xml file).

To add Android to our project run the following…

$ cordova platform add android

You should see a directory called “android” in the platforms folder. This folder contains a native Android project that is preconfigured to take the HTML and JavaScript in the “www” folder and run it in an Android device. If you opened Android Studio and clicked on “Create New Android Project” you would see almost the same files and folders in the project that gets created when creating a native Android application. There will be few extra files and folders in the Cordova Android project specific to Apache Cordova.

Because we now have a native Android project, we can run it on the Android emulator. In the root directory we can now run following…

$ cordova emulate android

This should launch the Android emulator and automatically run your application after it boots up. Note that you might need to set up a device for Android project to use before you try to run the command above. To do this, you will need to launch the Android Virtual Device Manager (AVD Manager.exe). This application resides in the root folder of where you installed your Android Studio SDK. You can also launch AVD Manager in Android Studio under the “Tools” menu under “Android.” However you open this application, once you are in there just click “Create New” and pick whatever device you want. Once you get the device set up you can try to run the command above again.

Adding Support for iOS Devices to the Project

Similarly, if you want to add support for iOS

$ cordova platform add ios

As was the case with Android above, you should see an “ios” directory. This folder contains a native Xcode project that is preconfigured to take the HTML and JavaScript in the “www” folder and run it in an iOS device.

Remember that you *must* have the SDK of the platform you are trying to add installed on your system. If you do not the Cordova console should inform you of this error.

For iOS you will want to make sure that you have the proper folder permissions in all of the directories and folders you will be working in. I had some issues trying to emulate when running all the cordova commands with sudo. So make sure on your Cordova project directory you do something like the following…

$ sudo chmod -R 777 foldername

so that you can run all the commands without using sudo

The first thing that you’ll want to do is add the iOS platform to your project.

$ cordova platform add ios

You can then build for iOS by running the following command. If you are able to do so without errors, you’ll know that everything is all good.

$ cordova build ios

Note in /platforms/ios/cordova/lib there is a list-emulator-images tool that you can run to list out all of the emulator images that you have installed. These are the different devices that you can emulate your apps…

$ ./platforms/ios/cordova/lib/list-emulator-images 

You will see a list like the following…

  • iPhone-4s
  • iPhone-5
  • iPhone-5s
  • iPhone-6-Plus
  • iPhone-6
  • iPad-2
  • iPad-Retina
  • iPad-Air
  • Resizable-iPhone
  • Resizable-iPad

If you want to specify a target, you can run the simulator on a specific device by targeting a specific device. For example…

cordova emulate ios --target="iPhone-4s"
cordova emulate ios --target="iPad-Air"
cordova emulate ios --target="iPhone-6"
cordova emulate ios --target="iPhone-6-Plus"

Otherwise, the iOS development tools will just use what is set as the default device (usually the latest version of the iPhone that is currently in production).

And of course, if you want to emulate on an iOS device in Xcode you can run the following command in your project root…

$ cordova emulate iOS

This should launch the iOS simulator and run your application.

Summary

In the above discussion we looked at all of the steps, tools, and environments necessary to create an Apache Cordova project and get things set up such that you can begin developing cross-platform mobile applications. In a future discussions we will take a deeper look at how write the code for out apps as well as how to package everything in your application up once you are finished developing and submit it to the respective stores for iOS (App Store) and Android (Google Play). But those are other discussions for some other days. So until next time, happy mobile developing!

]]>
https://9bitstudios.com/2015/12/create-mobile-applications-for-ios-and-android-with-html5-javascript-and-apache-cordova/feed/ 0
Debugging Node.js Applications with Node Inspector https://9bitstudios.com/2015/10/debugging-node-js-applications-with-node-inspector/ https://9bitstudios.com/2015/10/debugging-node-js-applications-with-node-inspector/#respond Thu, 29 Oct 2015 13:46:46 +0000 https://9bitstudios.com/?p=1087 Debugging is an important part any sort of application development. If you have errors or unexpected results occurring in your code you need to be able to step through your code and find where things are going awry. Thus it is very important that you are able to see what is happening at specific times when your code is executing. There are some IDEs (integrated development environments like Visual Studio or Eclipse) where debugging for the native application language like C# or Java is all built right into the tools and you don’t have to do anything to set it up. At the time of this writing in the later part of the year 2015, there are a few IDEs such as WebStorm and Komodo IDE that natively support Node.js debugging but this is often the exception rather than the rule (at present). Node.js, being a younger and relatively more immature platform often does not have debugging for it natively implemented in most IDEs yet. Fortunately, there are often plugins available that will enable Node.js debugging within the IDE. Node.js tools for Visual Studio 2012 and 2013 is one example. Nodeclipse is a plugin that will enable Node.js debugging capabilities in Eclipse.

Because there are so many different development environments and workflows that different developers have different preferences for we won’t look at debugging Node.js applications in a specific IDE. But we will look at a specific debugger called Node Inspector. There are other Node.js debuggers out there and if you want to use another debugger that is fine. You would just have to look at the docs for that particular debugger. It should be noted that Node Inspector works in Chrome and Opera only. You have to re-open the inspector page in one of those browsers if another browser is your default web browser (e.g. Safari or Internet Explorer). This is another indicator that shows widespread support for many things in and within Node.js is not entirely quite there just yet. So much of the Node.js module ecosystem is community driven, which has very noticeable pros and cons. The upside to this it is that there are a lot of awesome components of functionality that you can leverage via installation with a simple $ npm install of a module. The downside of this environment is that support and/or consistency for bug fixes and releases can vary quite a bit depending on who’s module(s) you are using. Just as a personal opinion, I find that on the whole the positives outweigh the negatives when it comes to open source software. I would much rather take this scenario over, say, a behemoth corporation owning and managing all of the releases that might seem more “professional” in its support and maintenance (as opposed to hobby/side-project code). But developing in and for open source applications is definitely far from perfect.

But all that aside, let’s get back to fun with Node.js debugging. Node Inspector works almost exactly as the Google Chrome Developer Tools. If you are not entirely familiar with Google Chrome’s developer tools read the DevTools overview to get started. Dev Tools can be used to set breakpoints in your application that halt the execution of the code when a certain statement (or statements) are reached. From there you can examine the state of particular objects to see what values they contain at that point in time. You can then step through your code moving from one statement to the next to see how the values change. If this all seems a little bit confusing at this point, not to worry. We will revisit this a bit later when we actually take on the task of debugging our application. But first we need to install the stuff we need to get debugging up and going.

Installing Node Inspector

To install Node inspector we will use the npm utility to install Node Inspector from npm.

$ sudo npm install -g node-inspector

Note: Windows 8.1 Users: At the time of this writing in the later part of 2015 for Windows 8.1 I had to omit installing an optional dependency which apparently breaks the install using npm. The way that you do this is by setting the –no-optional flag…

$ npm install -g node-inspector --no-optional

That should get it working for you. To check that it installed correctly you can always run

$ node-debug --version

which should output the version number for you without any error messages.

Sample Application

For our application we will use a sample API that I often utilize for demonstrating Node.js applications that uses Express.js as an application framework. If you are not familiar with Express there is an introduction to Express here. If you need a quick refresher on Node.js by any chance you can read A Node.js Primer. For a more in-depth look at Express.js, there is also an ongoing series entitled Creating an MVC Express.js Application.

We will start out by creating a package.json file and placing the following code within it…

{
    
    "name": "Node.js-API",
    "description": "An API in Node.js...",
    "version": "0.0.1",
    
    "repository": {
        "type": "",
         "url": ""
    },
    "dependencies": {

        "express": "4.4.4",
        "express-session": "1.5.1",
        "basic-auth": "1.0.3",
        "cookie-parser": "1.3.1",
        "body-parser": "1.4.3",
        "hbs": "3.1.0",
        "morgan": "1.1.1",
        "method-override": "2.0.2",
        "errorhandler": "1.1.1"
    }

}

We then run

$ npm install

to install all the dependencies.

Next, create a file called server.js with the following code…

var express = require('express');
var bodyParser = require('body-parser');
var cookieParser = require('cookie-parser');
var session = require('express-session');
var logger = require('morgan');
var methodOverride = require('method-override');
var errorHandler = require('errorhandler');
var http = require('http');
var path = require('path');
var app = express();
app.set('port', 1337);

app.set('view engine', 'html');
app.engine('html', require('hbs').__express);

/* Morgan - https://github.com/expressjs/morgan
 HTTP request logger middleware for node.js */
app.use(logger({ format: 'dev', immediate: true }));

/* cookie-parser - https://github.com/expressjs/cookie-parser
 Parse Cookie header and populate req.cookies with an object keyed by the cookie names. */
app.use(cookieParser('SECRETCOOKIEKEY123'));

/* body-parser - https://github.com/expressjs/body-parser 
Node.js body parsing middleware. */
app.use(bodyParser.json());
app.use(bodyParser.urlencoded({ extended: true }));

/* method-override - https://github.com/expressjs/method-override
 Lets you use HTTP verbs such as PUT or DELETE in places where the client doesn't support it. */		    
app.use(methodOverride());

app.use(express.static(path.join(__dirname, '')));

/* errorhandler - https://github.com/expressjs/errorhandler
 Show errors in development. */
app.use(errorHandler({ dumpExceptions: true, showStack: true }));

// send app to router
require('./router')(app);

http.createServer(app).listen(app.get('port'), function(){
  console.log('Express server listening on port ' + app.get('port'));
});

Next create a file called router.js with the following code…

// Routes
module.exports = function(app){ 
    // index.html
    app.get('/', function(request, response){
        response.render('index', {});
    }); 
    // API
    var artists = [
        { id: 1, name: 'Notorious BIG', birthday: 'May 21, 1972', hometown: 'Brooklyn, NY', favoriteColor: 'green' },
        { id: 2, name: 'Mike Jones', birthday: 'January 6, 1981', hometown: 'Houston, TX', favoriteColor: 'blue' },
        { id: 3, name: 'Taylor Swift', birthday: 'December 13, 1989', hometown: 'Reading, PA', favoriteColor: 'red' }
    ];

    // GET /api/artists
    app.get('/api/artists', function(request, response){
        response.json(artists);
    });


    // GET /api/artist/:id
    app.get('/api/artist/:id', function(request, response){
        var id = request.params.id;
        var obj = artists[id - 1]; 
        response.json(obj);
    });

};

And lastly we will create an index.html file as a homepage…

<!DOCTYPE html>
<html>
<head>
    <title>App</title>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
</head>
<body>
        
    <h1>Node.js Example</h1>
	
	<p>A basic example showing an API in Node.js</p>
	
	<p>Go to <a href="/api/artists">/api/artists</a> to view a JSON response of all artists</p>
	
	<p>Go to <a href="/api/artist/1">/api/artist/1</a> or <a href="/api/artist/2">/api/artist/2</a> to view a JSON response of an individual artist</p>
	
</body>
</html>

Now to run the application you simply have to open a terminal /command window and type the following…

$ node server

You should see a message logged to the screen that the Express server is running on port 1337. Press Ctrl+C or Cmd+C to quit.

Debugging With Node Inspector

To debug our application with Node Inspector, instead of running our application with the “node” command as we did above we can run it with node-debug instead…

$ node-debug server

This will open up a tab in your browser. As mentioned previously it will look a lot like Google Chrome’s dev tools because it uses a lot of the same structure from dev tools. By default the tools should stop the execution of the code at the first statement of the application as is shown.

Debugging Node.js applications

You can see all of the files that are present in our application (as well as the modules we have installed on the left).

To set some breakpoints you can click on the line numbers in the code like as is shown in the following screenshot.Try placing a breakpoint inside one of the routes (the “/api/artists” route) on the response statement. Next in your browser navigate to the “/api/artists” route. If all goes well script execution should stop on that statement. From here you can hover over different objects such as the request and the response object and and examine the different properties on them.

Debugging Node.js applications

Obviously this is a simple example. But as your application gets more complex debugging can be a powerful tool to track down errors that occur in Node.js applications. You could even use the “step into” button to step through individual modules as they are used. Hopefully this simple guide has helped you get on your way.

Until next time, happy debugging!

]]>
https://9bitstudios.com/2015/10/debugging-node-js-applications-with-node-inspector/feed/ 0
Basic Authentication in Node.js Express Applications and APIs https://9bitstudios.com/2015/10/basic-authentication-in-node-js-express-applications-and-apis/ https://9bitstudios.com/2015/10/basic-authentication-in-node-js-express-applications-and-apis/#respond Thu, 15 Oct 2015 14:49:43 +0000 https://9bitstudios.com/?p=1077 In the past we have looked at basic access authentication using the Slim PHP framework. In the context of an HTTP transaction, basic access authentication is a method for an HTTP user agent to provide a user name and password when making a request. It is an easy way to secure different parts of your application by prompting the user to enter credentials before you serve up the response, be it a webpage of HTML or some XML or JSON at an API endpoint. It looks something like the following in browsers…

Basic Authentication

All you need to do is send WWW-Authenticate headers to get this prompt to appear. You can also specify a realm that allows you to have different “groupings” of authentication. If a user successfully enters the their credentials for one realm they will not have to re-enter their credentials for other pages or routes protected under basic authentication in the same realm. This will last for the duration of the user’s session. However, if he or she tries to access a route under a different realm he/she will have enter credentials again (which can be the same credentials or a different name/password combination). In this manner you can have different authentications for different places within your website or web application.

When the user enters credentials, these credentials are encoded with BASE64 encoding and sent to the server. They are not encrypted or hashed in any way. Thus, it would be pretty easy for an individual on the same network to view and decode these credentials (and then possibly use them for malevolent purposes). This is what is known as a man in the middle attack (MitM) and it is one of the common security vulnerabilities that developers need to be cognisant of. You could, of course, add an additional component to security such as sending an additional hash in a cookie that can be decoded on the server. However, in order for this to be effective both the server and the client need to have a private key that is known on both ends and is not sent over the wire. Getting this key from the server to the client requires an additional step of involvement for users. Thus, probably the most straightforward way of using basic authentication in a secure manner is to use TLS/SSL and have all requests between server and client be over https://.

Whatever you decide to do, basic authentication can be a decent solution for security if it is used properly.

So in what follows we will take a look and see how we can implement this in a Node.js application that uses Express.js as an application framework. Before looking at the following section, it might be a good idea to be familiar with Express.js by reading the introduction to Express and be familiar with Node.js as well. Another article entitled A Node.js Primer will help you with that. For a more in-depth look at Express.js, there is also an ongoing series of posts that discusses how to create an MVC Express.js Application that covers many different aspects of using Express.js.

Let’s take a look and see how we might implement this…

Setting Up

Like with a lot of things in Node.js working with Node.js we will first create a package.json file that will be used to install our dependencies for this exercise. So create a package.json file and in it place the following code…

{
    
    "name": "Node.js-API",
    "description": "An API in Node.js...",
    "version": "0.0.1",
    
    "repository": {
        "type": "",
         "url": ""
    },
    "dependencies": {

        "express": "4.4.4",
        "express-session": "1.5.1",
        "basic-auth": "1.0.3",
        "cookie-parser": "1.3.1",
        "body-parser": "1.4.3",
        "hbs": "3.1.0",
        "morgan": "1.1.1",
        "method-override": "2.0.2",
        "errorhandler": "1.1.1"
    }

}

As can be seen we in our dependency list we will be using the basic-auth module from npm

Now that we have our package.json file created, we should install everything by opening a shell and running…

$ npm install

This will download all of our modules and place them in a folder called “node_modules”

Next, create a file called server.js and in it place the following code…

var express = require('express');
var bodyParser = require('body-parser');
var cookieParser = require('cookie-parser');
var session = require('express-session');
var logger = require('morgan');
var methodOverride = require('method-override');
var errorHandler = require('errorhandler');
var http = require('http');
var path = require('path');
var app = express();
app.set('port', 8080);

app.set('view engine', 'html');
app.engine('html', require('hbs').__express);

/* Morgan - https://github.com/expressjs/morgan
 HTTP request logger middleware for node.js */
app.use(logger({ format: 'dev', immediate: true }));

/* cookie-parser - https://github.com/expressjs/cookie-parser
 Parse Cookie header and populate req.cookies with an object keyed by the cookie names. */
app.use(cookieParser('SECRETCOOKIEKEY123'));

/* body-parser - https://github.com/expressjs/body-parser 
Node.js body parsing middleware. */
app.use(bodyParser.json());
app.use(bodyParser.urlencoded({ extended: true }));

/* method-override - https://github.com/expressjs/method-override
 Lets you use HTTP verbs such as PUT or DELETE in places where the client doesn't support it. */		    
app.use(methodOverride());

app.use(express.static(path.join(__dirname, '')));

/* errorhandler - https://github.com/expressjs/errorhandler
 Show errors in development. */
app.use(errorHandler({ dumpExceptions: true, showStack: true }));

// send app to router
require('./router')(app);

http.createServer(app).listen(app.get('port'), function(){
  console.log('Express server listening on port ' + app.get('port'));
});

We will not go into too much depth on what each of these lines of code do. This file serves as the kickoff point for starting our Node.js Express web application. A lot of these modules are somewhat superfluous at this point but they will definitely prove to be useful later on if you wanted to get into more complex development with APIs so I have gone ahead and included them here. If you are interested in a more in-depth explanation surrounding what each of these lines of code do, be sure to take a look at the creating an MVC Express.js application discussions. Again, we will not be discussing what all of this code does in too much depth. Just know that this is code that will start up a server and run all of the code that will be needed for when HTTP requests are sent to and from some specific routes. We will look at these routes next.

So next create a file called router.js. For our example we will return JSON from the various routes that we set up, but all the same basic authentication implementations would apply if we were returning a webpage of HTML or data in XML format…

var Authentication = require('./utilities/Authentication');

// Routes
module.exports = function(app){ 
    // index.html
    app.get('/', function(request, response){
        response.render('index', {});
    }); 
    // API
    var artists = [
        { id: 1, name: 'Notorious BIG', birthday: 'May 21, 1972', hometown: 'Brooklyn, NY', favoriteColor: 'green' },
        { id: 2, name: 'Mike Jones', birthday: 'January 6, 1981', hometown: 'Houston, TX', favoriteColor: 'blue' },
        { id: 3, name: 'Taylor Swift', birthday: 'December 13, 1989', hometown: 'Reading, PA', favoriteColor: 'red' }
    ];

    // GET /api/artists
    app.get('/api/artists', function(request, response){
        response.json(artists);
    });


    // GET /api/artist/:id
    app.get('/api/artist/:id', Authentication.BasicAuthentication, function(request, response){
        var id = request.params.id;
        var obj = artists[id - 1]; 
        response.json(obj);
    });

};

Notice that for the get all artists route “/artists” this route is open and accessible to anyone, but each individual artist page “/api/artist/:id” with id being the int value of the artist ID, this runs a middleware function called “Authentication.BasicAuthentication.” Middleware in Node.js and Express.js is discussed in this entry about creating an Express.js application. There is also a pretty good exploration of middleware in the aforementioned Slim PHP Basic Authentication tutorial. Different language, same thing conceptually.

We included this middleware function with the statement var Authentication = require(‘./utilities/Authentication’); at the top of our router.js file. We still need to write the code for this functionality, so let’s do that next.

Writing Our Basic Authentication Function

Create a folder called “utilities” and create a file called “Authentication.js” it is here where we will add our basic authentication check …

var basicAuth = require('basic-auth');

exports.BasicAuthentication = function(request, response, next) {

    function unauthorized(response) {
        response.set('WWW-Authenticate', 'Basic realm=Authorization Required');
        return response.send(401);
    };

    var user = basicAuth(request);

    if (!user || !user.name || !user.pass) {
        return unauthorized(response);
    };

    if (user.name === 'foo' && user.pass === 'bar') {
        return next();
    } else {
        return unauthorized(response);
    };
	
};

So as we can see from the code above, we will protect a number of different routes with the name “foo” and the password “bar.” The realm we provided is just called “Authorization Required.” By setting the “www-authenticate” header we will prompt the user to enter credentials

And lastly we can create our index.html which will really only provide some links to the different routes. This index.html will be served up by our server at the home route (“/”)…

<!DOCTYPE html>
<html>
<head>
    <title>App</title>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
</head>
<body>
        
    <h1>Node.js Basic Authentication Example</h1>
    <p>A basic example showing basic authentication of an API in Node.js</p>
    <p>Anyone should be able to view <a href="/api/artists">/api/artists</a></p>
    <p>However, individual artist pages such as <a href="/api/artist/1">/api/artist/1</a> or <a href="/api/artist/2">/api/artist/2</a> are protected by basic authentication. Username is foo, password is bar</p>

</body>
</html>

So now we can test out how everything works. Open a command window and run the following…

$ node server

If we go to https://localhost:8080 we should see the content in our index.html file. We can check out the different routes by clicking on the various links. If all is well, we should see that for the get all artists route “/artists” this route is completely accessible with no authentication required, but each individual artist page “/api/artist/:id”, you will be prompted for credentials. So enter the name and password — name: foo, password: bar — to authenticate. Once you enter these credentials you will be able to access other single artist routes as well because you are now authenticated against this realm.

Setting Different Realms

What if we wanted to have a way to set different realms? How would we go about doing this? What we need to do in this instance is we need to write another middleware function that will run before our Authentication.BasicAuthentication middleware function. We then need to pass that custom realm forward into the next middleware function.

To accomplish this we are going to attach this information onto the request object itself. Because JavaScript is a dynamic language we can just extend objects all we want! We can add new properties, new methods, update values, or whatever else. So what we’re going to so is we’re going to create a new function in our “Authentication” module that will return a middleware function. What does this look like? Update our Authentication module with a new “SetRealm” function…

var basicAuth = require('basic-auth');

exports.BasicAuthentication = function(request, response, next) {

    function unauthorized(response) {
        response.set('WWW-Authenticate', 'Basic realm=' + request.authRealm);
        return response.send(401);
    };

    var user = basicAuth(request);

    if (!user || !user.name || !user.pass) {
        return unauthorized(response);
    };

    if (user.name === 'foo' && user.pass === 'bar') {
        return next();
    } else {
        return unauthorized(response);
    };
	
};

exports.SetRealm = function(realm) {
    return function(request, response, next){
        request.authRealm = realm || 'default';	
        return next();
    }
};

Notice that we are dynamically adding a property called authRealm to the request object. The return value of this SetRealm function is a function… a middleware function to be more specific as is identifiable to the call to next(). We are adding a property called authRealm to the request object and then calling next. Notice to that in our “BasicAuthentication” method above we are using this authRealm property to set the basic realm identifier.

Now we can update our router.js file to make use of this new implementation…

var Authentication = require('./utilities/Authentication');

// Routes
module.exports = function(app){ 
    // index.html
    app.get('/', function(request, response){
        response.render('index', {});
    }); 
    // API
    var artists = [
        { id: 1, name: 'Notorious BIG', birthday: 'May 21, 1972', hometown: 'Brooklyn, NY', favoriteColor: 'green' },
        { id: 2, name: 'Mike Jones', birthday: 'January 6, 1981', hometown: 'Houston, TX', favoriteColor: 'blue' },
        { id: 3, name: 'Taylor Swift', birthday: 'December 13, 1989', hometown: 'Reading, PA', favoriteColor: 'red' }
    ];

    // GET /api/artists
    app.get('/api/artists', function(request, response){
        response.json(artists);
    });


    // GET /api/artist/:id
    app.get('/api/artist/:id', Authentication.SetRealm('artist'), Authentication.BasicAuthentication, function(request, response){
        var id = request.params.id;
        var obj = artists[id - 1]; 
        response.json(obj);
    });

    app.get('/api/other', Authentication.SetRealm('other'), Authentication.BasicAuthentication, function(request, response){
        respose.json({ message: 'This is the other route '});
    });

};

Notice that we have added a new route “/api/other.” As we can see we are using our Authentication.SetRealm method and passing in the realm name. This method will return a middleware function that will run in this location. Now if we run our application again we can see that to authenticate against the “/api/artist/:id” routes we need to authenticate with our credentials. But if we try to hit the “/api/other” route we need to authenticate with our credentials again! This is because the realm is different. We can do lots of different types of layers and customizations to protect our web application or API. It can be a good solution for your needs in a lot of different circumstances.

That is basically all there is to implementing basic authentication with Node.js Express applications. You could of course take this and expand upon it with different realms and routes, but the essentials are all there. So feel free to download the demo files below and play around with it. Remember to run $ npm install before you do anything else. And as always, thanks for reading!

Demo Files
]]>
https://9bitstudios.com/2015/10/basic-authentication-in-node-js-express-applications-and-apis/feed/ 0
An Angular 2 Primer https://9bitstudios.com/2015/09/an-angular-2-primer/ https://9bitstudios.com/2015/09/an-angular-2-primer/#respond Tue, 08 Sep 2015 13:44:30 +0000 https://9bitstudios.com/?p=1069 Angular 2 is the much anticipated latest release of the Angular platform maintained by a team of engineers over at Google. The first iteration of Angular (which we may refer to as Angular 1 or 1.X at times) was and has been very well received within the JavaScript community. Many saw it as an improvement on smaller single-page application libraries like Backbone.js and Knockout.js because it essentially did “more” for you. You got a lot of functionality out of the box with the result being that you had to write less boilerplate code than you would with using a more basic library. Directives allow you to define custom attributes for any element that you want and Angular also boasts other great features such as native data-binding, an AMD like module loading system, and services using a solid promise implementation for asynchronous data transfer. All of this and more comes pre-packaged within Angular and is coupled with a great community behind it, an abundance of resources, as well as great support from the team over at Google. Because of all this, it is not too surprising that many companies and organizations have turned to it as a solution for building their web and mobile applications.

If there were a few points of criticism of Angular as a framework, it usually surrounded a slightly steeper learning curve when compared to other libraries, and the observation that perhaps there was a little “too much magic” going on under the hood without the developer really fully understanding what is happening 100% in all circumstances. This is always a double-edged sword with a framework that gives you a lot of functionality out of the box. On one hand, it is great to have a system where writing a relatively small amount of code will give you a lot of dynamic features and functionality with minimal effort. On the other hand, this sometimes requires that you follow a very defined and specific pattern in the way that you structure your code and if you ever want to do something that is perhaps a bit unorthodox from the accepted way, it might not be so easy and a framework that is a bit more rigid when it comes to custom implementations not always desired — especially when those hard-to-track-down bugs surface at inopportune times. Like with so many things, there will always be pros and cons to any technology you encounter.

Nonetheless, the reception and response to Angular 1 was/is overall very positive. It was often paired with Node.js development using the web application framework Express.js and the NoSQL database MongoDB to create what was known as the MEAN stack (MongoDB, Express, Angular, Node.js). Many readers may be familiar with this and other technology paring acronyms (such as LAMP: Linux, Apache, MySQL, and PHP or Python). When certain groupings of technologies complement each other well and play together nicely, it always makes for a better development experience all around.

Angular 2 Announcement and Pushback

In the latter part of 2014 Google announced that they were developing Angular 2. Usually these sorts of announcements are met with are met with a lot of excitement. After all, who wouldn’t like a shiny new version of something that you already like. However there was one overarching dark cloud the loomed over the Angular 2 announcement that was met with a lot of frustration within the web development community: Angular 2 would be essentially a rewrite of the codebase and drastically different enough from Angular 1.X such that there would be no foreseeable upgrade path to move from Angular 1.X to Angular 2. This meant that existing applications in Angular 1.X would essentially have to be rewritten. On top of this, it was not immediately clear how long Angular 1.X would continue to be supported with new releases and bug fixes.

Naturally, of course, some developers were upset by this. Only time will tell what the full impact of this decision and approach will be. Nonetheless, we move forward towards the future regardless of how much of the past comes along with it. That’s what we are aiming to do in the following discussions and tutorials.

NOTE: At the time of this writing it is still not entirely clear whether any of this will change and the Angular team will put an upgrade path in place. Also note, at the time of this writing in mid-2015, Angular 2 is still in “developer preview.” This means that many of the concepts and code samples presented in this book are subject to change. I will do my best to keep up to date on the latest changes as they roll out, but please note that there might be some sensitivity involved with functionality between different versions of Angular 2 and its surrounding tools. If you encounter anything in this regard, please do not hesitate to contact me via the above channels.

Introduction to Angular 2

Angular 2 incorporates many modern features of the latest iterations of JavaScript and tools within the JavaScript community being released circa halfway through the second decade of the 21st century (2010 – 2020). This includes many syntactical and functional features of ECMAScript 6 — the latest iteration of JavaScript up from ECMAScript 5, Node.js based dependency management with npm , TypeScript — the type checking JavaScript utility syntax that has been built and maintained by Microsoft, and a number of others. In short, the fingerprints of many of the newest emerging technologies within the web development world during this window of time are present on the Angular 2 framework. Similar to those that have come before, each release of Angular 2 will attempt to be a more malleable and useful option for developers looking to solve the common problems that they all face.

So let’s look all of these pieces that are essential for developing an Angular 2 application…

Node.js

Angular 2 uses Node.js and more specifically npm for installation of the various dependencies it requires. Having been first published by Ryan Dahl in 2009, Node.js — the open source software that allows the common web language of JavaScript to run outside the browser — has absolutely grabbed ahold of imaginations in the world of technology in its first half-decade of life. The explosion of Node.js applications and the exponentially increasing number of published modules of npm, the repository where Node.js modules are stored, are a huge indicator of its success as a platform.

So be sure head over to the Node.js website and install it for your OS. You will definitely be needing it as we go along.

ECMAScript 6

Angular 2 uses many implementations found in ECMAScript 6, or ES6 for short. It would be beneficial to take a brief look at some of the new features found in this latest version of JavaScript up from ES5. For example, ECMAScript 6 implements a more syntactical conceptualization of classes in JavaScript. While JavaScript classes are not and never have been classes in the strictest technical sense as they are in the traditional object-oriented languages Java, C++, and C#, many JavaScript applications can still be written in a way that incorporates a very class-like implementation using functions, constructors and prototypal inheritance. For example, you will often see something the following in a JavaScript application (ES5):

// ES5
function Animal() {
    this.color = 'brown';
    this.size = 'medium';
    this.age = 1;
}
Animal.prototype.sound = function() {
    console.log('Grunt');
};
Animal.prototype.move = function() {
    console.log('Running');
};

var beast = new Animal();

Inheritance can even be implemented in this approach…

function Dog() {
    Animal.call(this);
}
Dog.prototype = new Animal();
Dog.prototype.constructor = Dog

var fido = new Dog();
fido.color // brown;

By calling the Animal function and passing in the Dog function as the context, and new instance of a Dog will get all of the properties and methods found on Animal. We then do a little bit of additional cleanup with some of the prototype to make sure that the pointers are pointing at the right place.

This is all fine, but it seems a little bit convoluted. Fortunately for us, ES6 implements these same objects as follows using the “class” key word and the constructor function. What is shown below is exactly the same as the above.

// ES6 Class
class Animal {
 
    constructor(){
        this.color = 'brown';
        this.size = 'medium';
        this.age = 1;
    }
 
    sound() {
        console.log('Grunt');
    }
    move() {
        console.log('Running');
    }
}

We can implement inheritance using the “extends” keyword. We override some of the default properties that we found on Animal.

class Dog extends Animal {    
    constructor(color, size, age) {
        this.color = color;
        this.size = size;
        this.age = age;
    }
 
    sound() {
        console.log('Woof');
    }
}
 
var d = new Dog('Black', 'medium', 5);
console.log(d.size); // medium
d.sound(); // Woof
d.move(); // Running

We can even go further than this and extend the Dog class. The implementation below makes use of the “super” keyword to call the constructor of the parent object…

class Pomeranian extends Dog{    
    constructor(color, size, age) {
        super(color, size, age)
    }
 
    sound() {
        console.log('Yap');
    }
}
 
var p = new Pomeranian('Brown', 'small', 5);
p.sound(); // Yap
p.move(); // Running

Another component of ES6 that you will find prevalent in Angular 2 is module loading. Modules in ES6 solve the problem of scope and dependency management. In the past with ES5 a variable or function just declared in the open — whether in a script block in an HTML file or in an external .js file — like so….

function sayHi(name) {
    return "Hi, " + name;
}

would be considered to be bad practice because you were polluting the global object (which is often the window object in the context of the web). As the size and complexity of your application grew the maintainability of it would become a lot more difficult because you would have to worry about potentially overwriting other variables and functions later on in your application if you happened to name them the same or accidentally assign them a value that you did not intend to. Because of this, you often saw applications “namespace” the various methods and variables of an application to objects like so…

var app = app || {};
app.greeting = {
    sayHi: function(name) {
        return "Hi, " + name;
    }
}; 

to avoid polluting the global object.

With ES6 modules, however, all of this becomes unnecessary. You can declare functions and variables freely and the scope is always local to that file unless explicitly specified as a global object. This makes managing scope and maintaining your application a lot easier.

If you have ever done any development with Node.js, you should be somewhat familiar with modules as it follows a particular form and structure known as the CommonJS module loading syntax. Basically the idea is that you can import various functions and methods from other JavaScript files into your own JavaScript file by using the “import” keyword. You reference the path to the file you are loading as a module from the location of the file you are importing your module(s) into. So let’s say in your project you had a file called “greeting.js” that lived in a folder named “lib” with the following code in it

export function sayHi(name) {
    return "Hi, " + name;
}
export function sayHello(name) {
    return "Hello, " + name;
}
export function sayHey(name) {
    return "Hey, " + name;
}

The “exports” keyword means that these functions are exported and can be imported into other JavaScript files. For example, in the root of your project (one level up from the “lib” directory) let’s say you had a file called main.js. In that file you could do the following…

import * as greet from 'lib/greeting';

console.log(greet.sayHi('Joe')); // "Hi, Joe"
console.log(greet.sayHello('Sally')); // "Hello, Sally"

Here we are importing all of the exported functions in the greeting.js file into a variable called “greet” using the * wildcard locally to our main.js file. If there were any other exported functions or properties in our greeting.js file, this would be available in main.js as well.

There are other syntaxes that can be utilized in module importing. For example, if we only wanted the sayHi and sayHello methods imported from our greeting.js file (and we did not want or need the sayHey method for some reason) we could do the following in main.js…

import { sayHi, sayHello } from 'lib/greeting';

console.log(sayHi('Joe')); // "Hi, Joe"
console.log(sayHello('Sally')); // "Hello, Sally"

There are other variations on the importing syntax and implementation as well that we might see as we go along. The main point is that this gives you a lot of flexibility in how you structure your application. Doing all of this is not too dissimilar from the importing that you would so in Java…

import com.domain.package

or C#

using System.Net;

The difference being that in JavaScript you import from the path to the file and in Java and C# the packages are compiled into memory and imported from there. But in all cases the approach serves the same purpose.

This is just a brief look at a couple of the newer features found in ES6. There are many other parts of ES6 that will be incorporated into Angular 2 we will discuss these as we go along.

TypeScript (Optional)

As mentioned earlier, Angular 2 is intimately connected with TypeScript. Though it is not required that you write in TypeScript to build your Angular 2 application, you certainly have the option to utilize it and much of the Angular 2 core code incorporates TypeScript for a greater level of validation of a lot of the values that make up the library. TypeScript offers up the following description of itself on its homepage

TypeScript lets you write JavaScript the way you really want to. TypeScript is a typed superset of JavaScript that compiles to plain JavaScript. Any browser. Any host. Any OS. Open Source.

That doesn’t sound too bad. The basic premise of TypeScript is that it offers an extension of syntax to regular JavaScript that offers a compile-time like checking of JavaScript types within your application. JavaScript, as you likely well know, is a weakly-typed language meaning that variables of one type can be assigned to a value another type (or sometimes automatically converted) with no error or warning being thrown. Thus in a weakly-typed language like JavaScript it is perfectly ok to do something like this…

var num = 1;  
console.log(typeof num);// number
num = "one";
console.log(typeof num); // string

where we just throw a string into our variable that *was* a number. Or, sometimes, we can even mix different types where an automatic conversion takes place…

var num = 1; 
num = num + 2 + " is the magic number"; 
console.log(num); // "3 is the magic number"
console.log(typeof num); // string

Whereas, if you were using a strongly-typed language like Java or C#, the following would not be allowed because the compiler would complain…

int num  = 1;
num = "one"; // error

In strongly-typed languages with variables being declared as certain types we cannot change the type of value that we assign to them. In JavaScript, however, we can. While this offers some flexibility within the language, it can also be the source for many bugs. TypeScript attempts to bring together the strengths of both strongly and weakly typed languages by letting you keep the flexibility of writing JavaScript as you like, but also allowing you to specify when you do not want the types of certain variables or parameters to change. Thus if we had something like this in vanilla JavaScript…

function greeter(person) {
    return "Hello, " + person;
}

var user = [0, 1, 2];
console.log( greeter(user) ); // Hello, 0,1,2

As we can see here user is an array and is of type “object.” JavaScript doesn’t care and just converts it to the string of all the values in the array “0,1,2”. If we accidentally did this and did not have good validation of data integrity, this could potentially be the source of a number of different unexpected bugs.

In TypeScript we could do the following where we always want to ensure the parameter of our function always received a string…

function greeter(person: string) {
    return "Hello, " + person;
}

var user = [0, 1, 2];
console.log( greeter(user) ); 

Notice the extra “: string” on our function parameter? If we were to run the TypeScript compiler with this code in our application we would get the following…

greeter.ts(7,26): Supplied parameters do not match any signature of call target

TypeScript does the type checking for us. Awesome! That, in a nutshell, is the 2 minute overview of what TypeScript is. We will not explicitly devote time to doing a Typescript tutorial because we will essentially learn enough of it as we go along in the context of Angular 2 — which is what is most important. If you do want a deeper background/understanding of what TypeScript is and why it is useful, you can take a look at the tutorials on the TypeScript website.

Now that you have Node.js installed, you will want to be sure that you have TypeScript installed as well (which you can install via npm). Be sure to sure to install globally with the -g flag.

$ npm install -g typescript

Now that we have briefly looked at some of the bare essentials to get up and running with Angular 2, we will now look at some of the steps involved with creating an application!

Getting Started with Angular 2

The first thing we will want to do to get up and going with creating an app in Angular 2 is to set up an http-server. If you have a local Apache or IIS setup you may wish to use this by putting your Angular 2 files in a directory created inside the www folder. Another quick easy implementation is to just pull down the Node.js http-server module…

$ npm install -g http-server

From there you can create a directory anywhere you like and run the following…

$ http-server

This will run an HTTP server at localhost:8080. If you got to https://localhost:8080 you should see something there that tells you a server is running. We have not created an index.html yet so as of right now some default content is just being served up. We will do that in what follows. It is worth looking at how to build an Angular 2 application in both native JavaScript and TypeScript just so you can get a feel for each and get a sense of which you prefer. We will start with native JavaScript.

JavaScript

We mentioned earlier that Angular 2 will use a lot of ES6 features. This will continue to be more and more prevalent as the library grows and matures, but currently, at the time of this writing in mid-2015, a lot of browsers do not support a number of the features found in ES6. Support is being added gradually but Angular 2 is still probably going to need to have a way to run in “older-ish” browsers. Thus, you can still write Angular 2 apps in JavaScript version ECMAScript 5. We will do this in what follows and it is probably easier to start here because there is less setup and tooling involved.

So create an index.html file and put the following markup…

<!DOCTYPE html>
<html>
<head>
    <script src="https://code.angularjs.org/2.0.0-alpha.26/angular2.sfx.dev.js"></script>
    <script src="main.js"></script>
</head>
<body>
    <my-app></my-app>
</body>
</html>

This will serve as the basis of our application. We are loading the dev version of Angular 2 from the repository at code.angularjs.org. In a production application we would want to pull this down and load it locally. But for now this will do fine.

Next, create a main.js file in the same directory as our index.html file…

function AppComponent() {}
AppComponent.annotations = [
    new angular.ComponentAnnotation({
        selector: 'my-app'
    }),
    new angular.ViewAnnotation({
      template: '<h1>My first Angular 2 App</h1>'
    })
];
document.addEventListener('DOMContentLoaded', function() {
    angular.bootstrap(AppComponent);
});

Now go to https://localhost:8080 and refresh. You should see the text “My first Angular 2 App” displayed. Congratulations, you have just created your first application with Angular 2!

We will get into what the pieces of our application handle in more detail in later tutorials. The basic premise of it is that Angular 2 has this concept of “components” which consist of 1) a piece of logic and 2) a view that defines the display of that logic. Components are somewhat analogous to what directives were in Angular 1.X. These components interact with services, another building block in Angular 2 that are responsible for data transfer; fetching and sending data to and from a server or other data source. Again, this “services” terminology is probably familiar to those readers who did some development in Angular 1.X — though “services” is a bit more universal in what it refers to in the web development world. At the most basic level we can see that our component defines a selector where we want to insert our data (the my-app element) and a template to render our data out. In this case it is static markup (an <h1> element), but this will become much more involved and dynamic as we build our application out and use services to move data in and out of our components.

So as we can see, we can use native ES6 JavaScript to build an Angular 2 app, but let’s see if we can use some TypeScript and some of the more novel features that we will find surrounding Angular 2.

TypeScript

Let’s create the same app using TypeScript. You should already have TypeScript installed via Node.js from earlier on but just in case you have not, you can do that now. Be sure to sure to install globally with the -g flag.

$ npm install -g typescript

There is one additional piece that we need to make our TypeScript stack complete. This is what is known as a “TypeScript definition.” What is this? Basically a TypeScript definition is the information that TypeScript needs to do the compile-time checking of types for common JavaScript libraries that are not written in TypeScript. For example, if you were using jQuery in your code and wanted to use, say, the fadeOut method somewhere in your application, how would TypeScript know that this method is expecting a string specifying the duration as the first parameter and a function as the callback as the second? The fadeOut method is defined in the core jQuery library which is not written in TypeScript. The answer is adding a reference to a TypeScript definition file which does tell TypeScript what to look for when someone uses something from the jQuery library in his/her code. There are whole repositories out there that consist of collections of TypeScript definition files for common JavaScript libraries that you can freely use if you want to write your application in TypeScript.

To implement TypeScript definitions we will need to install the TypeScript definition module tsd from npm…

$ npm install -g tsd

You then need to install the type script definitons onto your system using “tsd install.” Angular 2 you’ll want to have the d.ts files (TypeScript definition files use the format: filename.d.ts) for the following libraries. So run the following after installing the tsd module…

$ tsd install angular2 es6-promise rx rx-lite

This will pull down the .d.ts files and place them in a directory called “typings.” Angular 2 is the important one for now, but we will also definitely need the others later on so we might as well install them now.

The way that you import a TypeScript definition file in your own TypeScript file is by using the following syntax. You can add something like this at the beginning of your .ts files…

/// <reference path="../typings/angular2/angular2.d.ts" />

We are now all setup to start writing and compiling TypeScript. Sweet!

So similar to what we did before create an empty index.html file in the same directory as we have our “Typings” folder. In this index.html file add the following code…

<!DOCTYPE html>
<html>
<head>
    <script src="https://github.jspm.io/jmcriffey/bower-traceur-runtime@0.0.87/traceur-runtime.js"></script>
    <script src="https://jspm.io/system@0.16.js"></script>
    <script src="https://code.angularjs.org/2.0.0-alpha.26/angular2.dev.js"></script>
</head>
<body>
    <my-app></my-app>
    <script>
        System.import('main');
    </script>
</body>
</html>

The TypeScript setup includes SystemJS, a third-party open-source library that adds ES6 module loading functionality to browsers. Obviously this functionality is not present in the ES5 implementation. The above uses some slightly different synax to incorporate System.js. System.js will look for a file named “main.js” which we will create next by compiling a main.ts file to (remember that .ts is the extension of a TypeScript file) to main.js. So, in the same directory create a file called main.ts…

/// <reference path="../typings/angular2/angular2.d.ts" />
import {Component, View, bootstrap} from 'angular2/angular2';

@Component({
    selector: 'my-app'
})
@View({
    template: '<h1>My first Angular 2 App</h1>'
})

class AppComponent {

}
bootstrap(AppComponent);

Notice that we have the reference to the TypeScript definition for Angular 2. We then load our component and view similar to what we did before but also using a slightly different syntax.

Now we have to compile our main.ts file to a main.js file that can be used by our application. We do this by running the TypeScript compiler. In the same directory open up a terminal and type the following…

$ tsc --watch -m commonjs -t es5 --emitDecoratorMetadata main.ts

This sets up a “watch” such that whenever our main.ts file changes it will compile a main.js. Because this does not exist yet, the main.ts file will be compiled to main.js. The following main.js file is generated by the compiler…

/// <reference path="../typings/angular2/angular2.d.ts" />
var __decorate = (this && this.__decorate) || function (decorators, target, key, desc) {
    if (typeof Reflect === "object" && typeof Reflect.decorate === "function") return Reflect.decorate(decorators, target, key, desc);
    switch (arguments.length) {
        case 2: return decorators.reduceRight(function(o, d) { return (d && d(o)) || o; }, target);
        case 3: return decorators.reduceRight(function(o, d) { return (d && d(target, key)), void 0; }, void 0);
        case 4: return decorators.reduceRight(function(o, d) { return (d && d(target, key, o)) || o; }, desc);
    }
};
var __metadata = (this && this.__metadata) || function (k, v) {
    if (typeof Reflect === "object" && typeof Reflect.metadata === "function") return Reflect.metadata(k, v);
};
var angular2_1 = require('angular2/angular2');
var AppComponent = (function () {
    function AppComponent() {
    }
    AppComponent = __decorate([
        angular2_1.Component({
            selector: 'my-app'
        }),
        angular2_1.View({
            template: '<h1>My first Angular 2 App</h1>'
        }), 
        __metadata('design:paramtypes', [])
    ], AppComponent);
    return AppComponent;
})();
angular2_1.bootstrap(AppComponent);

Ew, that is a little bit messy. But oh well. If we are writing in the clean simpler syntax of TypeScript, we will not need to concern ourselves with what the generated code looks like too much.

Note: I encountered some weirdness with TypeScript on Windows machines with VisualStudio 2013 or 2015 installed, both of which come with TypeScript. There seems to be some sort of conflict when typing to run the command line to the Node.js version of the TypeScript compiler. I got an error in this scenario. You might need to run the following instead with the “.cmd” file extension.

$ tsc.cmd --watch -m commonjs -t es5 --emitDecoratorMetadata main.ts

I ran the TypeScript compiler on my Ubuntu 14.X virtual machine without issue.

Now as before, if we run

$ http-server

in the directory with our index.html file and open up https://localhost:8080 we should see the exact same text as we did before. We have just completed our first Angular 2 app only this time in TypeScript! Not too shabby!

Summary

Now that we have examined some of the dependencies and implementations that will be found in the current and future releases Angular 2, we have a good basis for building upon this knowledge and adding greater layers of complexity. We have also seen that Angular 2 is flexible enough to give you the option to write your application in either native JavaScript or TypeScript and it is very possible that other JavaScript libraries will be incorporated into the ecosystem as well. In upcoming discussions, we will take a closer look at the ins and outs of the core building blocks we can use to build applications in Angular 2.

]]>
https://9bitstudios.com/2015/09/an-angular-2-primer/feed/ 0
Creating an MVC Express.js Application (Part 4): Relational Data in MongoDB https://9bitstudios.com/2015/08/creating-an-mvc-express-js-application-part-4/ https://9bitstudios.com/2015/08/creating-an-mvc-express-js-application-part-4/#respond Tue, 04 Aug 2015 18:16:23 +0000 https://9bitstudios.com/?p=1045 In this section we will look at another interesting aspect of creating a web application using Node.js, Express, and MongoDB: referencing other data in the database. MongoDB is part of the NoSQL class of databases (as opposed to the traditional relational databases that have been so prevalent for so long). NoSQL databases store records as documents as opposed to relational databases which store records as rows in tables. Documents in NoSQL databases are basically collections of key value pairs sort of like JSON objects. As the MongoDB documentation describes in the introduction

A record in MongoDB is a document, which is a data structure composed of field and value pairs. MongoDB documents are similar to JSON objects. The values of fields may include other documents, arrays, and arrays of documents.

You can find many articles out on the web discussing the difference between NoSQL databases and relational databases. MongoDB is a solution to a common problem and like with many things it has its advantages and its drawbacks.

But even with their structure, NoSQL database documents still have need to store references to other objects within them (somewhat like foreign keys). We have been creating data models of books in previous examples in this tutorial that have a “title” field, an “author” field, and an “isPublished” field. We have been storing the author as a string value. But really in a real-world application we’d more likely want to store a reference to an author that exists in an authors collection elsewhere. That way we could store additional information about an author or show a collection of books written by the same author. When you start relating and connecting data in this manner your application becomes truly dynamic and useful

Setup

So let’s create an “AuthorModel” and all of the scaffolding to put an “authors” section in the database. Like we’ve done before, we’ll want to follow the same process: define our model schema for our “AuthorModel,” add routes, add controllers, and add views. We will move fairly quickly through this. A lot of what we are doing was covered earlier in this tutorial. If there are any parts that seem unclear, please go back and review the content presented earlier to get a refresher on how this application is being structured.

So let’s start by defining our author schema in our Models.js file. This one will be a bit simpler than our book model schema. All we need to add here is a name. What will be important later on is the author _id value that we can associate with a book as a reference field…

var Author = new mongoose.Schema({
    name: String
});


var BookModel = mongoose.model('Book', Book);
var UserModel = mongoose.model('User', User);
var AuthorModel = mongoose.model('Author', Author);

module.exports = {
    BookModel: BookModel,
    AuthorModel: AuthorModel,
    UserModel: UserModel
};

And let’s continue with adding our author routes to the router.js file making sure to add a refenrece to our soon-to-be-created AuthorsController…

var HomeController = require('./controllers/HomeController');
var BookController = require('./controllers/BookController');
var AuthorController = require('./controllers/AuthorController');

// Routes
module.exports = function(app){
    
    // Main Routes
    
    app.get('/', HomeController.Index);
    app.get('/other', HomeController.Other);   

    // Book Routes
    
    app.get('/books', BookController.Index);
    app.get('/books/add', BookController.BookAdd); 
    app.post('/books/add', BookController.BookCreate); 
    app.get('/books/edit/:id', BookController.BookEdit);
    app.post('/books/edit', BookController.BookUpdate); 
    app.get('/books/delete/:id', BookController.BookDelete);     

    // Author Routes
    
    app.get('/authors', AuthorController.Index);
    app.get('/authors/add', AuthorController.AuthorAdd); 
    app.post('/authors/add', AuthorController.AuthorCreate); 
    app.get('/authors/edit/:id', AuthorController.AuthorEdit);
    app.post('/authors/edit', AuthorController.AuthorUpdate); 
    app.get('/authors/delete/:id', AuthorController.AuthorDelete);  

}; 

Now we can add the respective controllers by creating an AuthorsController. This will look very similar to our BooksController because we are largely needing all the same types of actions (Create, Read, Update, and Delete) as we did with our BookController. The only difference is that in this case we’ll be using our author Models instead of our book models…

var Model = require('../models/Models');
var Validation = require('../utilities/Validation');

exports.Index = function(request, response){

    Model.AuthorModel.find(function(error, result){
        if (error) {
            console.log('Error');
            Validation.ErrorRedirect(response, '/', 'There was an error finding authors in the database');
        } else {
            response.pageInfo.title = 'Authors';
            response.pageInfo.authors = result;
            response.render('authors/Index', response.pageInfo);
        }
    });

};

exports.AuthorAdd = function(request, response){
    response.pageInfo.title = 'Add an Author';
    response.render('authors/AuthorAdd', response.pageInfo);
};

exports.AuthorCreate = function(request, response){ 

    var name = request.body.name;

    if(Validation.IsNullOrEmpty([name])) {
        Validation.ErrorRedirect(response, '/authors', 'Please fill out all fields');
    } else {

        var a = new Model.AuthorModel({ 
            name: name
        });

        a.save(function(error){
            if(error) {
                console.log('Error');
                Validation.ErrorRedirect(response, '/authors', 'There was an error adding the author to the database');
            } else {
                Validation.SuccessRedirect(response, '/authors', 'Author created successfully');
            }
        });
    }
};

exports.AuthorEdit = function(request, response){
    var id = request.params.id;
    
    Model.AuthorModel.findOne({ _id: id }, function(error, result){
        if(error) {
            console.log('Error');
            Validation.ErrorRedirect(response, '/authors', 'There was an error finding an author in the database with this id');
        }
	else {
            if(result) {
                response.pageInfo.title = 'Edit Author';
                response.pageInfo.author = result;
                response.render('authors/AuthorEdit', response.pageInfo);
            } else {
                Validation.ErrorRedirect(response, '/authors', 'There was an error finding an author in the database with this id');
            }
        }
	
    });
}

exports.AuthorUpdate = function(request, response){ 

    var name = request.body.name;

    if(Validation.IsNullOrEmpty([name])) {
        Validation.ErrorRedirect(response, '/authors', 'Please fill out all fields');
    } else {
    
        Model.AuthorModel.update(
            { _id: request.body.id }, 
            {
                name: name
            },
            { multi: true }, 
            function(error, result){
                if(error) {
                    console.log('Error')
                    Validation.ErrorRedirect(response, '/authors', 'There was an error finding an author in the database with this id');
                } else {
                    Validation.SuccessRedirect(response, '/authors', 'Author updated successfully');
                }        
            }
        );
    }
}

exports.Authorelete = function(request, response){ 
    var id = request.params.id;
    Model.AuthorModel.remove({ _id: id }, function(error, result) {
        if(error) {
            console.log('Error');
            Validation.ErrorRedirect(response, '/authors', 'There was an error deleting the author');
        } else {
            Validation.SuccessRedirect(response, '/authors', 'Author deleted successfully');
        }
    });
}

And lastly let’s create our views. Create a new folder in the main directory and call it “authors”. In this folder we can create the Index.handlebars, AuthorAdd.handlebars and AuthorEdit.handlebars views.

Index.handlebars

<ul>
{{#authors}}
    <li>
        <strong>{{name}}</strong> - <a href="/authors/edit/{{ _id }}">Edit</a> <a href="/auhors/delete/{{ _id }}" onclick="return confirm('Are you sure?')">Delete</a>
    </li>

{{ else }}
    <p>There are no authors.</p>

{{/authors}}
</ul>

<a href="/authors/add">Add Author</a>

AuthorAdd.handlebars

<form method="post" action="/authors/add">
    <label>Name</label> <input name="name" type="text" />
    <input type="submit" value="Submit" />
</form>

AuthorEdit.handlebars

<form method="post" action="/authors/edit">
    <input name="id" type="hidden" value="{{ author._id }}" />
    <label>Name</label> <input name="name" type="text" value="{{ author.name }}" />
</form>

This is one of the advantages to building with the model-view-controller design pattern. We are able to quickly add functionality to entirely new data types and all the scaffolding we need to add entries to the database simply by creating a few new files of similar type to others.

Now if we run our application using…

$ node app

we can go to the “/authors” routes and from there add some new authors to the database. These authors are not associated with any books yet, but we’ll change that shortly.

Adding Object References

Now that we have our authors in the db, the next thing we’ll want to do is update our book model schema in our Models.js file to reference an author field since a book object will be associated with an author. As described in the Mongoose documentation here, we can create references to other documents in our schemas. So we can do this like so. Before, our “BookModel” looked like this…

var Book = new mongoose.Schema({
    title: String,
    author: String,
    isPublished: Boolean
});

var Author = new mongoose.Schema({
    name: String
});

with our author stored as a string. We can update this to the following…

var Book = new mongoose.Schema({
    title: String,
    author: { type: mongoose.Schema.Types.ObjectId, ref: 'Author' },
    isPublished: Boolean
});

var Author = new mongoose.Schema({
    name: String
});

So now we have an author as a reference to an author than will be associated with each book.

Of course, now that we have updated our model, we’ll need to update the manner in which we handle things in our controllers because there is a little bit more involved in displaying a book in our views. We are going to have to look up the associated author _id value that exists on the book and pass it into the view along with the other regular book data. It might help to conceptualize things if you delete all of your existing books in the database and start afresh.

As always, we’ll start off small and we’ll work our way up. We’ll start out by working on the controllers and views to add some books with associated authors. Mongoose provides us a method of using promises as a way of retrieving data asynchronously through the exec method (which returns a promise). We can then chain the various function calls together using the then method and they will execute in their proper order. This will become increasingly important as our objects and our associations become more complex. So for our controller to add a book we need to first get all authors, then return the view.

exports.BookAdd = function(request, response){
    Model.AuthorModel.find({}).exec(function(error, result){

        if(error) {
            Validation.ErrorRedirect(response, '/books', 'There was an error getting the author list');
        } else {
            response.pageInfo.authors = result;
        }
    }).then(function(){

        response.pageInfo.title = 'Add a Book';
        response.render('books/BookAdd', response.pageInfo);
    });
};

When we pass in the empty object { } into the exec function Mongoose interprets this to mean “find all” in this case: find all authors.
So we’ve added the authors object to the pageInfo response. So let’s now go and update the view to add a book. We’ll use a <select> box to display a dropdown of a list of authors…

<form method="post" action="/books/add">
    <label>Title</label> <input name="title" type="text" />
    <label>Author</label>

    <select name="author" class="">
	{{#authors}}
	    <option value="{{_id}}">{{name}}</option>
	{{/authors}}
    </select>

    <label>Is Published?</label> <input name="published" type="checkbox" value="published" />
    <input type="submit" value="Submit" />
</form>

If you start the app up and go to the “books/add” route, you should see some of your authors populated in the dropdown. So what we send up to the server when we post the form back is no longer an author string, but rather an author “_id” value. Because we updated our BookModel

Of course, once we create a new book with our new schema we see that once we are redirected back to the “/books” route on successful adding of a book we no longer see our author name but rather our internal ugly MongoDB _id value. So let’s change our home view to show the author rather than this ugly id.

So like with our controller to add a book, we’ll need to get the author of each book so that we can display that author’s name. It wouldn’t seem very efficient to pull down all the authors and then compare the authors in the list for each book. Fortunately, Mongoose gives us a method that will allow us to populate the books we are getting back from the database with the object reference using the populate method. Thus, we’d want to update our Index controller in our BookController.js file to look like the following…

exports.Index = function(request, response){

    Model.BookModel.find({}).populate('author').exec(function(error, result){
        if (error) {
            console.log('Error');
            Validation.ErrorRedirect(response, '/', 'There was an error finding books in the database');
        } else {
            response.pageInfo.title = 'Books';
            response.pageInfo.books = result;
            response.render('books/Index', response.pageInfo);
        }
    });
};

See how we have used the populate method to populate the author field for each book on our book model with the author object. As a result, in our view we have direct access to this author object.

<ul>
{{#books}}
    <li>
        <strong>{{title}}</strong> by: {{ author.name }} - <a href="/books/edit/{{ _id }}">Edit</a> <a href="/books/delete/{{ _id }}" onclick="return confirm('Are you sure?')">Delete</a>
    </li>

{{ else }}
    <p>There are no books.</p>

{{/books}}
</ul>

<a href="/books/add">Add Book</a>

See how we can just access the author name via {{ author.name }} in our Index.handlebars view? Mongoose makes it nice and easy to do this. Nice and easy is always good!

Editing Items and Handlebars Helpers

We will use some of the same Mongoose concepts of getting the author object reference for our edit view for books as well. What is interesting about the edit view is that we also need to find *all* the authors as well so that we can populate the dropdown. We can’t just return the current one associated with the book because maybe the user of the site would want to update the author by choosing a different author in the dropdown. So here is what this would look like in our controller…

exports.BookEdit = function(request, response){
    var id = request.params.id;
    
    Model.BookModel.findOne({ _id: id }).populate('author').exec(function(error, result){
        if(error) {
            console.log('Error');
            Validation.ErrorRedirect(response, '/books', 'There was an error finding a book in the database with this id');
        }
        else {
            if(result) {

                response.pageInfo.book = result;

                Model.AuthorModel.find({}).exec(function(error, result){

                    if(error) {
                        Validation.ErrorRedirect(response, '/books', 'There was an error getting the author list');
                    } else {
                        response.pageInfo.title = 'Edit Book';
                        response.pageInfo.authors = result
                        response.render('books/BookEdit', response.pageInfo);
                    }
                });

            } else {
                Validation.ErrorRedirect(response, '/books', 'There was an error finding a book in the database with this id');
            }
        }
    });
}

Notice how we first find our book where we look up the record in the database using the id parameter as we have been doing before. But after this we then make a call to get all authors using the Model.AuthorModel.find({}).exec() method so that we can populate the dropdown. So in our view we can make some small adjustments to display everything that we need to…

<form method="post" action="/books/edit">
    <input name="id" type="hidden" value="{{ book._id }}" />
    <label>Title</label> <input name="title" type="text" value="{{ book.title }}" />

    <select name="author" class="">
	{{#authors}}
	    <option value="{{_id}}">{{name}}</option>
	{{/authors}}
    </select>

    <label>isPublished?</label> <input name="published" type="checkbox" value="published" {{#if book.isPublished}}checked{{/if}} />
    <input type="submit" value="Submit" />
</form>

There is, however a slight problem with our edit view in its current state. You’ll notice that if we have multiple authors to choose from in our dropdown we may not have the correct author selected. By default, the first author is always selected in the dropdown (as it was in our create view). But unless the current book we are editing happens to be by the first author in the list, it will not be correct.

How do we solve this? We’ll need to have some way of adding a “selected” attribute to the correct <option> value by comparing the current book’s author _id to the _id value in the <select> dropdown. How to do this? Because our controller does not know anything about the format of the view, as it turns out, we will need to do this comparison in the view itself.

To do this we will need to create a helper method within the handlebars templating engine to select the correct value. You can find more information on how helpers work in Handlebars on the Handlebars.js website. More important for our purposes is info on how to register helpers using the express-handlebars module which can be found here on npm. Following the format of registering the helper there, we will go to our app.js file and create a Handlebars helper called “ifCond” You will see in a moment why this is going to be useful. So in our app.js file update the section where we register handlebars as the view template to the following…

/* express-handlebars - https://github.com/ericf/express-handlebars
A Handlebars view engine for Express. */
hbs = handlebars.create({
   helpers:{
       ifCond: function(v1, operator, v2, options){
           
          v1 = v1.toString(); 
          v2 = v2.toString();  
          
          switch (operator) {
            case '==':
                return (v1 == v2) ? options.fn(this) : options.inverse(this);
            case '===':
                return (v1 === v2) ? options.fn(this) : options.inverse(this);
            case '<':
                return (v1 < v2) ? options.fn(this) : options.inverse(this);
            case '<=':
                return (v1 <= v2) ? options.fn(this) : options.inverse(this);
            case '>':
                return (v1 > v2) ? options.fn(this) : options.inverse(this);
            case '>=':
                return (v1 >= v2) ? options.fn(this) : options.inverse(this);
            case '&&':
                return (v1 && v2) ? options.fn(this) : options.inverse(this);
            case '||':
                return (v1 || v2) ? options.fn(this) : options.inverse(this);
            default:
                return options.inverse(this);
           }
       }
   },
   defaultLayout: 'main'
});

app.engine('handlebars', hbs.engine);
app.set('view engine', 'handlebars');

What this method will do is take in 2 values and compare them as strings within our view engine. So we can now update our BookEdit view to the following…

<form method="post" action="/books/edit">
    <input name="id" type="hidden" value="{{ book._id }}" />
    <label>Title</label> <input name="title" type="text" value="{{ book.title }}" />

    <select name="author" class="tw-admin-post-author">
	{{#authors}}
	    <option value="{{_id}}"{{#ifCond _id '==' ../book.author._id}}selected{{/ifCond}}>{{name}}</option>
	{{/authors}}
    </select>

    <label>isPublished?</label> <input name="published" type="checkbox" value="published" {{#if book.isPublished}}checked{{/if}} />
    <input type="submit" value="Submit" />
</form>

Note the use of the “ifCond” inline in the option values. Because we are doing this in the {{#authors}} block, the context is the list of authors so the _id is the value of each author id within the list. However, we need to compare this to the author _id of the current book we are editing. To get the _id value of the book object we are editing we need to switch the context using the “../” syntax. Handlebars uses this to go “one context up” to the book object where we can get the author _id value of the current book. So what this “ifCond” condition is doing for each <option> is checking to see if the author _id set in value attribute in the current option is equal to the book author _id of the book we are edting. If it is, we should set the <option> value where this is a match to be selected by adding the “selected” attribute.

Now if we rerun our application and go to edit a book, we should see the correct author selected in the dropdown. Pretty neat!

Conclusion

We are really coming along in our application development. We have relational data between different data types and we’re creating the appropriate views where they are applicable. We could easily build upon this to create all kinds of different relationships and associations between data to make our application truly dynamic. All you really need to do is repeat the processes discussed above for different objects and types.

Download the files below to play around with relational data in an Express.js application. As always, don’t forget to run

$ npm install

to install the dependency modules.

Download Files
]]>
https://9bitstudios.com/2015/08/creating-an-mvc-express-js-application-part-4/feed/ 0
Creating an MVC Express.js Application (Part 3): Data Access & Validation With MongoDB https://9bitstudios.com/2015/07/creating-an-mvc-express-js-application-part-3/ https://9bitstudios.com/2015/07/creating-an-mvc-express-js-application-part-3/#respond Mon, 13 Jul 2015 12:52:34 +0000 https://9bitstudios.com/?p=1038 In previous installments we looked at getting started with creating an Express.js MVC application, creating controllers and views. And then we looked at middleware and creating a config file to store application constants.

Now we will look at something that truly makes an Express.js application dynamic (and fun): data-access… which essentially boils down to the use of a database to store, retrieve, and manipulate information.

Like many things in technology, people will always argue about what is the “best” way to do something and what the best technologies to use for doing that something are. And the way in which an application should store data is not going to be excluded from this discussion (read: Internet flame-war). It is not really part of our purposes to argue what is “best” or “better” when it comes to data-access, but it is probably worth pointing out that a lot of the Express.js and Node.js communities seem to have embraced NoSQL databases such as MongoDB, and CouchDB. There is even a full “stack” you will hear mentioned known as the MEAN stack (MongoDB, Express, AngularJS, and Node.js) — just like you’d hear of a LAMP stack (Linux, Apache, MySQL, and PHP). The inclusion of MongoDB in this shows its prominence in developer preference in Express and Node applications.

So, it is probably worth knowing a bit about how to use a MongoDB database in a Node.js and Express.js application because you are more than likely to come across it at some point in your life as a developer. So, resultantly, we’ll utilize MongoDB in our application.

Installing MongoDB

Head on over to MongoDBs home page and download MongoDB for your OS. You’ll probably just want to pick the standard install and won’t need any fancy cloud services at this point. Be sure to read through the installation section in the docs section of the site. and do the subsequent tutorials to make sure you can test out that MongoDB was installed correctly. There is a “Getting Started” section that should walk you through this where you can try out creating, reading, inserting and deleting data a sample MongoDB database.

After you have installed MongoDB create a new folder in the root of your application can call it “db”. This is where we are going to store our database and we’re going to point MongoDB to put all the files for this database in here.

To start things up, next go to the directory where you installed Mongo and navigate into the bin directory and open a command window. So on Windows, for example, if you installed in the C:\mongodb directory, you would open a command window or shell in C:\mongodb\bin. You could also get there by opening a command window anywhere and typing

cd "C:\mongodb\bin"

Then you would type the following into the command window where we should specify the path to the “db” folder we just created. So wherever your application lives on your system you’ll want to specify that path by running the following command.

mongod --dbpath "C:\path\to\application\db"

or if you’re using BASH, something like this…

mongod --dbpath /c/path/to/application/db

If all goes well, you should see a message saying that MongoDB is waiting for connections. By default at the time of this writing, the version of MongoDB being used waits for connections on port 28017… so you should see that reflected somewhere in the messaging. Leave this running by leaving this window open (you can minimize if you like).

MongoDB

NOTE: When you first run this command, MongoDB will create all the files it needs in the “db” folder we created, so you should see a number of files pop up in there. Some are quite large.

Now that we have MongoDB installed and we can connect to it, lets write some Node.js code to do some data operations! Woo hoo! Like with so many things we have done before, we will utilise a module to act as a wrapper for our data access with MongoDB. Remember, you could always set things up and write your own code in Node.js for accessing data. Using modules is basically just a way to circumvent all of that grunt work and manual labor involved in those processes. If somebody else has already done the heavy lifting in making a module, might as well make use of it.

Installing Mongoose

I am going to use a popular module for accessing MongoDB on npm called Mongoose.js (which like pretty much all Node.js modules is avialble on npm). There are probably some other modules that you could use, we’re just going to go with this one to start. So as we have done before when we are adding a new module, we need to update our package.json with a new reference to Mongoose. We will also add another module called body-parser which is going to be useful for getting data out of forms so we can save it in our database.

{
    "name": "MVC-Express-Application",
    "description": "An Express.js application using the MVC design pattern...",
    "version": "0.0.1",
    "dependencies": {
        "express": "4.4.4",
        "body-parser": "1.4.3",	
        "express-handlebars": "1.1.0",
        "morgan": "1.1.1",
        "errorhandler": "1.1.1",
        "mongoose": "3.8.8"
    }
}

Then again, we should open a shell in our project root directory and run

$ npm install

which will pull down all the Mongoose and body-parser files.

The body-parser module is middleware (which we discussed earlier), so we need to add it to our app.js file. You can add it along with the other middleware, right after the express.static statement…

app.use(express.static(path.join(__dirname, 'static')));

app.use(bodyParser.json());
app.use(bodyParser.urlencoded({ extended: true }));

Database Settings in config.js

Now, we’ll want to add some initial code to connect our running MongoDB instance. Recall earlier that we created a config.js file. This is where having a config.js file is helpful because we are extending the functionality of our application but we have a handy place to store commonly used components of it. We will need to provide Mongoose a number of different pieces of information (name, host, etc), and we can put that into our config.js file for easy access.

Recall that when we created our config.js file we added a database property to it. We wont have to provide any credentials for our MongoDB connection string when we are doing this development locally. However, if we were to move our app to production it’s very possible that we’d need to do this (e.g. if the username was “admin” and the password was “password”). So the development section of this config object might look different than the production section. We are only using the development configuration for this tutorial, but we’ll also add a database object to the production section as well only to illustrate the possibility of different configurations in different environments.

var config = {};

config.development = {

    database: {
        name: 'MVCApplication',
        host: 'localhost',
        port: '27017',
        credentials: ''
    },
    application: {
        port: 1337
    }
    
};

config.production = {

    database: {
        name: 'tradewinds',
        host: 'localhost',
        port: '8080',
        credentials: 'admin:password@' // username:password@
    },
    application: {
        port: 80
    }    
    
};

config.environment = 'development';

module.exports = config;

So we’ve got our database name, port, and host set. We can now create some data models to store in this database.

Creating Data Models

Create another folder in the root directory called “models” and in it create a new JavaScript file called “Models.js”. In this file we are going to add the following…

var config = require('../config');
var mongoose = require('mongoose');
var connectionString = 'mongodb://' + config[config.environment].database.credentials + config[config.environment].database.host + ':' + config[config.environment].database.port  + '/'+ config[config.environment].database.name;
var db = mongoose.connection;

Here we have a reference to our config file where we can use the database information we’ve set in the config file. We’ll also pull in the mongoose module. The db variable will be the object that represents our database connection. One thing that will be handy for us is having some sort of messaging to tell us if we have connected successfully to the database or if there was an error. Mongoose provides a way for us to do this through the db object…

db.on('error', function(){
    console.log('There was an error connecting to the database');
});

db.once('open', function() {
    console.log('Successfully connected to database');
});

This code will log a message to the console whether we are successful in connecting to the database or if we encounter an error.

Lastly, we’re going to want to call the code to actually connect to MongoDB through Mongoose.

mongoose.connect(connectionString);

Reading through the Mongoose.js docs you can see how to create a data model through the schema interface that mongoose provides. We’ll do something simple like create a Book model definition through the mongoose.Schema syntax and then create an actual model based off of this schema using mongoose.model. Lastly, because our Models.js file is itself a module, we’re going to want to export an object containing our models for other parts of our application (such as our Controllers) to use.

var Book = new mongoose.Schema({
    title: String,
    author: String,
    isPublished: Boolean
});

var BookModel = mongoose.model('Book', Book);

module.exports = {
    BookModel: BookModel
};

We can add as many models as we need for whatever data we want to store by repeating this approach. So if we added a “User” model (e.g. to store account information), our file would look like this…

var Book = new mongoose.Schema({
    title: String,
    author: String,
    isPublished: Boolean
});

var User = new mongoose.Schema({
    name: String,
    password: String,
    email: String
});

var BookModel = mongoose.model('Book', Book);
var UserModel = mongoose.model('User', User);

module.exports = {
    BookModel: BookModel,
    UserModel: UserModel
};

You can create whatever models you want with whatever properties you want for whatever data you need to store.

Accessing Data in Controllers and Views

So let’s now put in some code to read, write, and delete data from our controllers and views. In our “controllers” folder, create a new controller called BookController.js and add the following code…

var Model = require('../models/Models');

exports.Index = function(request, response){
};

exports.BookAdd = function(request, response){
};

exports.BookCreate = function(request, response){ 
};

We’ll add code to get and insert data into the database using our data models momentarily, but before we do that, don’t forget to update our router.js file with a reference to BookController.js and these new routes.

var HomeController = require('./controllers/HomeController');
var BookController = require('./controllers/BookController');

// Routes
module.exports = function(app){
    
    // Main Routes
    
    app.get('/', HomeController.Index);
    app.get('/other', HomeController.Other);   

    // Book Routes
    
    app.get('/books', BookController.Index);
    app.get('/books/add', BookController.BookAdd); 
    app.post('/books/add', BookController.BookCreate); 
    
};

Note that here we essentially have 2 add routes. Notice though that one is a GET route and one is a POST route. We’ll use the GET route to display the form to add a new book, and we’ll use the post route to take in the data entered into that form and add it to the database.

Now back in our BookController.js file, for our main controller in our BookController.js file (the one named Index), we’ll want to set things up so that when a user goes to the /books route, we will show all the books in the database. So do do this we’ll need add some code to fetch the books from our database and then we’ll loop over the results in our view. This is how we’ll do this in our controller…

var Model = require('../models/Models');

exports.Index = function(request, response){

    Model.BookModel.find(function(error, result){
        if (error) {
            console.log('There was an error')
        } else {
            response.pageInfo.title = 'Books';
            response.pageInfo.books = result;
            response.render('books/Index', response.pageInfo);
        }
    });

};

Basically what this code says to do is find all books. We’ll be doing the same thing we did in earlier exercises by attaching everything to the pageInfo object to send to the view. Note that the result parameter (in which will be stored a set of items that the Mongoose find query finds in our MongoDB database) will be set to a “books” property on the pageInfo object. We’ll then send the pageInfo object to the view.

Before we create the view it’s worth noting that if we have an error that occurs with a database operation (or any other operation for that matter) it’s a good idea to do a redirect with messaging to the user so he/she knows that an error occurred. So we can make use of the notifications middleware that we implemented earlier and redirect with a message in case an error occurs. So it would be good practice change the above code to..

var Model = require('../models/Models');

exports.Index = function(request, response){

    Model.BookModel.find(function(error, result){
        if (error) {
            console.log('There was an error');
            response.redirect('/?error=true&message=There was an error getting books from the database');
        } else {
            response.pageInfo.title = 'Books';
            response.pageInfo.books = result;
            response.render('books/Index', response.pageInfo);
        }
    });

};

Here we are redirecting to the home route “/” with the query string and message to display an error notifications. If we build our application right, we hope that we;ll seldom see this error. But errors do happen and it’s important that your application handles things gracefully when they do.

But if we don’t get an error in our database operation, we’ll be able to pass the data we get back to the view. Speaking of the view, let’s create that right now. In our views folder create a new folder called “books” and create an Index.handlebars file in it. Add the following code to this file…

<ul>
{{#books}}
    <li>
        <strong>{{title}}</strong> by: {{ author }} 
    </li>
{{ else }}
    <p>There are no books.</p>
{{/books}}
</ul>

<a href="/books/add">Add Book</a>

Because we passed response.pageInfo directly into the view, the “books” property is directly available to be accessed using Handlebars syntax. So the {{#books}} marker basically says loop over the “books” object that was passed to the view. The “books” object was set to the result we got back from our Mongoose query, which contains a set of book models. Thus, inside the books object both the title and author properties are available because those are part of the book model schema.

Of course, we don’t have any books in our database right now so the message stating that there are no books will appear in this case. In Handlebars, the content that follows the {{ else }} block will render if the {{ books }} set is empty.

So let’s add some code to actually add a book to the database. In our BooksController.js file, add the code to say we’re going to render a form when the user goes to the “books/add” route with a GET request (i.e. navigates there in his/her browser).

exports.Index = function(request, response){

    Model.BookModel.find(function(error, result){
        if (error) {
            console.log('There was an error');
            response.redirect('/?error=true&message=There was an error getting books from the database');
        } else {
            response.pageInfo.title = 'Books';
            response.pageInfo.books = result;
            response.render('books/Index', response.pageInfo);
        }
    });

};

exports.BookAdd = function(request, response){
    response.pageInfo.title = 'Add a Book';
    response.render('books/BookAdd', response.pageInfo);
};

exports.BookCreate = function(request, response){ 
};

All we need to do in our BookAdd GET route is set the page “title” attribute (recall that this is in our Main.handlebars layout) and then tell Express.js to render the “BookAdd” view — which we will create next. So now create a view called BookAdd.handlebars in our “views/books” directory. In this file we will add a form.

<form method="post" action="/books/add">
    <label>Title</label> <input name="title" type="text" />
    <label>Author</label> <input name="author" type="text" />
    <input type="submit" value="Submit" />
</form>

Note that this form, when submitted, will send a POST request to the BookCreate method in our controller. Even though the action is set to “/books/add”, recall in our router.js we added the line:

app.post('/books/add', BookController.BookCreate);

This means that a POST request sent to the “/books/add” endpoint will be handled by the BookCreate method in our controller. So even though the route “/books/add” is the same as the GET request, it’s the type of request that differentiates which controller method will execute.

So in our BookCreate controller we’ll need to add some code to add a new book model object to our database. So in our BookCreate method in BookController.js add the following code…

exports.BookCreate = function(request, response){ 

    var title = request.body.title;
    var author = request.body.author;

    var b = new Model.BookModel({ 
        title: title,
        author: author,
        isPublished: true
    });

    b.save(function(error){
        if(error) {
            console.log('Error');
            response.redirect('/books?error=true&message=There was an error adding the book to the database');
        } else {
            response.redirect('/books?success=true&message=Book created successfully');
        }
    });

};

Here the request object will contain the values submitted with the form on the request.body. The name attributes on each of the text fields get added to the request body. This data is then used to create a new book model object containing these values which can then be saved to the database by calling Mongoose’s save method on it. If the save is successful, we will redirect back to the home books route which will now have the book rendering as part of the list. We’ll even pass in some parameters which if you recall in an earlier discussion will be acted upon by our notification middleware to give us a “Success” message when we’ve successfully added a book! If we are for some reason unable to add a book to the database, we will redirect back to the “/books” route with an error message.

Note that we are not really doing any kind of validation of the data submitted to the form. Normally we would want to check for empty fields and/or invalid inputs. For books we can basically allow a user to enter pretty much anything (as long as there is something there) for both title and author. However, if we were, for example, storing a user’s email address on a “UserModel,” we would want to validate that the e-mail was in valid e-mail format before attempting to add the record to the database. If the e-mail provided by the user was invalid we would want to redirect back to the form with a massage informing the user that the e-mail that they had entered was invalid. You would normally do these checks for all data types and fields before you attempted to add anything to the database. This is something that we’ll revisit more in-depth later on, but it is something that is important and it’s worth mentioning here if only in passing.

Let’s update our views and controller to include the “isPublished” field. First the view…

<form method="post" action="/books/add">
    <label>Title</label> <input name="title" type="text" />
    <label>Author</label> <input name="author" type="text" />
    <label>Is Published?</label> <input name="published" type="checkbox" value="published" />
    <input type="submit" value="Submit" />
</form>

And then the controller…

exports.BookCreate = function(request, response){ 

    var title = request.body.title;
    var author = request.body.author;
    var isPublished = false;
    if(request.body.published === 'published') {
        isPublished = true;
    }

    b.save(function(error){
        if(error) {
            console.log('Error');
            response.redirect('/books?error=true&message=There was an error adding the book to the database');
        } else {
            response.redirect('/books?success=true&message=Book created successfully');
        }
    });
};

Here we have a check to see if the “isPublished” field value is coming up in the request body. If it is, it means that the box is checked. Thus we can set this value to true. If the box is not checked we will create our book in the database with the isPublished flag set to false.

Editing and Deleting Data

How would we go about doing editing and deleting items from the database? To do these actions we’ll need to have access to some sort of identifier use to have a way to tell which item (in this example which book object) we want to act upon. Fortunately MongoDB has been taking care of this for us behind the scenes. Every document in a MongoDB database has an internal “_id” property that contains a unique value that automatically gets added by MongoDB when a new item is created. More on this is discussed in the data modeling section on the MongoDB website. We could see what this key/value pair looks like if we update our view for a book to look like the following (adding an {{_id }} to the view)…

<ul>
{{#books}}
    <li>
        <strong>{{title}}</strong> by: {{ author }} - {{ _id }}
    </li>

{{ else }}
    <p>There are no books.</p>

{{/books}}
</ul>

<a href="/books/add">Add Book</a>

Now if you start up your app and go to the “/books” route, you’ll see there will now also be a code also displayed next to each item that will look something like this…

55a653333cfc15942813fa6e

and each one will be different. That collection of random letters and number is the unique _id value for this particular entry in the database. Why is this value important? Well, it’s because we’re going to make use of this value to edit and delete data. If we know the unique value of the book we want to edit or delete we can act upon it without affecting the other items in the database.

Deleting Data

So let’s actually start with deleting data and then we’ll move on to editing data. How would we do deleting? Well to start we’re going to have create a new controller method to handle delete requests. So let’s add the following method to the bottom of our BookController.js file…

exports.BookDelete = function(request, response){
    var id = request.params.id; 
    console.log('Delete: ' + id)
}

And we’re also going to want to specify the route for deleting an item in in our router.js…

...
    app.get('/books', BookController.Index);
    app.get('/books/add', BookController.BookAdd); 
    app.post('/books/add', BookController.BookCreate); 
    app.get('/books/delete/:id', BookController.BookDelete);
};

Note that we are adding a parameter for an :id. This is because we are going have to pass an id to the controller as a parameter so that the “BookDelete” controller method will know which item to delete.Recall that we discussed using these named parameters in our introduction to Express.js discussion. Please see that section if you need a quick refresher on what these are and how they work. In essence, our id value is going to be available on the request.params object. Because our parameter is named “:id” in the route, that value is made available to us there by Express.js. It is important to note again that there is nothing significant about calling our route “:id”. The name is not really important. If we had named our parameter “tacos” like so…

app.get('/books/delete/:tacos', BookController.BookDelete);

then we could access the value passed in as the first parameter by using request.params.tacos. Of course, it is always good practice to use a descriptive name that is relevant to the code you are writing (so I’d recommend against using “tacos”), but just know that you have the flexibility to name your parameters whatever you like for whatever your purposes are.

Let’s update our Index.handlebars view for books by adding a link to delete that item. We are going to make use of this unique _id key that is present on each item that we have in our database and pass it in as the parameter. So let’s update our view to look like the following…

<ul>
{{#books}}
    <li>
        <strong>{{title}}</strong> by: {{ author }} - <a href="/books/delete/{{ _id }}" onclick="return confirm('Are you sure?')">Delete</a>
    </li>
{{ else }}
    <p>There are no books.</p>

{{/books}}
</ul>

<a href="/books/add">Add Book</a>

So as can be seen here, we have the path to the delete route where we will be passing in the _id key as the parameter which we will use to go find the item we want to delete. We’re also adding a bit of confirmation in inline JavaScript to prevent users from accidentally deleting an item. Confirmation of destructive actions is always a good practice when you write software.

Now if you were to run the application, go to the books route and click on one of the Delete buttons next to a database item, you would get the confirmation message and then see the id of the item you would be trying to delete logged to the console. Of course, we have not written the code to actually delete the item from the database yet, so we’ll do that next. So, back in our “BookDelete” controller method, let’s write the code to actually delete an item. Update the code in the “BookDelete” method to look like the following…

exports.BookDelete = function(request, response){ 
    var id = request.params.id;
    Model.BookModel.remove({ _id: id }, function(error, result) {
        if(error) {
            console.log('Error');
            response.redirect('/books?error=true&message=There was an error deleting the book');
        } else {
            response.redirect('/books?success=true&message=Book deleted successfully');
        }
    });
}

The code will first get the id value from the parameter using request.params.id as we’ve been discussing, and then it will use that variable in Mongoose’s remove method.to look in the database for an item that has its “_id” value as that parameter. When it finds it, it will delete the item and then redirect to the the main “/books” route. So now if you run the app again and delete an item, if all goes well you’ll see that upon redirect the item that you deleted is no longer there. Success!

Editing Data

Editing data going to be interesting because to create an “edit” view we first have to go and get the item that we want from the database and then populate the form with its values, but we are going to use a lot of the same concepts that we use to delete an item (namely, passing an id parameter to a view).

Hopefully by now the concept of creating routes, controllers, and views is becoming somewhat familiar. So to create editing functionality we should first update our router.js file. As we did with creating an item, we’ll need to add 2 routes, one to display the item’s data in a form and the other to receive that data when the form is submitted (posted) back to the server …

...
    app.get('/books', BookController.Index);
    app.get('/books/add', BookController.BookAdd); 
    app.post('/books/add', BookController.BookCreate);
    app.get('/books/edit/:id', BookController.BookEdit);
    app.post('/books/edit', BookController.BookUpdate); 
    app.get('/books/delete/:id', BookController.BookDelete);
};

And let’s add the controller code for our route to display the form…

exports.BookEdit = function(request, response){
    var id = request.params.id;
    
    Model.BookModel.findOne({ _id: id }, function(error, result){
        if(error) {
            console.log('Error');
            response.redirect('/books?error=true&message=There was an error finding a book with this id');
        }
        else {
            response.pageInfo.title = 'Edit Book';
            response.pageInfo.book = result
            response.render('books/BookEdit', response.pageInfo);
        }
    });
}

Here again we are utilizing the _id value that gets passed forward into this view as a parameter just as we did with deleting data, only this time we are using that value to go and get (lookup) this item from the database. If we have a successful result of finding the item in the database, we’ll then pass this data to the view via the “book” property (along with the other pieces of information as we’ve been doing)

So in our view because we have appended the book property onto the pageInfo object and set it equal to all of the data in our database, the various properties of that data item will be available to us on the book object…

<form method="post" action="/books/edit">
    <input name="id" type="hidden" value="{{ book._id }}" />
    <label>Title</label> <input name="title" type="text" value="{{ book.title }}" />
    <label>Author</label> <input name="author" type="text" value="{{ book.author }}" />
    <label>isPublished?</label> <input name="published" type="checkbox" value="published" {{#if book.isPublished}}checked{{/if}} />
    <input type="submit" value="Submit" />
</form>

Note that we are using the Handlebars “if” statement syntax to check the checkbox if this database record has its “isPublished” flag set to true. Note too we’re making use of a hidden input field that stores the _id. This will be needed because when we post this form back to the server, the controller that receives the request will need to know which item to update with the new values that we set.

Speaking of which, let’s write our controller to receive this POST request…

exports.BookUpdate = function(request, response){ 

    var title = request.body.title;
    var author = request.body.author;
    var isPublished = false;
    if(request.body.published === 'published') {
        isPublished = true;
    }
    
    Model.BookModel.update(
        { _id: request.body.id }, 
        {
            title: title,
            author: author,
            isPublished: isPublished
        },
        { multi: true }, 
        function(error, result){
            if(error) {
                console.log('Error');
                response.redirect('/books?error=true&message=There was an error updating the book in the database');
            } else {
                response.redirect('/books?success=true&message=Book updated successfully');
            }        
        }
    );

}

Here we are using the “body” property that is on the request object to access the form data that contains our updated values. We call Mongoose’s update method by passing in updated values. Mongoose will update the database record we tell it to (by giving it the _id value) and will update the properties on that record with what we pass in as the second parameter.

The last thing we should do is put a handy link to edit each item in our Index.handlebars method for books using the _id value just as we did for deleting items…

<ul>
{{#books}}
    <li>
        <strong>{{title}}</strong> by: {{ author }} - <a href="/books/edit/{{ _id }}">Edit</a> <a href="/books/delete/{{ _id }}" onclick="return confirm('Are you sure?')">Delete</a>
    </li>

{{ else }}
    <p>There are no books.</p>

{{/books}}
</ul>

<a href="/books/add">Add Book</a>

Testing It All Out

Whew! That is a lot of information to digest all at once but we have written enough code to actually have a functioning system of data access with our MongoDB instance. If we still have our database running and waiting for connections on port 28017 we can open a new shell in the root of our project and run…

$ node app

You should see a message that the app has started and that we have successfully connected to the database. Now navigate to the “/books” route. Obviously we haven’t added any books yet, so there will be a message saying that there are no books. However, we can change that by going to the “/books/add” route and adding a books there. If all goes well well we should add the book and then redirect back to the “/books” route with a new shiny book in our list. From there, you can also try editing and deleting data as well.

Validation of Data

In this section we will briefly cover validation of data. We have gone over entering data into the database but we sort of glossed over the validation components i.e. verifying that the data is good before we enter it into the database.

To do validation, we are going to make use of a utilities library that we’ll call “Validation” (makes sense). Like with everything else we’ve done, we’ll make it into a module. So in the utilities folder, create a new file called Validation.js. And in the BookController.js file add a reference to this at the top.

var Validation = require('../utilities/Validation');

This is roughly what our validation file might ook like…

exports.IsNullOrEmpty = function(check){
    
    var errors = false;
    
    if(Object.prototype.toString.call(check) === '[object Array]') {
	
        for(var i=0; i < check.length; i++){
	    
            if(!check[i]) {
                errors = true;
            }
            if(check[i].trim() === '') {
                errors = true;
            }
        }
	
    }
    else if(typeof check === 'string') {
        if(!check)
            errors = true;
        if(check.trim() === '')
            errors = true;
    }
    
    return errors;
    
};

exports.Equals = function(one, two) {
    if(one === two)
        return true;
    else
        return false;
};

exports.ValidateEmail = function(email) { 
    var re = /^(([^<>()[\]\\.,;:\s@\"]+(\.[^<>()[\]\\.,;:\s@\"]+)*)|(\".+\"))@((\[[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\])|(([a-zA-Z\-0-9]+\.)+[a-zA-Z]{2,}))$/;
    return re.test(email);
};

exports.ValidateDate = function(dateString) { 
    // Check pattern
    if(!/^\d{4}\/\d{1,2}\/\d{1,2}$/.test(dateString))
        return false;

    // Parse the date parts to integers
    var parts = dateString.split("/");
    var year = parseInt(parts[0], 10);
    var month = parseInt(parts[1], 10);
    var day = parseInt(parts[2], 10);

    if(year < 1000 || year > 3000 || month === 0 || month > 12)
        return false;

    var monthLength = [ 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31 ];

    // Adjust for leap years
    if(year % 400 === 0 || (year % 100 !== 0 && year % 4 === 0))
        monthLength[1] = 29;

    return day > 0 && day <= monthLength[month - 1];
};

Here we have a few different methods that we can pass data to and we’ll want to this before we attempt to do anything with the database. We could definitely add more methods here if we wanted to for any sort of validation that our application needed. These might include things like limiting a max number of characters, or using some regular expressions to make sure that phone numbers, credit cards or whatever else are invalid format. The important thing is that it is all here in one place where we can easily extend upon things.

So for example with our BookCreate view, we can probably just add in some validation to confirm that there are not empty strings entered into any of the fields. To do this we can use our IsNullOrEmpty method. Note that this method gives us the possibility of passing in either a single variable to check or we can pass in an array of variables to check a number of inputs at a single time,

exports.BookCreate = function(request, response){ 

    var title = request.body.title;
    var author = request.body.author;

    if(Validation.IsNullOrEmpty([title, author])) {
        response.redirect('/books/add?error=true&Please fill out all fields');
    }
 ...

Here we are doing a check if the title field and/or the author fields are empty. If either one of them are we are going to redirect to the books/add route with a message to please fill out all fields.

Speaking of redirects, we have been doing that quite a bit in our application with a lot of the same types of parameters for success and error messages in each place. Rather than write these out every time, we can roll these redirects into methods that will handle this for us. We call call these “SuccessRedirect” and “ErrorRedirect” and we can make these part of the Validation module…

exports.SuccessRedirect = function(response, route, message) {
    
    if(typeof message !== 'undefined') {
        response.redirect(route + '?success=true&message=' + message);
    }
    else {
        response.redirect(route + '?success=true');
    }
};

exports.ErrorRedirect = function(response, route, message) {
    
    if(typeof message !== 'undefined') {
	response.redirect(route + '?error=true&message=' + message);
    }
    else {
	response.redirect(route + '?error=true');
    }
};

This just gives us a way to pass in what we need without having to construct the query string every time. So our BookCreate method would become something like…

exports.BookCreate = function(request, response){ 

    var title = request.body.title;
    var author = request.body.author;

    if(Validation.IsNullOrEmpty([title, author])) {
        Validation.ErrorRedirect(response, '/books', 'Please fill out all fields');
    } else {
        var b = new Model.BookModel({ 
            title: title,
            author: author,
            isPublished: true
        });
        b.save(function(error){
            if(error) {
                console.log('Error');
                Validation.ErrorRedirect(response, '/books', 'There was an error adding the book to the database');
            } else {
                Validation.SuccessRedirect(response, '/books', 'Book created successfully');
            }
        });
    }
};

A little bit cleaner and every little bit helps. We’d also want to do the same in our controllers for editing and deleting items as well.

Going even further than this, we could also do validation against the database. For example, when adding a book we could first check to see if a book with the same name already exists in the database and redirect with an error message informing the user that they must enter a unique name — if we cared about something like that. It’s not likely that we’d want to do it with book titles because it is very possible that there could be two books with the same name written by different authors but there definitely are times when you’d want to do this sort of check. For example, with user accounts you’ll often want to
make sure that all user account names and/or e-mail addresses are unique in your system, so you’d definitely want to check if a user with the same account name/email already existed before attempting it to the database.

But since we only have a “BookModel,” let’s just hypothetically say for some reason we want all book titles to be unique in our system. This is what implementing a check against this would look like…

exports.BookCreate = function(request, response){ 

    var title = request.body.title;
    var author = request.body.author;

    if(Validation.IsNullOrEmpty([title, author])) {
        Validation.ErrorRedirect(response, '/books', 'Please fill out all fields');
    } else {

        Model.BookModel.findOne({ title: title }, function(error, result) {

            if(result) {
                Validation.ErrorRedirect(response, '/books', 'There is already a book with this title in the database');
            } else {
                var b = new Model.BookModel({ 
                    title: title,
                    author: author,
                    isPublished: true
                });


                b.save(function(error){
                    if(error) {
                        console.log('Error');
                        Validation.ErrorRedirect(response, '/books', 'There was an error adding the book to the database');
                    } else {
                        Validation.SuccessRedirect(response, '/books', 'Book created successfully');
                    }
                });
            }

        });

    }

};

As before we first check that all fields are filled out. We then look up if there is already a book with this title in the database. If it finds a result, we redirect with an error message saying, “There is already a book with this title in the database.” If not, then it is finally okay to try to add the entry to the database.

Conclusion

Wow, we have covered a lot a lot on data access so far. In upcoming installments, we will look at some more advanced concepts such as session data (signing in/out) as well as securing our application from common attacks such as cross-site request forgeries (CSRFs).

Download the files below to play around with data access. Be sure that you install MongoDB and point it at the “db” folder in the package. This folder is empty in the download, but MongoDB will automatically add all the database files when you first run the command.

Also be sure to remember to run…

$ npm install

to install all dependencies before you try to use the application.

Download Files
]]>
https://9bitstudios.com/2015/07/creating-an-mvc-express-js-application-part-3/feed/ 0
Creating an MVC Express.js Application (Part 2): Middleware and Configuration https://9bitstudios.com/2014/12/creating-an-mvc-express-js-application-part-2/ https://9bitstudios.com/2014/12/creating-an-mvc-express-js-application-part-2/#respond Fri, 19 Dec 2014 19:41:27 +0000 https://9bitstudios.com/?p=1010 Previously, in an earlier installment we discussed some initial considerations for creating an application in Express.js following the Model View Controller (MVC) design pattern. We’ll pick up where we left off in what follows. The focal point will center around middleware and configuration…

Middleware

One of the things that we are going to want to implement in our application is middleware. There is a pretty good list of Express.js middleware in the Express.js project. Middleware is an important component of Express.js applications. You couple probably think of a middleware function or method as a function that runs on every request/response cycle at whatever point you want to specify. For example, if you wanted to see if the current user who is making the request is authenticated on every single request, you might have this authentication check run in a middleware function before issuing the response. That’s just one example, but there are many other pieces of functionality that you can run within middleware functions.

So let’s add some of the common Express.js middlewares. One useful middleware utility that we can use is a logging component. This will give us information about all of the requests made as our application runs. Express.js uses something called Morgan to accomplish this.

To add middleware, we’re going to want to add it to our package.json file as a dependency. So let’s update our package.json file to look like the following

{
    "name": "MVC-Express-Application",
    "description": "An Express.js application using the MVC design pattern...",
    "version": "0.0.1",
    "dependencies": {
        "express": "4.4.4",	
        "express-handlebars": "1.1.0",
        "morgan": "1.1.1",
    }
}

Don’t forget that we have to install our new module as well. Fortunately, Node.js and npm make this easy. All we have to do is run $ npm install again and all of our packages will be updated…

$ npm install

Now that our dependency is installed, we need to add a reference to it in our main application file…

var logger = require('morgan');

Let’s add the following lines of code to our main app.js file…

/* Morgan - https://github.com/expressjs/morgan
 HTTP request logger middleware for node.js */
app.use(logger({ format: 'dev', immediate: true }));

Now if we run our application and look at our CLI window we can see all the requests being output on every request response cycle. And just like that, we have made use of our first middleware.

We will also want a utility to log any errors that occur while we are doing development. So let’s add an error handling utility to our package.json file…

{
    "name": "MVC-Express-Application",
    "description": "An Express.js application using the MVC design pattern...",
    "version": "0.0.1",
    "dependencies": {
        "express": "4.4.4",	
        "express-handlebars": "1.1.0",
        "morgan": "1.1.1",
        "errorhandler": "1.1.1"
    }
}

After we run $npm install again to install the error handling module, we again need to add a reference to it…

var errorHandler = require('errorhandler');

Now we can also add the following code to our main application file as well…

/* errorhandler - https://github.com/expressjs/errorhandler
 Show errors in development. */
app.use(errorHandler({ dumpExceptions: true, showStack: true }));

We’d probably want to comment this out if we were ever to move our application into a production environment, but for development this is a very handy thing to have for debugging because it can tell us where, when, and how any errors in our application are occurring.

We are not just limited to using middleware that Express.js provides. We can also create our own as well. Let’s add a directory called “utilities” to our project and put a Middleware.js file in this folder.

We will want to make sure that we include a reference to this file in our main application file.

var Middleware = require('./utilities/Middleware');

What can we add to our Middleware.js file? Well, whatever we want really. For example, we can add something that will check to see if there is a set value in the query string and tell our application to show a notification depending what is set. Notifications such as “Profile updated successfully” or “There was an error uploading the file” or other relevant messages are a very important part of a good user-experience in any application. So our application is going to need these as well and using a middleware function to handle this aspect of functionality seems like a decent approach.

Recall that previously we had appended a “pageInfo” object to the response pass to our views. We will utilize this same approach here and add a “notifications” property to this object. Because the middleware runs *before* the controllers that handle our routes, we can initialize the pageInfo property here instead…

exports.AppendNotifications = function(request, response, next) {
    
    response.pageInfo = {};
    response.pageInfo.notifications = {};

    if(request.param('success')) {
        response.pageInfo.notifications.success = "Success!"
    }
    else if (request.param('error')){
        response.pageInfo.notifications.error = "Sorry, an error occured"
    }
    
    next();
    
};

Notice the next(); function at the end of our custom middleware function. This is a common function utilized in middleware implementations. Basically all it does is say “go to the next middleware function, if any.” If there are no more middleware functions to run, execution of the application will just continue on as normal. This way, you can group middleware functions together to run sequentially in the order that you want to specify.

We can also add additional properties on this object e.g. like one to store a message with specific information about the event that occurred. So we’ll add a message property to the notifications object…

exports.AppendNotifications = function(request, response, next) {
    
    response.pageInfo = {};
    response.pageInfo.notifications = {};
    response.pageInfo.notifications.message = '';

    if(request.param('message')) {
        response.pageInfo.notifications.message = request.param('message'); 
    }

    if(request.param('success')) {
        response.pageInfo.notifications.success = "Success!"
    }
    else if (request.param('error')){
        response.pageInfo.notifications.error = "Error!"
    }
    
    next();
    
};

Now we can add our middleware to our main application file, just as we did with the Express.js proved middleware…

app.use(Middleware.AppendNotifications);

Now that we have our middleware in place we’ll need to update our views to be able to show the notifications. Fortunately, we can add something to show these notifications in our Main.handlebars layout…

<!DOCTYPE html>
<html lang="en">
    <head>
      <meta charset="utf-8">
      <meta http-equiv="X-UA-Compatible" content="IE=edge">
      <meta name="viewport" content="width=device-width, initial-scale=1.0">
      <meta name="description" content="">
      <meta name="author" content="">
      <link rel="shortcut icon" href="data:image/x-icon;," type="image/x-icon"> 

      <title>{{ title }}</title>

    </head>

    <body>

        <div class="notifications">
    
            {{#if notifications.success}}
            <div class="success">
                {{ notifications.success }} {{ notifications.message }}
            </div>
            {{/if}}
    
            {{#if notifications.error}}
            <div class="error">
                {{ notifications.error }} {{ notifications.message }}
            </div>
            {{/if}}

        </div>

        {{{body}}}
    </body>
</html>

This uses the conditional {{#if }} syntax that the Handlebars.js templating engine provides. This is one of the built-in helpers of Handlebars. You can read more about conditionals and other helpers here.

Now if you navigate to one of our routes and add the query string to the end e.g. https://localhost:1337/?success=true or https://localhost:1337/other?error=true we can see the notification appear. We can also add a message parameter as well e.g. https://localhost:1337/?success=true&message=User added to database. In the normal flow of application, we would usually do a redirect with these parameters after performing some action depending on the outcome but we don’t really have that functionality in our application yet so to see the notifications we just have to add them end of of our URL.

We will use middleware more extensively as the development of our application matures. But for now this illustration shows how middleware can be implemented in useful ways.

Now that we’ve added a spot for notifications, it might be a good idea to add a little bit of style to those notifications. Recall earlier that in our app.js file we had added the following line…

app.use(express.static(path.join(__dirname, 'static')));

This was, if you recall, a way set a directory to serve up some static files from. In this case, we’d want to serve up a CSS file to add a bit of styling in our app. So in this “static” directory create a “css” folder and create a style.css file in tie “css” folder. In this file add the following…

.notifications .success {
  padding: 5px;
  border: 1px solid #090;
  color: #090;
  background-color: #9fc;
}

.notifications .error {
  padding: 5px;
  border: 1px solid #900;
  color: #900;
  background-color: #fc9;
}

This will add some styling to our notifications. Of course we’ll also have to update our Main.handlebars layout with a reference to this CSS file in the <head> section…

<!DOCTYPE html>
<html lang="en">
    <head>
      <meta charset="utf-8">
      <meta http-equiv="X-UA-Compatible" content="IE=edge">
      <meta name="viewport" content="width=device-width, initial-scale=1.0">
      <meta name="description" content="">
      <meta name="author" content="">
      <link rel="shortcut icon" href="data:image/x-icon;," type="image/x-icon"> 
      <link href="/css/style.css" rel="stylesheet">
      
      <title>{{ title }}</title>

    </head>

    <body>

        <div class="notifications">
    
           {{#if notifications.success}}
            <div class="success">
                {{ notifications.success }} {{ notifications.message }}
            </div>
            {{/if}}
     
            {{#if notifications.error}}
            <div class="error">
                {{ notifications.error }} {{ notifications.message }}
            </div>
            {{/if}}

        </div>

        {{{body}}}

    </body>
</html>

Now if you add the success or error and/or message query string(s) to the end of any of our routes you will see the same behavior as before only this time with some slick styling for our notifications! This static directory can be used to serve up any other file type that we might need (JavaScript files, images, etc). We just need to add the correct path reference in the layouts or our individual views.

This notifications piece is a great candidate to be a partial view. We looked at partial views earlier on. So we can move this piece…

<div class="notifications">
    
    {{#if notifications.success}}
        <div class="success">
            {{ notifications.success }} {{ notifications.message }}
        </div>
    {{/if}}
     
    {{#if notifications.error}}
        <div class="error">
            {{ notifications.error }} {{ notifications.message }}
        </div>
    {{/if}}

</div>

into its own view called Notifications.handlebars and put it in the “partials” directory. Then we can update the Main.handlebars layout…

<!DOCTYPE html>
<html lang="en">
    <head>
      <meta charset="utf-8">
      <meta http-equiv="X-UA-Compatible" content="IE=edge">
      <meta name="viewport" content="width=device-width, initial-scale=1.0">
      <meta name="description" content="">
      <meta name="author" content="">
      <link rel="shortcut icon" href="data:image/x-icon;," type="image/x-icon"> 
      <link href="/css/style.css" rel="stylesheet">
      
      <title>{{ title }}</title>

    </head>

    <body>

        {{> Notifications}}

        {{{body}}}

    </body>
</html>

Now we’ll shift gears and talk about configuration, which is another component that is important to any well-structured application.

Configuration

If you have used any framework in any language — such as Laravel (PHP) or Django (Python) — you know that it is often a good idea to have a configuration file where you can store application variables that will remain constant throughout the application. These sorts of settings include things like database names, connection strings, root URLs, ports, or anything else that you want to utilize. It will also give you a place where you can easily make changes to settings when moving from one environment to another, e.g. when moving from your development environment to production

So we’ll want to create a config.js file for our application as well. Create a config.js file and place it in the main top-level project folder. In config.js place the following code

var config = {};

config.development = {

    application: {
        port: 1337
    }
    
};

config.production = {

    application: {
        port: 80
    }    
    
};

config.environment = 'development';

module.exports = config;

And we’ll need to make sure that we include a reference to our config file in our main application file.

var config = require('./config');

So, for example, if we do something like changing the following line in our main application file from…

app.set('port', 1337);

to

app.set('port', config[config.environment].application.port);

we are making use of our configuration file because the value of the port we have set will be looked up in the config file. Now if we ever want to push our application from development to staging to production, the only thing we need to edit is the config.js file because, we have a way to quickly and easily set our “environment”. So if we change that string value from “development” to “production,” all of the variables within the object will be switched over across our application. The rest of the application will remain unchanged.

The great thing about this too is that as we add more features and functionality to our application, we can store the needed values for these in our config.js file. This way our application will scale well as it grows and progresses on. Other values important in an application such as database connection strings, credentials, SMTP servers, and strings used for creating hashes and tokens can all be stored in a configuration file. At the end of it all, our config.js file might end up looking more like the following…

var config = {};

config.development = {
    
    database: {
        name: 'MVCApplication',
        host: 'localhost',
        port: '27017',
        credentials: '' // username:password@
    },
    smtp: {
        username: "username",
        password: "password",
        host: "smtp.gmail.com",
        port: 587,
        ssl: false
    },
    application: {
        port: 1337,
        cookieKey: '8YQM5GUAtLAT34'
    }
    
};

config.production = {
    
    database: {
        name: 'proddb',
        host: 'localhost',
        port: '8080',
        credentials: 'admin:password@' // username:password@
    },
    smtp: {
        username: "username",
        password: "password",
        host: "smtp.yourmailserver.com",
        port: 25,
        ssl: false
    },    
    application: {
        port: 80,
        cookieKey: '5SCjWfsTW8ySul'
    }    
    
};

config.environment = 'development';

module.exports = config;

This is one way to do configuration. Keep in mind that it’s not the only way and there are many other ways you could implement a configuration component in your application. It will probably often come down to a matter of personal preference. The important thing is that you do it in some manner or another to give your application a greater degree of flexibility as you move between environments for development, test, and production. You’ll be glad that you did and you’ll thank yourself later.

Summary

Overall, in this section we looked at 2 important aspects of creating an Express.js application: middleware and configuration. In upcoming explorations, we’ll take a look at some more advanced templating with our views as well as data access and authentication. But for now, it’s good to digest this information in small portions. So feel free download the files below and play around with application configuration and middleware. Remember to run…

$ npm install

after you download to install dependencies.

Download Files
]]>
https://9bitstudios.com/2014/12/creating-an-mvc-express-js-application-part-2/feed/ 0