Click here to Skip to main content
15,881,248 members
Articles / Web Development / HTML

How to Make an Email Web App using Angular

Rate me:
Please Sign up or sign in to vote.
4.81/5 (30 votes)
30 Jan 2014CPOL20 min read 113.2K   94   51   11
How to make an email web app using Angular

Introduction

We are going to create an email application using Angular JS. First, we're going to build the front end using AngularJS and HTML, at the end we’re going to add in the server portion.

We're going to learn angular by diving right in and explaining concepts as we go as we have to. Since we’re not doing the server portion until the end, we will need to mock that data right in the code. I think this is not only a good way to learn, it's a good way to go about building an application.

To start with, we need our boilerplate HTML. This HTML will include all the necessary libraries. We are going to use Bootstrap for our look and feel and of course Angular for our guts.

Here is what that code looks like:

Image 1

HTML
<!DOCTYPE html>
<html>
<head>
    <script  src="http://netdna.bootstrapcdn.com/twitter-bootstrap/2.3.2/js/bootstrap.min.js"></script>
    <script src="http://ajax.googleapis.com/ajax/libs/angularjs/1.2.6/angular.min.js"></script>
    <link rel="stylesheet" type="text/css" href="http://netdna.bootstrapcdn.com/twitter-bootstrap/2.3.2/css/bootstrap-combined.min.css"/>
</head>
<body>
    <div class="container">
    </div>
</body>
</html>

To start with, we are going to focus on functionality related to managing emails, this means we are not going to address things like user sign in, at least not right now.

The first thing we are going to tackle is the email list. From this screen, we should be able to see who the email is from, what the subject of the email is, and when we received it.

First, we are going to write the HTML for this table, then we are going to use angular to generate it dynamically. Here is the HTML for the static version:

HTML
<table class="table table-bordered table-condensed">
    <tbody>
        <tr>
            <td>Guinan</td>
            <td>It's an Earth drink. Prune juice.</td>
            <td>Dec 24</td>
        </tr>
        <tr>
            <td>Beverly Crusher</td>
            <td>Captain always push themselves too hard.</td>
            <td>Dec 23</td>
        </tr>
        <tr>
            <td>Mom</td>
            <td>Don't forget to wear clean underwear today.</td>
            <td>Nov 22</td>
        </tr>
    </tbody>
</table>

The classes on the table are bootstrap classes that make the table look nice. This is what it looks this:

We're going to take a very incremental step by step approach to build this table using angular in order to introduce several concepts in detail. First, we are going to try to use an angular expression to replace one of the pieces of data. Replace Guinan with {{ "Guinan Test" }}. This should cause Guinan Test to be displayed instead of Guinan.

But that’s not what happens. Instead this happens:

Image 2

This is because AngularJS does not automatically apply itself. You have to tell Angular what portions of the page to apply itself on. You do that by adding the ng-app attribute, you can add that attribute at any level, let’s add it to the container <div> tag and see what happens.

Image 3

Your HTML tag should look like this:

HTML
<div class="container" ng-app>

When you refresh, you should see the value inside the brackets:

Image 4

Expressions allow you to embed JavaScript right into your HTML. (Technically it’s not JavaScript - but that’s a topic for another time). In the real world, there would be no point in using an expression just to display a string, I’m doing it here in order to introduce the concept.

Basically, angular runs the code inside the double curly brackets and renders the result. If for example, you replaced that expression with:

C#
{{ "Guinan" + " " + "Smith" }}

Image 5

If you replaced the expression with:

C#
{{ 10 * 3 }}

You would get:

Image 6

Again these aren’t real world examples, there would be no point in using an express that multiplies 10 times 3 since we already know the answer. The real fun is when we start using expressions with data.

So let’s continue making this table data driven. Now we already used the ng-app attribute in order for angular to know what portion of the HTML to process. Angular calls these directives. Now we are going to use the ng-init attribute to initialize some data, then update one of the rows to use that data.

We can use this attribute anywhere. I’m going to put it in <tbody> tag. So my <tbody> tag looks like this:

HTML
<tbody ng-init="email={from: 'John', subject: 'I love angular', date: 'Jan 1'}">

Now I’m going to update the first row in my table to use that data. From this:

