Difference between revisions of "Getting MEAN"

From CSE330 Wiki
Jump to: navigation, search
Line 13: Line 13:
 
* Restart your app, make sure you can see a link to the newly created package.
 
* Restart your app, make sure you can see a link to the newly created package.
  
== A Closer Look at the App ==
+
=== A Closer Look at the App ===
 
Take a look at the directory where you app resides, you will see two folders '''public''' and  '''server''', which contain code for the client side and server side respectively.
 
Take a look at the directory where you app resides, you will see two folders '''public''' and  '''server''', which contain code for the client side and server side respectively.
  
Line 69: Line 69:
 
If you have trouble understanding what the code does, review the Mongoose [http://mongoosejs.com/docs/index.html quick start] guide.
 
If you have trouble understanding what the code does, review the Mongoose [http://mongoosejs.com/docs/index.html quick start] guide.
  
= Practice =  
+
= Models Practice =  
 
Define a schema for a model named '''Phone''', name it phone.js and save it in the corresponding folder in 'myPackage' (hint: /packages/myPackage/server/models/)
 
Define a schema for a model named '''Phone''', name it phone.js and save it in the corresponding folder in 'myPackage' (hint: /packages/myPackage/server/models/)
 
A product needs to have the following fields with specific types. Here is an example of a Phone object can be stored in the MongoDB:
 
A product needs to have the following fields with specific types. Here is an example of a Phone object can be stored in the MongoDB:
Line 117: Line 117:
  
  
== Views & Routing ==
+
= Views & Routing =
 
Let's switch to the public folder where the views reside.  
 
Let's switch to the public folder where the views reside.  
  
Line 144: Line 144:
  
 
* Try changing {{item.title}} inside the <a> </a>tags to "my articles" see what happens to the page.
 
* Try changing {{item.title}} inside the <a> </a>tags to "my articles" see what happens to the page.
* The ui-sref is "href" in ui-route, an AngularJS plugin, try changing {{item.link}} to #!/newroute,  
+
* The ui-sref is "href" in ui-route, an AngularJS plugin, try changing {{item.link}} to #!/myarticles,  
 
* What happens to the application now? When you click on "my articles"?
 
* What happens to the application now? When you click on "my articles"?
  
Line 153: Line 153:
 
open up articles.js found in this folder and find this line:
 
open up articles.js found in this folder and find this line:
  
             .state('all phones', {
+
             .state('all articles', {
                 url: '/phones',
+
                 url: '/articles',
 
                 templateUrl: 'public/articles/views/list.html',
 
                 templateUrl: 'public/articles/views/list.html',
 
                 resolve: {
 
                 resolve: {
Line 160: Line 160:
 
                 }
 
                 }
 
             }
 
             }
This is ui-route's  
+
This is ui-route's way of telling the server what to serve the page specified by the templateUrl when it sees "localhost:3000/#!/phones".
 
+
The #! is a hash prefix used for MEAN to make ajax calls so make sure to include it when coding your views.
 
+
Now try changing the url to "/myarticles", save and go back to your app, click on "my articles" now, what happens?
 
 
  
 +
*This is important if you want to customize your navigation bar and links. Just remember that each url needs an entry in the route file, in the format of the example above.
  
  
  
  
 +
= Practice =
  
=== Packages ===
+
Can you implement a view in your myPackage to display all phones injected in the DB?
* Create a package and locate it. Compare the file structure
+
Hint: myPackage has the same file structure as the default app.
Once you init and run an app,
 

Revision as of 23:33, 29 April 2014

Installation

  • To install MEAN, follow instructions here on how to get started.
  • Take a moment and read the rest of the documentations to get familiar with the file structure and idioms.

Running the Default App

  • Init and run an app. Make sure MongoDB is connected and running (if you run into problems, refer to the section on MongoDB)
  • Explore features of the default Article app (such as logging in, adding/deleting articles).

Generating a Package

  • By now you should know what a package is in MEAN. If you don't, read this.
  • Try creating a package named myPackage and locate it inside the packages folder
  • Compare the structure of myPackage folder to that of the default app. Make sure you see both public and server folders and their subfolders.
  • Restart your app, make sure you can see a link to the newly created package.

A Closer Look at the App

Take a look at the directory where you app resides, you will see two folders public and server, which contain code for the client side and server side respectively.


Models

Open up article.js in /server/models

MEAN is MVC on the client side and the server side. Since the model is tied to the backend to MongoDB, you will only see the models folder on the server side, which is normal. The models are mongoose models that's why we need to require mongoose (what the following line does):

var mongoose = require('mongoose'), Schema = mongoose.Schema;

The following part then defines the schema:

var ArticleSchema = new Schema({

   created: {
       type: Date,
       default: Date.now
   },
   title: {
       type: String,
       default: ,
       trim: true
   },
   content: {
       type: String,
       default: ,
       trim: true
   },
   user: {
       type: Schema.ObjectId,
       ref: 'User'
   }

});

The next part is validations, or criteria an object needs to pass before it can be saved to the DB. The following code is to make sure that an article has a title:

ArticleSchema.path('title').validate(function(title) {

   return title.length;

}, 'Title cannot be blank');


Finally, Mongoose allows us to define methods to our data objects as well. These are called statics. From the Mongoose doc: Schemas not only define the structure of your document and casting of properties, they also define document instance methods, static Model methods, compound indexes and document lifecycle hooks called middleware. The following code defines a method called load for the article schema:

ArticleSchema.statics.load = function(id, cb) {

   this.findOne({
       _id: id
   }).populate('user', 'name username').exec(cb);

};

If you have trouble understanding what the code does, review the Mongoose quick start guide.

Models Practice

Define a schema for a model named Phone, name it phone.js and save it in the corresponding folder in 'myPackage' (hint: /packages/myPackage/server/models/) A product needs to have the following fields with specific types. Here is an example of a Phone object can be stored in the MongoDB:

   {
       "age": 0, 
       "id": "motorola-xoom-with-wi-fi", 
       "imageUrl": "img/phones/motorola-xoom-with-wi-fi.0.jpg", 
       "name": "Motorola XOOM\u2122 with Wi-Fi", 
       "snippet": "The Next, Next Generation\r\n\r\nExperience the future with Motorola XOOM with Wi-Fi, the world's first tablet powered by Android 3.0 (Honeycomb)."
   }

This is taken from phones.json used by the AngularJS tutorial. If you have gone through the tutorial, you should have realized that instead of using a DB, json files were used to simplify the tutorial. Find phones.json in /app/phones in the angular tutorial folder and try importing its content to MongoDB so you can use them in your current MEAN package.

  • Run mongod and connect to mongo shell (mongo --shell), then type "use mean-dev" to switch to database used by mean.
  • Type mongoimport --db mean-dev --collection phones --type json --file <path to phones.json> --jsonArray
  • Type show collections to see if phones are added to your database, type coll = db.phones to see the content of the file.

Controllers

You'll find a controllers folder on both the server side and the client side.

  • The client side controllers are part of the Angular MVC scheme that contains client side logic and may issue requests to the server.
  • The server side controllers deal with the models and requests from the client side.

Server side:

  • Find articles.js in the controllers folder. Try to understand what each part does.
  • Find articles.js in /server/routes/middlewares

You'll see that it requires the articles controller and its methods for querying the database.

The first section requires the articles controller, which defines different methods

For example: app.route('/articles')

       .get(articles.all)

tells the server to use a method named "all" in the articles controller when the url is pointed to /articles.

Client side: open up articles.js in /public/articles/controllers Compare the functions defined in ArticlesController, can you find the corresponding functions on the server side implementation of articles controller?

Here is a diagram to help you under stand how this works:

File:Pic


Views & Routing

Let's switch to the public folder where the views reside.

Go to public/articles/views, open up list.html: The first line tells the framework that ArticlesController is responsible for this particular view and when this view is loaded, use find() to initiate data binding.

<section data-ng-controller="ArticlesController" data-ng-init="find()">

Feel free to take a look at what find() does. Make sure you understand that what find() does is actually done by the backend, where a corresponding find() is written (as mentioned above). Hopefully you have a better understanding of how these technologies all work together now.

Review the AngularJS section if you have any questions regarding the view data binding.

The view files in articles/views only defines the code for displaying the articles, where does the navigation bar gets defined. The answer is in /public/system.

  • The .html files in public/system/views provide a container/layout for the application.

For example, header.html includes the menu bar (displayed on the top of the page):

  • Try changing Template:Item.title inside the <a> </a>tags to "my articles" see what happens to the page.
  • The ui-sref is "href" in ui-route, an AngularJS plugin, try changing Template:Item.link to #!/myarticles,
  • What happens to the application now? When you click on "my articles"?

The page to articles is no longer served!

But how does the framework know which page to serve given a certain url? The file that's responsible for this (called routing in web development) is in public/articles/routes

open up articles.js found in this folder and find this line:

           .state('all articles', {
               url: '/articles',
               templateUrl: 'public/articles/views/list.html',
               resolve: {
                   loggedin: checkLoggedin
               }
           }

This is ui-route's way of telling the server what to serve the page specified by the templateUrl when it sees "localhost:3000/#!/phones". The #! is a hash prefix used for MEAN to make ajax calls so make sure to include it when coding your views. Now try changing the url to "/myarticles", save and go back to your app, click on "my articles" now, what happens?

  • This is important if you want to customize your navigation bar and links. Just remember that each url needs an entry in the route file, in the format of the example above.



Practice

Can you implement a view in your myPackage to display all phones injected in the DB? Hint: myPackage has the same file structure as the default app.