Model-view-controller

Design patterns are solutions to common programming situations. An extremely popular pattern for web development is Model-view-controller, or MVC, and it's derivatives.

This pattern separates our concerns into 3 areas:

  • Model - which handles the storage of data.
  • View - displays to the user data and updates according to changes in the model.
  • Controller - connects the model and the view.

This may seem abstract. That's because it is! Don't let this vague description overwhelm or confuse you.

If an interviewer asked you what MVC was, and you didn't tell them anything but what we've gone over, it would only be fair for them to think of that as a great answer.

Now, if that interview then asked how MVC related to Angular, you would have to have some understanding of how Angular handles, manipulates, and displays data.

We will get a introduction to that here.

MVC and Angular

Angular says that it's not MVC, but that's it's MV*. The * standing for "whatever."

Don't be fooled, we can consider Angular an MVC framework.

View

In Angular, the view is written in an HTML file. Sprinkled in the HTML file are Angular Directives. If you don't know what those are right now, it's okay. For now, just know that they are what make the view more than an HTML file, and help it communicate with our controller.

To tell Angular that we want our HTML to be the view, we us the directive ng-app. We use it like this:

<html ng-app="myApp">

Any HTML in between the opening and closing tag that has the ng-app directive is an Angular view.

Controller

In our JavaScript, we will have a controller function. This function needs to be connected to our application. One way to do that is to add it to the variable representing the our application.

var app = angular.module("myApp");

app.controller("ourNewController", function () {
    // controller logic goes here
});

Our controllers will require Angular services or our own services. These services will help us with all sorts of things.

Probably our most important service is called $scope.

The "$" signifies that the service is an Angular service.

We use dependency injection to be able to use services in our controller. We inject the service like this:

app.controller("ourNewController", function ($scope) {})

You will also see it like this.

app.controller("ourNewController", ["$scope", function ($scope) {}])

The first way will break if your code is minimized.

For this controller to communicate with our view, we can add a directive to our view. Specifically the ng-controller directive.

<body ng-controller="ourNewController">

$scope is our Model!!

Model

We love our $scope object. It will contain data to be displayed to our user. It will also contain data collected from input fields in the view.

$scope can also contain functions that can be invoked/called at different times. Events like clicking, or data being changed from user input, or data being manipulated by the controller can trigger these functions.

Let's see one example of how we can use $scope.

app.controller("ourNewController", function ($scope) {
    $scope.name = "Franklin"
})

We just gave $scope some data, and now we can use that in the view.

<body ng-controller="ourNewController">
    <p>{{name}}</p>
</body>

If you are following along, we are missing some set-up code. There will be a full Angular app, HTML and JS, at the bottom.

When this page gets rendered, {{name}} will be replaced by Franklin.

This is called data binding

Data binding

We just saw data go from the model to the view, but what about from the view to the model?

We will use a directive called ng-model

<input type="text" ng-model="name" />

Now, whatever is entered into that input box will update the model.

$scope.name will be changed to "Alfred" if the user types "Alfred" into the input box.

If this is our controller, we would observe two way data binding

<body ng-controller="ourNewController">
    <p>{{name}}</p>
    <input type="text" ng-model="name" />
</body>

The view updates the model because of the input tag with the ng-model directive, and as the model updates, it updates the view using the {{name}} which is attached to $scope. Remember $scope.name?

As promised, here is our app. It's all there! Model, view, controller and two way data binding.

<!doctype html>
<html ng-app="myApp">
  <head>
    <title>My Angular App</title>
    <script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.5.6/angular.min.js"></script>
  </head>
  <body ng-controller="ourNewController">  
    <p>{{name}}</p>
    <input type="text" ng-model="name" />
  </body> 
</html> 
var app = angular.module("myApp");

app.controller("ourNewController", function ($scope) {  
    $scope.name = "Franklin"
})