HTML
<tr>
    <td>{{ 10 * 3 }}</td>
    <td>It's an Earth drink. Prune juice.</td>
    <td>Dec 24</td>
</tr>

To this:

HTML
<tr>
    <td>{{ email.from }}</td>
    <td>{{ email.subject }}</td>
    <td>{{ email.date }}</td>
</tr>

And when I run it, I get this:

Image 7

Now instead of one email, let’s do an array of emails, then display one row for each email. To do that, we will have to change our “ng-init” so that it creates an array, then use another Angular directive to repeat the HTML row for each email. To do that, we use another directive called “ng-repeat”.

So change the ng-init to:

HTML
<tbody ng-init="
  emails = [
    { from: 'John', subject: 'I love angular', date: 'Jan 1' },
    { from: 'Jack', subject: 'Angular and I are just friends', date: 'Feb 15' },
    { from: 'Ember', subject: 'I hate you Angular!', date: 'Dec 8' }
  ]
">

Then add the following ng-repeat attribute and value to the <tr> tag:

ng-repeat="email in emails"

So that it looks like this:

HTML
<tr ng-repeat="email in emails">

When you run it, you should get this:

Image 8

Now we have a dynamically generated table. The problem is that the data is all in the HTML, what good is that, let's fix that.

Let’s get the code that initializes the emails array out of the HTML to where it belongs in the JavaScript. To do this, we will have to create a special function that Angular calls a controller. Then, we will use the ng-controller directive to associate that controller with a portion of the HTML - similar to what we did with ng-app.

So add the following code to your JavaScript:

JavaScript
function EmailController($scope) {
  $scope.emails = [
    { from: 'John', subject: 'I love angular', date: 'Jan 1' },
    { from: 'Jack', subject: 'Angular and I are just friends', date: 'Feb 15' },
    { from: 'Ember', subject: 'I hate you Angular!', date: 'Dec 8' }
  ];
}

Then in your HTML, add the ng-controller directive and assign it the value EmailController. You can use this directive on any element, but only that element and its child elements can access the emails variable created in the controller, so it should be assigned to a parent of the <tr> tag. I’m going to add it to the table tag so that it looks like this:

HTML
<table ng-controller="EmailController" class="table table-border table-condensed">

If you run it, everything should look exactly the same. The only thing that changed is that instead of the emails being initialized inside the HTML, it’s now being initialized inside the controller function.

Did you notice the controller function has a parameter called $scope? That’s how data is shared between a controller and HTML. Any variables created in the $scope by the controller are accessible by the HTML, and vise versa.

Now we will add the ability to click on an email and see its content. We are going to use Bootstrap’s standard modal dialog HTML to create the email popup. To do that, add the following HTML below your table:

HTML
<div class="modal">
    <div class="modal-header">
        <button type="button" class="close">×</button>
        <h3>Subject</h3>
    </div>
    <div class="modal-body">
        <strong>From:</strong> Steve <br />
        <strong>Date:</strong> Jan 2 <br />
        <br />
        <p>
            Hey You, <br />
            <br />
            How you doing?<br />
            <br />
            Sincerely<br />
            Your Bro
        </p>
    </div>
    <div class="modal-footer">
        <a href="#" class="btn btn-primary">Close</a>
    </div>
</div>

When you run this, you should see a popup overlapping your table that looks like this:

Image 9

Now we only want this popup to appear when the user clicks on an email on the list. So first, we need a way to control its visibility. We do that by binding it to a variable, when the variable is true the popup is visible, when it's false it's not.

First let's create the variable in the controller, let's call it isPopupVisible and let's set it to false. Like so:

JavaScript
$scope.isPopupVisible = false;

Your controller should look something like this:

JavaScript
function EmailController($scope) {
    $scope.isPopupVisible = false;

    $scope.emails = [
       { from: 'John', subject: 'I love angular', date: 'Jan 1' },
       { from: 'Jack', subject: 'Angular and I are just friends', date: 'Feb 15' },
       { from: 'Ember', subject: 'I hate you Angular!', date: 'Dec 8' }
    ];
}

Now we add the ng-show directive to the popup in order to bind it to that variable. To do that, add the following directive to your modal div:

ng-show="isPopupVisible"

