How to make an email web app using Angular (Part II)

In the first post of this series we created a table and made it data driven. In that simple example we touched on several concepts including expressions, directives, scope, and controller. We used the directives ng-app, ng-controller, ng-repeat, and ng-init.

In this post we will add the ability to click on an email and see it’s content. Just as in the last post we are going to start with the static HTML and move on to add functionality to it using Angular.

We are going to use Bootstraps standard modal HTML to create the email popup. To do that we are going to add the following HTML under your table:

<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 get a popup above your table that looks like this: http://jsfiddle.net/luisperezphd/6eKzx/

modal
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 it’s 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:

$scope.isPopupVisible = false;

Your controller should look something like this:

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 and bind it to that variable. To do that add the following directive to your div with the modal class:

ng-show="isPopupVisible"

It should look like this:

<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 list. First let’s create a function that sets that variable to true, let’s call it showPopup(), like so:

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

Your controller should now look like this:

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 let’s do it at the row level. We’ll use use Angular’s ng-click directive, like so to call this function from each row:

ng-click=”showPopup()”

So that your <tr> tag looks like this:

<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 the last post ng-controller applies a controller to the element it’s own and it’s child elements. In the last post we placed it on the <table>, but since the modal HTML is outside that table we need to move this directive on level up to the container. Your container <div> should look like this:

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

There now you have a popup that comes up when you click on an email: http://jsfiddle.net/luisperezphd/T5txH/

You will probably notice right away that there is no way to close it. Let’s fix that. Let’s create another function called closePopup() that sets isPopupVisible to false. Then let’s add an ng-click directive to the × and the close button that calls that function. Do that and you should get this: http://jsfiddle.net/luisperezphd/wLA78/

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 pass the email we want to display. Then we need to store that email in a variable and bind to the popup. And 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:

$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:

<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:

<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:

ng-click="showPopup(email)"

Your <tr> tag should look like this:

<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: http://jsfiddle.net/luisperezphd/hLgjd/

The only thing we don’t display is the email body, that’s because we hadn’t created that data. Let’s do that now. Let’s modify the array of emails to include an email body.

$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: http://jsfiddle.net/luisperezphd/Z2xuh/

In the next post we will add functionality to compose an email.

How to make an email web app using Angular (Part III)

Comments

Leave a Reply

Your email address will not be published. Required fields are marked *