Adding Messaging to City Saves

In order to provide a better user experience, we will add messaging to the "save city" button to indicate that the city has been successfully saved. In order to do that, we will need to make changes to the app/views/current.html template and the app/scripts/controllers/current.js file.

How ngMessages works

The ngMessages directive is a powerful tool for making different messages appear on the page. It allows you to define a set of messages in your template using HTML markup so you can style them and present them exactly as you wish. Then, in your controller, you only need to set up a Javascript object to trigger the messages.

This mechanism is supported by built in features of AngularJS, such as form validation that happens automatically based on HTML form configuration. But we can also use it however we want by setting up some simple message objects in our controllers.

We will step through the process of adding messages to the "save city" feature we created.

Create an object to control our messages

In order to know whether or not to show a message, the ngMessages directive expects to receive an object it can parse that contains boolean values (true/false). We can create this object in the function where we save the city to localStorage.

Make the following changes to CurrentCtrl in the file app/scripts/controllers/current.js:

$scope.saveCity = function(city){
    var cityData = {
        'name': city.name,
        'id': city.id
    };
    if (!$localStorage.savedCities){
        $localStorage.savedCities = [cityData];
    } else {
        // Check to make sure we haven't already saved the city.
        var save = true;
        for (var i=0; i < $localStorage.savedCities.length; i++){
            if ($localStorage.savedCities[i].id === cityData.id) {
                // this is a duplicate, so don't save
                save = false;
            }
        }
        if (save===true){
            $localStorage.savedCities.push(cityData);
            // Add object to trigger messages
            $scope.citySaved = {
                'success': true
            };
        } else {
            console.log('city already saved');
            // Add object to trigger messages
            $scope.citySaved = {
                'duplicate': true
            };
        }
    }
};

As you can see, the code above is for the saveCity() function, which expects to receive a city object and then saves that city into the $localStorage.savedCities array. We can easily define the $scope.citySaved object as part of this function. In the case where we save a new city, we set the $scope.savedCity.success value to true. In the case where the user has attempted to save a duplicate city, we set $scope.savedCity.duplicate to true.

These values will be interpreted by the ng-messages directive in our template so our messages can be shown at the proper time.

Adding messages to the view template

Now that we have the $scope.savedCity value defined properly in our controller, we can add the following markup to the app/views/current.html template:

<div ng-messages="citySaved">
    <p class="city-saved-alert bg-success text-success" ng-message="success">
        {{currentWeather.name}} has been saved to your list of cities.
    </p>
    <p class="city-saved-alert bg-warning text-warning" ng-message="duplicate">
        {{currentWeather.name}} has already been saved to your list of cities.
    </p>
</div>

The code above sets up our messages to be controlled by the $scope.citySaved object. First, we create a container <div> element, and we give it the ng-messages attribute. We set ng-messages="citySaved", which tells the ng-messages directive to inspect the $scope.citySaved value in order to determine which messages below should be shown.

Within the <div> that contains our messages, we have defined <p> tags that possess the ng-message attribute. The first message, which is our "success" message, is triggered when $scope.citySaved.success is true. If that value is not true, then that message will not show.

Similarly, the second message is controlled by the value of $scope.citySaved.duplicate. If that value is true, then the message will be shown. If not, then it will be hidden.

Notice that the functionality of messages doesn't care about what classes, content, or HTML structures you have in your messages. Although the messages must be contained within an element that has the ng-messages attribute, you are otherwise free to create whatever HTML structure and assign whatever styles you wish. In this example, we are using default Bootstrap CSS styles to give the messages a "success" and "warning" look.

Try it out

Success!

If you've successfully implemented these changes to the respective files, you should be able to test it out. Click into the current weather for a city and click the "save city" button. You should see one of these messages appear. Search, view and save a few cities to get an idea of how much this improves your app. Contemplate all the different things you could do with styling to improve the look and feel of these messages. Once again, there are many possibilities to explore here. Have fun and experiment.

results matching ""

    No results matching ""