It should look like this:

HTML
<div class="modal" ng-show="isPopupVisible">

Now that we have bound the visibility of the popup to the isPopupVisible variable, we need a way to set that variable to true. So let's wire up that click event to the email list. First, we’ll create a function that sets that variable to true, let's call it showPopup(), like so:

JavaScript
$scope.showPopup = function () {
    $scope.isPopupVisible = true;
};

Your controller should now look like this:

JavaScript
function EmailController($scope) {
    $scope.isPopupVisible = false;

    $scope.showPopup = function () {
        $scope.isPopupVisible = true;
    };

    $scope.emails = [
       { from: 'John', subject: 'I love angular', date: 'Jan 1' },
       { from: 'Jack', subject: 'Angular and I are just friends', date: 'Feb 15' },
       { from: 'Ember', subject: 'I hate you Angular!', date: 'Dec 8' }
    ];
}

Since each email corresponds to a row, we’ll do it at the row level. We'll use Angular's ng-click directive to call this function from each row, like so:

JavaScript
ng-click="showPopup()"

So that your <tr> tag looks like this:

HTML
<tr ng-repeat="email in emails" ng-click="showPopup()">

Now before this will work, we will have to do one more thing. If you remember from above ng-controller applies a controller to the element its on and child elements. Last time we placed it on the <table>, but since the modal HTML is outside that table we need to move this directive one level up to the container. Your container <div> should look like this:

HTML
<div class="container" ng-app ng-controller="EmailController">

Now you have a popup that appears when you click on an email. You will probably notice right away that there is no way to close it. Let's create another function called closePopup() that sets isPopupVisible to false. Then let's add an ng-click directive to the close button, the ×, and have the close button call that function.

Great, now we have a popup that opens and closes. Now let's get it to display the contents of the email. To accomplish that, we are going to have to modify showPopup() to include a parameter for us to specify the email we want to display. Then, we need to store that email in a variable and bind it to the popup. Finally, we need to pass the email to the function when the user clicks on the list.

So modify the function to look like this:

JavaScript
$scope.showPopup = function (email) {
    $scope.isPopupVisible = true;
    $scope.selectedEmail = email;
};

Then modify the markup for your modal to use the data from selectedEmail. It should change from this:

HTML
<div class="modal" ng-show="isPopupVisible">
    <div class="modal-header">
        <button type="button" class="close" ng-click="closePopup()">×</button>
        <h3>Subject</h3>
    </div>
    <div class="modal-body">
        <strong>From:</strong> Steve <br />
        <strong>Date:</strong> Jan 2 <br />
        <br />
        <p>
            Hey You, <br />
            <br />
            How you doing?<br />
            <br />
            Sincerely<br />
            Your Bro
        </p>
    </div>
    <div class="modal-footer">
        <a href="#" class="btn btn-primary" ng-click="closePopup()">Close</a>
    </div>
</div>

To this:

HTML
<div class="modal" ng-show="isPopupVisible">
    <div class="modal-header">
        <button type="button" class="close" ng-click="closePopup()">×</button>
        <h3>{{selectedEmail.subject}}</h3>
    </div>
    <div class="modal-body">
        <strong>From:</strong> {{selectedEmail.from}} <br />
        <strong>Date:</strong> {{selectedEmail.date}} <br />
        <br />
        <p>
            Hey You, <br />
            <br />
            How you doing?<br />
            <br />
            Sincerely<br />
            Your Bro
        </p>
    </div>
    <div class="modal-footer">
        <a href="#" class="btn btn-primary" ng-click="closePopup()">Close</a>
    </div>
</div>

Finally, change the call to showPopup() in the table to pass the email. Like so:

JavaScript
ng-click="showPopup(email)"

Your <tr> tag should look like this:

HTML
<tr ng-repeat="email in emails" ng-click="showPopup(email)">

Note that email is the name we assigned in ng-repeat. Now when you click on it, the popup will display the content of the email you clicked on.

The only thing we don't display is the email body. Let's do that now. Let's modify the array of emails to include an email body.

