Creating our Add-Edit view

Now that we have the controller in place, let’s work on the form to add and edit the page content.

Create a new file at angcms/public/partials/add-edit-page.html, and add the following content:

<h1>{{heading}}</h1>
<hr/>

<form role="form" id="add-page" ng-submit="savePage()">
<div class="form-group">
<label>Page ID</label>
<input class="form-control" type="text" readonly ng-model="pageContent._id"/>
</div>
<div class="form-group">
<label>Page Title</label>

<input class="form-control" type="text" ng-model="pageContent.title"/>
</div>
<div class="form-group">
<label>Page URL Alias</label>
<input class="form-control"type="text" ng-model="pageContent.url"/>
</div>

<div class="form-group">
<label>Menu Index</label>
<input class="form-control"type="number" ng-model="pageContent.menuIndex"/>
</div>

<div class="form-group">
<label>Page Content</label>
<textarea rows="15" class="form-control" type="text" ng-model="pageContent.content"></textarea>
</div>
<input type="submit" class="btn btn-success" value="Save">
</div>
</form>

Test the add page to ensure that it’s working.

Writing a custom filter to autogenerate the URL field

Most CMS tools would autogenerate the URL alias based on the title of the page. While doing this, we will need to ensure that the alias being generated is stripped out of any special characters and all spaces are ideally replaced by a dash.

We will do this by creating our own custom filter.

Open up the angcms/public/js/filters.js file, and add the following code.

'use strict';

/* Filters */

angular.module('myApp.filters', [])
  .filter('formatURL', [
    function() {
      return function(input) {
        var url = input.replace(/[`[email protected]#$%^&*()_|+-=?;:'",.<>{}[]/]/gi, '');
        var url = url.replace(/[s+]/g, '-');
        return url.toLowerCase();

      };
    }
  ]);

Here, we are basically creating a filter called formatURL and taking in the input parameters. We first remove any special characters that may be present using regex. We then replace all spaces with a hyphen and return the formatted string in lowercase.

Now, let’s see how to use it in our code. We will use this filter in our controller, so let’s make the highlighted changes in our controller file located at angcms/public/js/controlllers.js:

.controller('AddEditPageCtrl', ['$scope', '$log', 'pagesFactory', '$routeParams', '$location', 'flashMessageService','$filter',
    function($scope, $log, pagesFactory, $routeParams, $location, flashMessageService,$filter) {

As you can see, we are injecting the $filter module into our controller.

Next, we create a $scope function as follows:

$scope.updateURL=function(){
  $scope.pageContent.url=$filter('formatURL')($scope.pageContent.title);
}

Within the update URL function, we store the value into the pageContent.url property by using the formatURL filter and passing $scope.pageContent.title as an argument to it.

Next, we need to make the highlighted changes to our partial located at angcms/public/partials/admin/add-edit-page.html, as highlighted:

<label>Page Title</label>
<input class="form-control" type="text" ng-change="updateURL()" ng-model="pageContent.title"/>
</div>
<div class="form-group">
<label>Page URL Alias</label>
<input class="form-control"type="text" readonly ng-model="pageContent.url"/>
</div>

Save the files and test the add-edit page in the browser. Notice the URL field getting updated automatically as you enter the title field.

Adding the WYSIWYG editor

Most CMS tools would have a What You See Is What You Get (WYSIWYG) editor. This allows the content administrators to easily format the text on a page, for example, add headings, make the text bold or italics, add numbering bullets, and so on.

We’ll see how to add TinyMCE, a very popular WYSIWYG editor, to our page content text area.

Angular UI has a ready-to-use module, which makes it very easy to add TinyMCE to any form in an angularjs app.

The Angular-UI TinyMCE wrapper can be downloaded from GitHub at https://github.com/angular-ui/ui-tinymce.

Alternatively, we can also use bower to download the files.

Assuming that you have already installed bower, run the following command in the terminal;

bower install angular-ui-tinymce --save

This will create a folder called bower_components and download the files within it.

Next, let’s include these libraries in our index.html file, as highlighted in the following code:

<script type="text/javascript" src="bower_components/tinymce/tinymce.min.js"></script>
<script type="text/javascript" src="lib/angular/angular.js"></script>
<script type="text/javascript" src="bower_components/angular-ui-tinymce/src/tinymce.js"></script>
<script src="lib/angular/angular-route.js"></script>

Next, we will add the TinyMCE module as a dependency to our app in the angcms/public/js/app.js file, as highlighted in the following code:

angular.module('myApp', [
    'ngRoute',
    'myApp.filters',
    'myApp.services',
    'myApp.directives',
    'myApp.controllers',
    'ui.tinymce',
    'ngCookies',
    'message.flash'
]).

This is all that is required to include TinyMCE in our angularjs app.

Now, to add the editor to our angcms/public/partials/admin/add-edit-page.html file, we will simply call our directive, as highlighted in the following code:

<textarea ui-tinymce rows="15" class="form-control" type="text" ng-model="pageContent.content"></textarea>

Save the file, and now, try to add or edit a page to notice TinyMCE replace the text area.

Setting up an Interceptor to detect responses

A use case that we need to consider is what happens if the backend web service’s session timed out and somebody from the frontend is trying to add, edit, or delete a page.

At the instance when the backend service times out, it would return a 401 status code; we would need to have every angularjs controller check for this status code and redirect the user to the login page in case it gets one.

Instead of writing this check on each and every controller, we will make use of an Interceptor to check every incoming response, and act accordingly.

Let’s chain our Interceptor service in our services.js file as follows:

.factory('myHttpInterceptor', ['$q', '$location', function($q, $location) {
    return {
        response: function(response) {
            return response;
        },
        responseError: function(response) {
            if (response.status === 401) {
                $location.path('/admin/login');
                return $q.reject(response);
            }
            return $q.reject(response);
        }
    };
}]);

The next step is to push this into $httpProvider.

We will add the following code to our angcms/public/js/app.js file:

.config(function ($httpProvider) {
    $httpProvider.interceptors.push('myHttpInterceptor');
});

To test whether our Interceptors are working or not, open up a new tab in the browser in Incognito or private browsing mode and try to directly put in the URL to edit a page; it would be something like http://localhost:3000/admin/add-edit-page/<_id>.

It should automatically redirect you to the login page.