Angularjs example MotoAds more advanced directive

Another thing we will add to MotoAds demo application is a feature which allows us to comment each advert. A good idea would be to realize this as AngularJS directive. It will look like in the picture below. We can see all added comment to advert, click on Comment link activate the comment form with Preview, Send and Cancel buttons.

The comment form we will realize as AngularJS directive. Before we start let's look at changed adverts.json, there is the additional comments field (array of comments):
[
  {
    "brandName": "Audi",
    "modelName": "A1",
    "year": 2011,
    "price": 35000,
    "imageUrl": "img/audi_a1_1.jpg",
    "countryName": "Germany",
    "regionName": "Bavaria",
    "comments" : [
      "This car is awesome I want it\nBeatiful color\nFunny look",
      "Very cool vehicle\nJust perfect"
    ]
  }
]
]]>

Step 1
We create commenForm.html template which we use in directive: <div class="ma-advert-comment-form"> <form name="commentForm" novalidate> <div ng-hide="previewModeOn"> <textarea ng-model="content" placeholder="Write a comment..."></textarea> </div> <div class="ma-advert-comment-preview" ng-show="previewModeOn" ng-bind-html="preview | newlines"></div> <div class="control-group"> <div class="controls"> <button ng-click="togglePreviewMode()" ng-disabled="isUnchanged()" class="btn btn-info btn-small">{{ previewModeOn && 'Edit' || 'Preview' }}</button> <button ng-click="sendCommentForm()" ng-disabled="isUnchanged()" class="btn btn-success btn-small">Send</button> <button ng-click="closeCommentForm()" class="btn btn-small">Cancel</button> </div> </div> </form> </div>
Step 2
We in directives.js we create AngularJS directive:
motoAdsApp.directive('commentForm', function(Advert) {
  return {
    restrict: "E",
    replace: true,
    scope: {
      commentModeOn: '=',
      advertId: '='
    },
    templateUrl: "views/commentForm.html",
    link: function(scope, element, attrs) {
      scope.content = '';
      scope.previewModeOn = false;

      scope.closeCommentForm = function() {
        scope.previewModeOn = false;
        scope.commentModeOn = false;
      };

      scope.isUnchanged = function() {
        return angular.isUndefined(scope.content) || angular.equals(scope.content, '');
      };

      scope.togglePreviewMode = function() {
        scope.preview = scope.content;
        scope.previewModeOn = !scope.previewModeOn;
      };

      scope.sendCommentForm = function() {
        var advert = Advert.get({advertId: scope.advertId}, function() {
          advert.comments.push(scope.content);
          Advert.update(advert, function() {
            scope.closeCommentForm();
            scope.$parent.advert.comments.push(scope.content);
            scope.content = '';
          });
        });

        scope.preview = scope.content;
        scope.previewModeOn = true;
      };
    }
  };
});
]]>

Step 3
We add simple CommentController into controllers.js:
motoAdsApp.controller('CommentController', ['$scope',
  function($scope) {
    $scope.commentModeOn = false;
    
    $scope.isAnyComment = function() {
      return ($scope.advert.comments.length > 0);
    };
  }]);

Step 4
We add simple newlines filter into filters.js:
motoAdsApp.filter('newlines', function() {
  return function(text) {
    if (text) {
      return text.replace(/\n/g, '<br/>');
    }
    return text;
  };
});

Step 5
We comment-form directive into adverts.html and some additional code to list comments and activate the comment form: <table class="ma-advert-table"> <thead> <tr class="ma-advert-table-headers"> <th>Image/Country/Region</th> <th>Brand</th> <th>Model</th> <th>Year</th> <th>Price ($)</th> <th>Operation</th> </tr> </thead> <tbody ng-controller="CommentController" ng-repeat="advert in adverts"> <tr class="ma-advert-table-row"> <td><a href="#/"><img class="img-rounded" ng-src="{{advert.imageUrl}}"></a><br/> <span>{{advert.countryName}}, {{advert.regionName}}</span></td> <td>{{advert.brandName}}</td> <td>{{advert.modelName}}</td> <td>{{advert.year}}</td> <td>{{advert.price}}</td> <td> <input type="hidden" value="{{advert._id}}"> <a href="" ng-click="editAdvert(advert._id)">Edit</a> <br/><a href="" ng-click="removeAdvert($index)">Remove</a> <br/><a href="" ng-click="commentModeOn = true">Comment</a></td> </tr> <tr class="ma-advert-comment-list-row" ng-show="isAnyComment()"> <td colspan="6"> <div class="ma-advert-comment-title">Comment(s):</div> <div class="ma-advert-comment-list" ng-repeat="comment in advert.comments"> <div class="ma-advert-comment" ng-bind-html="comment | newlines" /> </div> </td> </tr> <tr class="ma-advert-comment-form-row" ng-show="commentModeOn"> <td colspan="6"> <comment-form comment-mode-on="commentModeOn" advert-id="advert._id" /> </td> </tr> </tbody> </table> If you want to run this example on your computer, you can download sources from GitHub.

Any comment would be highly appreciated.

Komentarze

Popularne posty z tego bloga

AngularJS example MotoAds more advanced than the tutorial on angularjs.org

Java ESL program for connecting to the FreeSWITCH

Java program for connecting to the FreeSWITCH XML-RPC