HTML
$scope.emails = [
    {
        from: 'John',
        subject: 'I love angular',
        date: 'Jan 1',
        body: 'hello world!'
    },
    {
        from: 'Jack',
        subject: 'Angular and I are just friends',
        date: 'Feb 15',
        body: 'just kidding'
    },
    {
        from: 'Ember',
        subject: 'I hate you Angular!',
        date: 'Dec 8',
        body: 'wassup dude'
    }
];

Now update the markup for the modal so that it displays that copy in the body of the modal.

Now we’re going to add functionality to compose an email. For our compose email popup, we will need 3 fields and 2 buttons. One field for the To address, another for Subject, and one for the body of the email. One button to send and another to cancel. Our HTML looks like this:

HTML
<div class="modal">
    <div class="modal-header">
        <button type="button" class="close"">×</button>
        <h3>Compose Email</h3>
    </div>
    <div class="modal-body">
        <form>
            <input type="text" placeholder="To" style="width:95%;"><br />
            <input type="text" placeholder="Subject" style="width:95%;"><br />
            <textarea style="width:95%;" rows="10"></textarea>
        </form>
    </div>
    <div class="modal-footer">
        <a href="#" class="btn">Close</a>
        <a href="#" class="btn btn-primary">Send</a>
    </div>
</div>

The output looks like this:

Image 10

As we’ve done before, we want to add a variable and some functions to control the visibility. Since we covered how to do this already, I won't dive into it here. In summary, we need to do the following:

  • Add the variable isComposePopupVisible to the controller
  • Create the function showComposePopup() that sets it to true
  • Create the function closeComposePopup() that sets it to false
  • Added ng-show="isComposePopupVisible" to the modal
  • Added ng-click="closeComposePopup()" to the × and the "Close" button
  • Added a compose button under the email list:
  • <button class="btn btn-primary">Compose</button>
  • Added ng-click="showComposePopup()" to the button

Now we want to capture the information that the user enters so we're going to bind the textboxes to the fields of an object. Similar to what we did with the email popup using the selectedEmail variable.

The difference is that with the email popup we used expressions, expressions are for rendering data. In this case, we are going to use the ng-model directive because it's a two-way binding. By that, I mean that if the user types in something into the input field we want the variable to automatically be updated. Likewise if the controller changes the value of one of the variables, then we want the inputs to automatically updated to reflect that.

To get started, add the composeEmail variable to the controller as an empty object, like so:

JavaScript
$scope.composeEmail = {};

Then update the HTML to bind to fields in this object, by adding ng-model="composeEmail.to" and ng-model="composeEmail.body" to the <input>s and <textarea> respectively. So it looks something like this:

HTML
<input type="text" placeholder="To" ng-model="composeEmail.to">
<input type="text" placeholder="To" ng-model="composeEmail.subject">
<textarea rows="10" ng-model="composeEmail.body"></textarea>

Now let's confirm this is actually binding by displaying an alert box with this information when the user clicks the "Send" button. So let's create a function in our controller, bind it to the "Send" button and have it display the values in the composeEmail variable. Your function should look like this:

JavaScript
$scope.sendEmail = function() {
    alert($scope.composeEmail.to
        + " " + $scope.composeEmail.subject
        + " " + $scope.composeEmail.body);
};

Now let's bind the "Send" button to it like so:

HTML
<br />
<a href="#" class="btn btn-primary" ng-click="sendEmail()">Send</a>

Now you can test it by clicking the "Compose" button, entering some information into the "To" and "Body" fields on the form and clicking "Send". You should see whatever you typed come up in the popup.

Now let's add a couple more things. The first thing we want to do is make the popup disappear. To do that, we’ll add $scope.isComposePopupVisible = false; to sendEmail(). Also, you will notice that if you click the "Compose" button again instead of it being empty, it has the information you entered the last time. Let's correct this by assigning an empty object to the composeEmail in the showComposePopup() function. When you are done, your functions should look like this:

JavaScript
$scope.sendEmail = function() {
    $scope.isComposePopupVisible = false;
    alert($scope.composeEmail.to
        + " " + $scope.composeEmail.subject
        + " " + $scope.composeEmail.body);
};

$scope.showComposePopup = function() {
    $scope.composeEmail = {};
    $scope.isComposePopupVisible = true;
};

