5

My application is using Angularjs at client side. I have five directive which are using same logic. Following are required details of my code

  1. I have one pure javascript class as AppUtilities.js having following method defined

    var AppUtilities = {
      //Get the guid for given collection
      getGUID: function (collectionName) {
          var prefix;
          var guid;
          //get first two character
          if (!Utilities.isEmpty(collectionName)) {
             prefix = collectionName.substring(0, 2);
             //Get timestamp
             var timestamp = Utilities.getTimestampId();
             //concate prefix to get the guid
             guid = prefix + timestamp;
          }
          return guid;
      }
    };
    
  2. I have five different directive in which I need to use "getGUID()" method to bind with template. Since template is only able to bind with scope function therefore I have defined scope method in all these five template as below

    scope.getGUID = function (collectionName) {
      return AppUtilities.getGUID(collectionName);
    }
    
  3. Then in all the five directive template, this method is bind as scope variable

    <h4 class="guid" id="guid" data-ng-bind-template="{{getGUID('goal')}}"></h4>
    

How can I avoid declaring these method as scope variable and directly use as AppUtilities.getGUID(collectionName) in the HTML template?

3
  • put AppUtilities in rootScope Commented May 26, 2015 at 6:38
  • With filters, which are usable in all templates once defined, you could use {{ 'goal'|getGUID }}. No scope vars, no manipulation of $rootScope. Commented May 26, 2015 at 6:55
  • create a service and put this method inside a service..then you need to do $scope.AppUtilities = AppUtilities to make it available in scope/html Commented May 26, 2015 at 6:55

3 Answers 3

2

There are multiple ways, but honestly, it seems like more effort than its worth, since you can just do:

scope.getGUID = AppUtilities.getGUID;

Of course, you could use $rootScope, but to me personally it feels wrong - I like when things are explicitly declared and do not magically appear.

Alternatively, if you only need to render the GUID in the UI, create a GUID directive. For example:

.directive("guid", function(){
  return {
    template: "<span>{{getGUID()}}</span>",
    link: function(scope, element, attrs){
       scope.getGUID = function(){
         return AppUtilities.getGUID(attrs.guid || attrs.name);
       };
    }
  }
});

and use as:

<h4 class="guid"><guid name="goal"></guid></h4>
Sign up to request clarification or add additional context in comments.

4 Comments

your solution is cool..still thinking creating service would be an better option too..
@pankajparkar, well, that's what I suggested as well as a first option
Great..That perfect one +1.. I also suggested the same in comments
Yeah, I saw... but I wanted to give the OP another potential option
2

Without manipulating the individual scopes or the root scope, you could simply define a filter which is usable in all templates. Note that, for all the good reasons, I'd still define and inject AppUtilities, even if it is a global, as it's own service.

app.filter('toGUID', ['AppUtilities', function (AppUtilities) {
  return function (input) {
    return AppUtilities.getGUID(input);
  };
}]);

// <pre>{{ 'goal'|toGUID }}</pre>

app.service('AppUtilities', function () {
  return AppUtilities;
});

(function (app, ng) {
  'use strict';

  app.filter('toGUID', ['AppUtilities', function (AppUtilities) {
    return function (input) {
      return AppUtilities.getGUID(input);
    };
  }]);
  
  app.service('AppUtilities', function () {
    return AppUtilities;
  });

  var Utilities = {
    isEmpty: function (collectionName) {
      return false;
    },
    getTimestampId: function () {
      return '_something';
    }
  };

  var AppUtilities = {
    //Get the guid for given collection
    getGUID: function (collectionName) {
      var prefix;
      var guid;
      //get first two character
      if (!Utilities.isEmpty(collectionName)) {
        prefix = collectionName.substring(0, 2);
        //Get timestamp
        var timestamp = Utilities.getTimestampId();
        //concat prefix to get the guid
        guid = prefix + timestamp;
      }
      return guid;
    }
  };

})(angular.module('app', []), angular);
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.4.0-rc.2/angular.min.js"></script>

<div data-ng-app="app">
  <pre>{{ 'goal'|toGUID }}</pre>
</div>

Comments

0

Hide it in a div:

<div id="hidden" data-ng-model="hidden" style="display:none"></div>
<script>
$('#hidden').html(AppUtilities.getGUID(collectionName));
</script>

Then, ng-bind to the div's contents:

<div id="realDiv" data-ng-bind-html="hidden"></div>

2 Comments

i think it's not a good solution according to angularjs way of doing thinks ( avoid the use of jquery as possible )
the question specifically states "avoid declaring these method as scope variable". everyone else here was like, uh nope. i'm simply answering the question.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.