So now let's do something a little more interesting than displaying an alert box. Normally emails you send out go into your "Sent" folder. Right now, we only have the equivalent of an inbox. First let's add a "Sent" folder and toggle between it and the "Inbox" using tabs.

Let's start with the HTML. Add the following HTML to the top of your container:

HTML
<ul class="nav nav-tabs">
    <li><a>Inbox</a></li>
    <li><a>Sent</a></li>
</ul>

It should look like this:

Image 11

Like everything else we've "angularized", we need a variable to keep track of which tab we're in. Let's call it activeTab, and by default let's set it to "inbox".

JavaScript
$scope.activeTab = "inbox";

Now let's change this variable when the user clicks on "Inbox" or "Sent". We can do that right inside ng-click, like this ng-click="activeTab='inbox'". So your HTML looks like this:

HTML
<ul class="nav nav-tabs">
    <li><a ng-click="activeTab='inbox'">Inbox</a></li>
    <li><a ng-click="activeTab='sent'">Sent</a></li>
</ul>

Now let's only display the current email list when the activeTab is "inbox" by using the ng-show directive like so:

JavaScript
ng-show="activeTab=='inbox'"

So far so good. Now when you click on the "Sent" tab, the email list disappears and when you click on "Inbox" it reappears.

Problem is you can't tell which tab is selected. Bootstrap has a way to make a tab look selected, it requires adding the active CSS class to the selected tab's <li> element. See http://getbootstrap.com/2.3.2/javascript.html#tabs.

So we need a way to add this class but only when the activeTab variable is set to the corresponding value. So the <li> for "Inbox" should have an active class only when activeTab is set to "inbox". For this, we use the ng-class directive. This directive takes an object, for each property in that object if the value is true it adds a class by that name.

For example in the following code, angular adds the active CSS class to the <li> element:

HTML
<li ng-class="{active: true}">Inbox</li>

The result is:

HTML
<li class="active">Inbox</li>

If the value were false, the class in this case would be empty. In our case, we want to replace true with the appropriate condition like so:

HTML
<li ng-class="{active: activeTab == 'inbox'}">Inbox</li>

Your final code should look something like this:

HTML
<ul class="nav nav-tabs">
    <li ng-class="{active: activeTab == 'inbox'}">
        <a ng-click="activeTab='inbox'">Inbox</a>
    </li>
    <li ng-class="{active: activeTab == 'sent'}">
        <a ng-click="activeTab='sent'">Sent</a>
    </li>
</ul>

And should look like this:

Image 12

Now the only thing left is to display the sent emails in the "Sent" tab. To do that, we essentially need to copy what we did for the inbox:

  • Create a variable in the controller called sentEmails assign it an empty array
  • Copy the HTML table for the email list
  • Change the ng-repeat to ng-repeat="email in sentEmails"
  • Change the ng-show condition to ng-show="activeTab=='sent'"
  • Change {{ email.from }} to {{ email.to }}

You can do a quick test by adding objects to the sentEmails array and confirm that they show up.

Now what we want to do now is add the sent email to this array. This part is purely JavaScript, we just use JavaScript's Array.push() function to add the composeEmail to the sentEmails array. Like so:

JavaScript
$scope.sentEmails.push($scope.composeEmail);

Also, we can use this opportunity to remove the alert, since we can now see sent emails in the "Sent" tab. YoursendEmail() function should look like this:

JavaScript
$scope.sendEmail = function() {
    $scope.isComposePopupVisible = false;
    $scope.sentEmails.push($scope.composeEmail);
};

So far so good. There are just a couple of things we can touch up. For example, after you send an email and go to the "Sent" tab, you will see the date column is blank. This is because the date field is not bound to anything on the form so it's not populated. This is as it should be because the date should be the date you sent the email not something the user specifies. Normally, this would be done on the server, for our purposes though since we don’t have a server portion yet we'll do this in the sendEmail() function. You can simply assign the date property directly like so:

JavaScript
$scope.composeEmail.date = new Date();

Now, if you test this by sending an email, you will notice another problem right away. The date looks something like this "2013-12-27T21:47:01.678Z". I don't like that, I want it to look like the dates in the inbox, but those dates were strings, not actual JavaScript date objects.

Luckily angular provides us with a way to format our expressions using something called "filters". In our case, we can fix how the date is displayed by changing this {{ email.date }} to this {{ email.date | date:'MMM d' }}. If you notice, what we did was add | date:'MMM d' to the end of the existing expression.

The vertical line, known as a pipe (|), is how you tell angular to run the data through a filter. The name of filter in this case is date, the colon (:) separates the filter from the parameter, and the string that follows tells the date filter how to format it. For the different ways you can format the date, see the Angular documentation: http://docs.angularjs.org/api/ng.filter:date http://jsfiddle.net/luisperezphd/UKYnz/.

Alright just a few more things to cleanup. For example, if you send an email and then click on it to see its content, the date on the popup is still ugly - missed a spot. The "From" field is blank because as in the case with the date, it’s something we have to assign when it’s sent. Finally, there is no "To" field. The solutions to these are the same as the issues we dealt with before so we know the solution:

  • Format the date using the filter by appending | date:'MMM d' at the end of the expression
  • Assigned $scope.composeEmail.from the value "me" in the sendEmail() function
  • Add "To" field and expression to the HTML
  • Assign "To" values to the sample emails in the controller

Now we are going to work on some of the remaining functionality to nicely round out the application, like forwarding and replying to emails. We are going to implement it by reusing the compose email functionality. I’ll go through it quickly since it’s pretty straight forward and we’re not introducing any new concepts.

First, we need to add the “Reply” and “Forward” buttons to the email details popup.

HTML
<a href="#" class="btn">Forward</a>
<a href="#" class="btn">Reply</a>

Should look like this:

Image 13

Then, we create the reply and forward functions on the controller:

JavaScript
$scope.forward = function() {
};

$scope.reply = function() {
};

Then, we bind those functions to the buttons.

HTML
<a href="#" class="btn" ng-click="forward()">Forward</a>
<a href="#" class="btn" ng-click="reply()">Reply</a>

Now we need to do the following:

  • Hide the view details popup
  • Populate the composeEmail object
  • How it’s populated depends on whether it’s a reply or a forward
  • Show the compose email popup

That’s it. Here is the commented reply() function:

JavaScript
$scope.reply = function() {
    // hide the view details popup
    $scope.isPopupVisible = false;
    // create an empty composeEmail object the compose email popup is bound to
    $scope.composeEmail = {};
    // copy the data from selectedEmail into composeEmail
    angular.copy($scope.selectedEmail, $scope.composeEmail);

    // edit the body to prefix it with a line and the original email information
    $scope.composeEmail.body =
        "\n-------------------------------\n"
        + "from: " + $scope.composeEmail.from + "\n"
        + "sent: " + $scope.composeEmail.date + "\n"
        + "to: " + $scope.composeEmail.to + "\n"
        + "subject: " + $scope.composeEmail.subject + "\n"
        + $scope.composeEmail.body;

    // prefix the subject with "RE:"
    $scope.composeEmail.subject = "RE: " + $scope.composeEmail.subject;
    // the email is going to the person who sent it to us
    // so populate the to with from
    $scope.composeEmail.to = $scope.composeEmail.from;
    // it’s coming from us
    $scope.composeEmail.from = "me";
    // show the compose email popup
    $scope.isComposePopupVisible = true;
};

When you click “Reply”, the compose window should look like this:

Image 14

The forward() is practically identical to this, the only difference is that the subject is prefixed with “FW:“ instead of “RE:” and to is blank instead of the sender.

If you run this now, you will notice 2 things. One, in the "Sent" tab, the emails are listed from top down in the order they were sent. We want to display this in the reverse order so the last email you sent shows up at the top. To do that, we can change the line of code that adds composeEmail to the sentEmails array. Instead of using push() to add the email to the end of the array, we will use splice() to add it to the beginning. Like so:

JavaScript
//$scope.sentEmails.push($scope.composeEmail); // OLD
$scope.sentEmails.splice(0,0,$scope.composeEmail); // NEW

Also, if you open up one of the sent emails with all the new added text you will see that all the text runs into each other, no line breaks. We can fix this with a little CSS. We’ll use inline CSS just this once. We’ll wrap the body of the email around a <span> tag and set the CSS white-space property to pre. This tells the browser to honor line breaks. Like so:

HTML
<span style="white-space:pre">{{selectedEmail.body}}</span>

In terms of UI, our app is now fairly complete. But before it can be a real app, it has to be able to talk to a server to do the actual work of sending and storing emails. That’s what we’re going to do in this post.

Now the first thing I have to do is setup the server portion. I purposely left this post for last because I wanted you to be able to try out the Angular code without forcing you to setup a local development environment. Also, I wanted it to be useful for everyone no matter what server technology they used - PHP, .NET, Node.js, etc.

Obviously, I won’t be able to do past this point. After all, I can’t show you how to communicate with a server without a server, and that means I have to pick a technology. I’m going to use ASP.NET MVC. I will also do my best to describe the server portion in enough detail so that it’s also useful to you regardless of what server technology you use.

ASP.NET MVC Primer

A very quick primer for those not familiar with ASP.NET MVC. In this type of web application, URLs are mapped to classes and methods. For example, if a user entered the URL http://localhost/Home/Index in their web browser that would trigger the method Index() in the class HomeController to run.

That method can choose whether to return data or HTML. The HTML is stored in a separate file referred to as a view. These views have the extension .cshtml. Similar to the controller, the proper view is selected based on the URL, once again for the URL http://localhost/Home/View, it will use the view stored in the folder\Views\Home\Index.cshtml.

Of course I’m simplifying things, but this explanation should suit our purposes.

Back to the App

To start we need to create an ASP.NET MVC project in Visual Studio. I chose to start with an empty project and added a controller class called HomeController. And an action method called Index. In my view I include the CSS, JavaScript, and HTML I mentioned at the beginning.

Now let’s update the app so that we get the email list from the server instead of hardcoding it in the JavaScript. First, we’ll create the method on the ASP.NET controller:

C#
public ActionResult GetEmails()
{
    return Json(new[] {
        new {
            from = "Riker",
            to = "me",
            subject = "Nice to meet you, Pinocchio",
            date = "Jan 8",
            body = "That and helping Data finish 'Pop Goes the Weasel'. Also counts as a CMOH."
        },
        new {
            from = "Picard",
            to = "me",
            subject = "I'm sorry, this is becoming a speech",
            date = "Jan 7",
            body = "But then I'm entitled, I'm the captain."
        },
        new {
            from = "Data",
            to = "me",
            subject = "Could you please continue...",
            date = "Jan 6",
            body = "...the petty bickering? I find it most intriguing."
        },
        new {
            from = "Troi",
            to = "me",
            subject = "But you spell knife with a 'k'",
            date = "Jan 5",
            body = "I spell 'knife' with an 'n', but then I never could spell."
        },
    });
}

In this example, we’re returning a static list of emails. We’re using the Json() method to tell ASP.NET to return this data back to the browser as JSON.

Now, we’re going to replace the hardcoded list in our JavaScript with a call to this action. The JavaScript is in the view along with our HTML (/Views/Home/Index.cshtml). So replace this:

JavaScript
$scope.emails = [
    {
        from: 'John',
        to: 'me',
        subject: 'I love angular',
        date: 'Jan 1',
        body: 'hello world!'
    },
    {
        from: 'Jack',
        to: 'me',
        subject: 'Angular and I are just friends',
        date: 'Feb 15',
        body: 'just kidding'
    },
    {
        from: 'Ember',
        to: 'me',
        subject: 'I hate you Angular!',
        date: 'Dec 8',
        body: 'wassup dude'
    }
];

With this:

JavaScript
$http.post("/Home/GetEmails").then(function(response) {
    $scope.emails = response.data;
});

Finally, we need to add $http as a parameter in our Angular controller, like we did with $scope. So your controller method should be changed from this:

JavaScript
EmailController($scope)

to this:

JavaScript
EmailController($scope, $http)

That’s it, if you compile and run this, you should see your email list change.

One down and one to go. Sending email is going to be very similar, the main difference is that we didn’t pass any data to GetEmails() but we need to pass information about the email we’re sending to SendEmail().

This method is going to be simple. All the server is going to do is populate the date and from fields of the email and send that information back to Angular. To accomplish this, we are going to need two things. We need to add an action to our ASP.NET controller and a C# class to hold the data Angular is sending.

Let’s start with the C# class. It should contain all the same fields found in the JavaScript code. For our purposes, you can put this class anywhere. In order to simplify things and keep all the code in one place, I’m adding it as a nested class inside the controller:

C#
public class ComposeEmail
{
    public string from { get; set; }
    public string to { get; set; }
    public string subject { get; set; }
    public string date { get; set; }
    public string body { get; set; }
}

Now for the ASP.NET action method itself:

C#
public ActionResult SendEmail(ComposeEmail composeEmail)
{
    composeEmail.from = "me";
    composeEmail.date = DateTime.Now.ToString("MMM d");

    return Json(composeEmail);
}

Finally, the call from Angular. Change the sendEmail() method from this:

JavaScript
$scope.sendEmail = function () {
    $scope.isComposePopupVisible = false;
    $scope.composeEmail.from = "me";
    $scope.composeEmail.date = new Date();
    $scope.sentEmails.splice(0, 0, $scope.composeEmail);
};

To this:

JavaScript
$scope.sendEmail = function () {
    $http.post("/Home/SendEmail", $scope.composeEmail).then(function (response) {
        $scope.isComposePopupVisible = false;
        $scope.composeEmail = response.data;
        $scope.sentEmails.splice(0, 0, $scope.composeEmail);
    });
};

That’s it! If you run your code now, send an email and check the “Sent” tab, you will see that the date is populated. If you click to open that email, you will see that the “from” field is populated as well.

This covers the essentials of AngularJS and everything you need to start creating a simple functional web application. In this series, you created a fairly elaborate UI with multiple screens that update dynamically. To make it functional, you communicated with a backend server to do the work.

We’re just scratching the surface of what’s possible with AngularJS.

License

This article, along with any associated source code and files, is licensed under The Code Project Open License (CPOL)


Written By
Technical Lead
United States United States
Long time software developer 20+ years and blogger at "Simply Good Code"

For the last several years I've worked on developing salable SaaS products using .NET technologies. I'm always trying out new technologies and looking for ways to improve applications and develop them faster.

My favorite programming languages are C#, JavaScript, and HTML. But really I'm interested in anything and everything programming. My favorite thing is to take an application from concept to completion.

If you like my article and would like to be notified of new posts you can sign up for my mailing list just visit my blog www.simplygoodcode.com

Comments and Discussions

 
Questionsources of example Pin
kivadim17-May-16 3:35
kivadim17-May-16 3:35 
AnswerRe: sources of example Pin
Luis Perez ----- (Simply Good Code)6-Aug-16 17:28
Luis Perez ----- (Simply Good Code)6-Aug-16 17:28 
QuestionVery Good Article Pin
rjvenugopal22-Aug-15 21:23
rjvenugopal22-Aug-15 21:23 
GeneralMy vote of 1 Pin
praveenchouhan5715-May-15 0:11
praveenchouhan5715-May-15 0:11 
SuggestionWeb API Pin
tatran.eu@gmail.com28-May-14 11:14
tatran.eu@gmail.com28-May-14 11:14 
GeneralMy Vote of 5 - This is Awesome Pin
scallan13-May-14 14:17
scallan13-May-14 14:17 
GeneralMy vote of 5 Pin
Renju Vinod10-Feb-14 17:21
professionalRenju Vinod10-Feb-14 17:21 
Nice
QuestionFrankie Pin
FranksLIC5-Feb-14 13:06
FranksLIC5-Feb-14 13:06 
GeneralMy vote of 5 Pin
J Atkinson30-Jan-14 22:56
J Atkinson30-Jan-14 22:56 
GeneralMy vote of 5 Pin
M Rayhan30-Jan-14 19:11
M Rayhan30-Jan-14 19:11 
GeneralMy vote of 5 Pin
Humayun Kabir Mamun30-Jan-14 18:14
Humayun Kabir Mamun30-Jan-14 18:14 

General General    News News    Suggestion Suggestion    Question Question    Bug Bug    Answer Answer    Joke Joke    Praise Praise    Rant Rant    Admin Admin   

Use Ctrl+Left/Right to switch messages, Ctrl+Up/Down to switch threads, Ctrl+Shift+Left/Right to switch pages.