If you've been keeping up to date on the RhoMoible blogs, then you've seen the recent post about all the benefits of using Ionic in your RhoMobile application. A big part of what makes Ionic so extraordinary is that it is built on top of AngularJS.


While many developers know about the power of AngularJS and its data-binding abilities, few might know about Angular's impressive finer points: directives and services. Directives are one of Angular’s most overlooked, yet most powerful features.

 

What is a Directive?

At its most basic level, a directive is a marker on a DOM element (an attribute, element name, comment, or CSS class) that tells the Angular compiler in your HTML to attach a specified behavior to the marked DOM element. This allows you to take a lot of repetitive code out of your HTML files. You can name your directives based on their purpose, such as “displayImages” or “showWeeklyWeather.” This gives the added bonus of making your code clearer and easier to read.


On top of this, Angular lets you have custom directives and create your own reusable functionality. This is where Angular directives really shine.


Below is a custom Directive that changes the background color of “Hello World” to match the color in the input box.



HTML Code:


<html>

  <head>
    <meta charset="utf-8" />
    <script data-require="angular.js@1.2.x" src="http://code.angularjs.org/1.2.7/angular.js" data-semver="1.2.7"></script>
    <script src="js/app.js"></script>
  </head>


  <body ng-controller="MainCtrl" ng-app="myapp">
  <input type="text" ng-model="color" placeholder="Enter a color" />
  <hello-world/>
</body>
</html>










JavaScript Code:


var app = angular.module('myapp', []);


app.controller('MainCtrl', function($scope) {
  $scope.name = 'World';
});


app.directive('helloWorld', function() {
  return {
    restrict: 'AE',
    replace: true,
    template: '<p style="background-color:{{color}}" >Hello World </p>',
    link: function(scope, elem, attrs) {
      elem.bind('click', function() {
        elem.css('background-color', 'white');
        scope.$apply(function() {
          scope.color = "white";
        });
      });
      elem.bind('mouseover', function() {
        elem.css('cursor', 'pointer');
      });
    }
  };
});









This might look light a bit of code, but if you want this functionality in multiple places on a web page, all you have to do is drop the hello world directive into the HTML “<hello-world/>” and watch the magic happen.


The “restrict” and “replace” properties from the code above are optional.


Restrict lets your HTML know how you are going to reference your directives and can be set to:

'A' - only matches attribute name

'E' - only matches element name

'C' - only matches class name

or any combination of the above:

'AEC' - matches either attribute or element or class name

If you don’t set restrict to anything, its default status will be 'AE'.


“Replace: true” means that the content of the directive template will replace the element that the directive is declared on, in this case, the </hello-world> tag.


Another important thing to notice in the code above is that the directive is named “helloWorld” in the JavaScript file, but is referenced as “hello-world” in the HTML code. This is not a typo; your HTML file knows that hello-world = helloWorld. It is important to follow this pattern as HTML files expect “snake-case” variables and JavaScript files expect “camelCase” variables.


There’s a lot of potential in custom directives and they are becoming increasingly popular.


Angular Google Maps is a great example of how to take advantage of custom-made directives. Angular Google Maps is a set of directives (part of angular-ui) written in CoffeeScript and JavaScript which integrate Google Maps in an AngularJS application. There are directives for most of the widely-used Google Maps objects, including markers, windows, lines and shapes, and coming up is integration with more layer objects, including the HeatMap.


Screen Shot 2015-07-30 at 3.52.27 PM.png


UI-Bootstrap is a useful directive that comes with many of the great Bootstrap features that you’ve grown to love, but without any dependency on jQuery or Bootstrap’s JavaScript. Bootstrap offers a powerful set tools that can take you far and wide. (The website below was created with Bootstrap)


Screen Shot 2015-07-30 at 3.57.04 PM.png


Check out more of the gorgeous designs people have created.


If you are in the market for more basic features, UI-Calendar lets you implement a fully functioning Arshaw FullCalendar or UI-Router, which provides many routing options that don’t inherently come with Angular.


Screen Shot 2015-07-30 at 4.06.53 PM.png


Whatever you need, there’s probably a directive for that


Directive Deep Dive

The Ionic blog post touched on earlier had a great feature where a user's profile would load with a generic profile picture and then clicking on the picture would let you use RhoMobile's Camera API to open your device's camera and take a new profile picture.


Screen Shot 2015-07-30 at 4.29.59 PM.png


This feature will come in handy, so let's turn it into a directive for future use.


.directive("profileDirective", function() {
    return {
        restrict: "AEC",
        template: '<div class="item item-image" ng-click="takePicture()"> <img ng-src={{dataUriModel}}> <div/>',
        link: function(scope, element) {
          scope.dataUriModel = "data:image/svg+xml;base64,PD94bWwgdmVyc2lvbj0iMS4wIiBlbmNvZGluZz0iVVRGLTgiIHN0YW5kYWxvbmU9Im5vIj8+CjwhLS0gQ3JlYXRlZCB3aXRoIElua3NjYXBlIChodHRwOi8vd3d3Lmlua3NjYXBlLm9yZy8pIC0tPgoKPHN2ZwogICB4bWxuczpkYz0iaHR0cDovL3B1cmwub3JnL2RjL2VsZW1lbnRzLzEuMS8iCiAgIHhtbG5zOmNjPSJodHRwOi8vY3JlYXRpdmVjb21tb25zLm9yZy9ucyMiCiAgIHhtbG5zOnJkZj0iaHR0cDovL3d3dy53My5vcmcvMTk5OS8wMi8yMi1yZGYtc3ludGF4LW5zIyIKICAgeG1sbnM6c3ZnPSJodHRwOi8vd3d3LnczLm9yZy8yMDAwL3N2ZyIKICAgeG1sbnM9Imh0dHA6Ly93d3cudzMub3JnLzIwMDAvc3ZnIgogICB4bWxuczpzb2RpcG9kaT0iaHR0cDovL3NvZGlwb2RpLnNvdXJjZWZvcmdlLm5ldC9EVEQvc29kaXBvZGktMC5kdGQiCiAgIHhtbG5zOmlua3NjYXBlPSJodHRwOi8vd3d3Lmlua3NjYXBlLm9yZy9uYW1lc3BhY2VzL2lua3NjYXBlIgogICB3aWR0aD0iNjAwLjAwMDA2IgogICBoZWlnaHQ9IjYwMCIKICAgaWQ9InN2ZzIiCiAgIHZlcnNpb249IjEuMSIKICAgaW5rc2NhcGU6dmVyc2lvbj0iMC40OC40IHI5OTM5IgogICBzb2RpcG9kaTpkb2NuYW1lPSJQcm9maWxlUGxhY2Vob2xkZXJTdWl0LnN2ZyIKICAgaW5rc2NhcGU6ZXhwb3J0LWZpbGVuYW1lPSIvaG9tZS9uYXVnaHQxMDEvRG9jdW1lbnRzL2FydC9Qcm9maWxlUGxhY2Vob2xkZXJTdWl0LnBuZyIKICAgaW5rc2NhcGU6ZXhwb3J0LXhkcGk9IjMwIgogICBpbmtzY2FwZTpleHBvcnQteWRwaT0iMzAiPgogIDxkZWZzCiAgICAgaWQ9ImRlZnM0IiAvPgogIDxzb2RpcG9kaTpuYW1lZHZpZXcKICAgICBpZD0iYmFzZSIKICAgICBwYWdlY29sb3I9IiNmZmZmZmYiCiAgICAgYm9yZGVyY29sb3I9IiM2NjY2NjYiCiAgICAgYm9yZGVyb3BhY2l0eT0iMS4wIgogICAgIGlua3NjYXBlOnBhZ2VvcGFjaXR5PSIwLjAiCiAgICAgaW5rc2NhcGU6cGFnZXNoYWRvdz0iMiIKICAgICBpbmtzY2FwZTp6b29tPSIwLjciCiAgICAgaW5rc2NhcGU6Y3g9IjYxNy4yMTEyNSIKICAgICBpbmtzY2FwZTpjeT0iMzI3LjQ1ODQ4IgogICAgIGlua3NjYXBlOmRvY3VtZW50LXVuaXRzPSJweCIKICAgICBpbmtzY2FwZTpjdXJyZW50LWxheWVyPSJsYXllcjEiCiAgICAgc2hvd2dyaWQ9ImZhbHNlIgogICAgIGlua3NjYXBlOndpbmRvdy13aWR0aD0iMTYwMCIKICAgICBpbmtzY2FwZTp3aW5kb3ctaGVpZ2h0PSI4NTQiCiAgICAgaW5rc2NhcGU6d2luZG93LXg9Ii0yIgogICAgIGlua3NjYXBlOndpbmRvdy15PSItMyIKICAgICBpbmtzY2FwZTp3aW5kb3ctbWF4aW1pemVkPSIxIgogICAgIGZpdC1tYXJnaW4tdG9wPSIwIgogICAgIGZpdC1tYXJnaW4tbGVmdD0iMCIKICAgICBmaXQtbWFyZ2luLXJpZ2h0PSIwIgogICAgIGZpdC1tYXJnaW4tYm90dG9tPSIwIiAvPgogIDxtZXRhZGF0YQogICAgIGlkPSJtZXRhZGF0YTciPgogICAgPHJkZjpSREY+CiAgICAgIDxjYzpXb3JrCiAgICAgICAgIHJkZjphYm91dD0iIj4KICAgICAgICA8ZGM6Zm9ybWF0PmltYWdlL3N2Zyt4bWw8L2RjOmZvcm1hdD4KICAgICAgICA8ZGM6dHlwZQogICAgICAgICAgIHJkZjpyZXNvdXJjZT0iaHR0cDovL3B1cmwub3JnL2RjL2RjbWl0eXBlL1N0aWxsSW1hZ2UiIC8+CiAgICAgICAgPGRjOnRpdGxlPjwvZGM6dGl0bGU+CiAgICAgIDwvY2M6V29yaz4KICAgIDwvcmRmOlJERj4KICA8L21ldGFkYXRhPgogIDxnCiAgICAgaW5rc2NhcGU6bGFiZWw9IkxheWVyIDEiCiAgICAgaW5rc2NhcGU6Z3JvdXBtb2RlPSJsYXllciIKICAgICBpZD0ibGF5ZXIxIgogICAgIHRyYW5zZm9ybT0idHJhbnNsYXRlKC03NDMuMjAxNTUsOTcuNTY2MzU0KSI+CiAgICA8cGF0aAogICAgICAgc3R5bGU9Im9wYWNpdHk6MC41O2ZpbGw6Izk5OTk5OTtzdHJva2U6bm9uZSIKICAgICAgIGQ9Im0gMTAyNi41MTg0LC0zNC4wNDM4NTQgYyAtMTQuOTExMywxLjI3MTk5IC0zMC40NTU2NCw0Ljc1NjYxNSAtNDIuOTk1OTEsMTIuOTI0MTE1IC0xMC45NzIxNiw3LjE0NjI0OSAtMTkuMjMzMzcsMTguMzY3NjM5MSAtMjUuNTUyMjksMjkuODM2Mjc5MSAtNC42OTAxMiw4LjUxMjQ2ODkgLTYuOTkyNDIsMTguMjc2NDYyOSAtOC41ODc4MywyNy44NjM2NDk5IC0yLjUyNDU0LDE1LjE3MDQ1OSAtMS40MjIyOCw0Ni4xMTUzNTMgLTEuNDIyMjgsNDYuMTE1MzUzIGwgLTUuNDA2MTcsOC44Njk0OTEgYyAtMS4zNjMzOCwxMC43Mjg1NjYgMC4zNzk1MSwyMS4xMTU3ODYgMC43NzMwMSwzMS44NDQzNDYgMC4zMDY2Niw4LjM2MTk2IDEuMjQ0OTgsMTYuNzIzOTQgMi45Njc3MywyNS4wODU5MSBsIDguNTA3NjEsOS45NzEwNSBjIDAsMCAxLjk3ODk3LDExLjg1MTY2IDUuNDYxMDYsMjAuMDU1MzEgMy40ODIwNiw4LjIwMzYzIDE3LjA5Mjc5LDI2Ljk5NTIyIDE3LjA5Mjc5LDI2Ljk5NTIyIC0xMi41MzcwNCw0LjMzNTE4IC0zMS4xNTQ2LDguMDQ4OTcgLTM3LjU4OTc2LDEzLjAwODU5IC00LjY3Mjg0LDMuNjAxNCAtNS43NjIyOSwxMC42MjUxNSAtOC4xOTM3MiwxNi4zODc0NSBsIC0xMTUuMzAzMzgsMjEuMTE3ODMgLTE0LjM2MDEyLDIxLjIwMjMxIDAsMzAuNjYzMSAtNTguNzA3NTksMTk0LjUzNzQ4IDYwMC4wMDAwNSwyZS01IC0xOC40MTQ5LC02Mi4wODY0NCAtMjIuNTUzOCwtMTI2LjI4NDY1IC0xLjM1MTUsLTI1LjI1Njk0IC04Ljg2OTYsLTE1LjAzNTkgLTQ2LjM3NDcsLTE3LjA2MzIxIC02Ni4yMjU1LC0xMS41NzI1OCBjIC03LjA2NzUsLTcuMjkyNyAtMTUuOTk5OSwtMTcuNDMwMiAtMjEuMjAyMywtMjEuODc4MDcgLTUuMTg5MSwtNC40MzY0MyAtMjguNjY0LC0xMC45MjQ5NyAtNDIuOTk1OSwtMTYuMzg3NDQgbCAtMi43MDMxLC05LjU0NTI3IGMgMCwwIDcuNjY4MiwtOS4yNTI4MSAxMC4yMjEsLTE2LjM4NzQzIDIuNTUyOCwtNy4xMzQ2MyAzLjM3ODgsLTI1LjkzMjcxIDMuMzc4OCwtMjUuOTMyNzEgbCA0LjgxNDksMS4zNTE1NSA0LjgxNDksLTcuNTE3OTYgMi4wMjczLC0yNy4yODQyNCBjIDAsMCAwLjM5NjksLTMyLjM0MDMzMiAtMS4zNTE1LC0zNi4xNTM3MzQgLTEuNzQ4NSwtMy44MTM0MDEgLTUuNDkwNywtNC44MTQ4NjcgLTUuNDkwNywtNC44MTQ4NjcgMCwwIDAuOTk3MiwtMjkuNTYzODA4IC0yLjcwMzEsLTQzLjY3MTY4NCAtMy44NDk5LC0xNC42NzgzMzYgLTEwLjQyNDksLTI5LjA3NjE3MjEgLTE5Ljg1MDcsLTQwLjk2ODYwMjEgLTcuNzI4MywtOS43NTA2MTQ5IC0xNy41MzQ2LC0xOC42NTE1NDI5IC0yOC45ODYyLC0yMy41MTYwMzc5IC0xNi4zNDA1LC02Ljk0MTMyOCAtMzUuMTc3MSwtNy45ODAyNTggLTUyLjg2NjYsLTYuNDcxMjg5IHogbSAtNDcuMTM1LDI1MS44OTM1NDQgMTAuODk2ODEsMTkuNzY2MyAzOC45NDEyOSwzMi43NzQ4OCAxOS4wOTA1LDEuMzUxNTQgNDQuNDMxOSwtMjMuOTA1MzkgMTkuNzY2NCwtMjcuMjg0MjQgLTIuMDI3NCwxMC4yMjEwMyAtMjMuOTA1Myw2OC45Mjg2MiAtMTkuODUwOCw2NC44NzM5OCAtMTIuOTI0MSw1OS4zODMzNiAtMTMuMDA4Niw3Mi4zOTE5NCAtMzIuMDE0NiwtMTkzLjE4NTk2IC0xOS4xNzUwMSwtNDAuMjkyODMgeiBtIDg0LjY0OTMsMTQ1LjM2NTgzIC0xNi4zODMyLDgxLjkxNTc3IC02LjgyNjMsNDkuNTI0NDQgLTIyLjgzNDksLTE1NC4xMTY4MyA3Ljg1NDMsLTIwLjczNzM1IDIwLjE4MywtMi4wMDEwMSAtMTkuMTk2NCwtMC4zMjEzNCAtMTIuMzE3LC0yNS42MDY1MiAtNi42MjYsNS4yOTgyMyAxNy45MTkxLC0yMy4zODAxMyAyNC41NzQ3LDEuMzY1MjcgMjYuOTYzOSwzMS43NDIzNiAtMTUuNjQ2NiwtMTMuMDUwODQgLTE0LjczMDUsMjMuNjMxNjMgMTYuMzgzMiwzNC44MTQyMiB6IgogICAgICAgaWQ9InBhdGgyOTk2IgogICAgICAgaW5rc2NhcGU6Y29ubmVjdG9yLWN1cnZhdHVyZT0iMCIKICAgICAgIHNvZGlwb2RpOm5vZGV0eXBlcz0ic3Nzc2Njc2NjemNzY2NjY2NjY2NjY2Njc2NjemNjY2N6Y3Nzc3NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2MiIC8+CiAgPC9nPgo8L3N2Zz4K";
          scope.takePicture = function(){
          Rho.Camera.takePicture({
            outputFormat: Rho.Camera.OUTPUT_FORMAT_DATAURI
            },
            function(resp){
                scope.dataUriModel = resp.imageUri;
                scope.$apply();
          });
        }
        }
    };
});







We pass the original image (in dataUri format) into the scope of our directive, and then simply make the necessary API calls and store the new photo as our profile picture.


Any time you want to use this feature, you could drop "<profile-directive/>" into your HTML and reap all the benefits without any additional code.


Clean, simple, and easy to implement, directives are the way to go.


The Best in Service

Services are singletons, which are objects that are instantiated only once per app (by the $injector). They provide an interface to keep together methods that relate to a specific function. The $http service is an example of an AngularJS service that provides low-level access to the browser’s XMLHttpRequest object. Rather than needing to dirty the application with low-level calls to the XMLHttpRequest object, we can simply interact with the $http API.

Angular offers several useful services (like $http), but for most applications you'll also want to create your own. You can define your own service by registering the service's name and service factory function, with an Angular module. This function generates the single object or function that represents the service to the rest of the application. The object or function returned by the service is injected into any component (controller, service, filter or directive) that specifies a dependency on the service.

Services are registered to modules via the Module API. Typically you use the Module factory API to register a service:

var myModule = angular.module('myModule', []);
myModule.factory('serviceId', function() {
  var shinyNewServiceInstance;
  // factory function body that constructs shinyNewServiceInstance
  return shinyNewServiceInstance;
});





Note that you are not registering a service instance, but rather a factory function that will create this instance when called.

To use an Angular service, you add it as a dependency for the component (controller, service, filter or directive) that depends on the service. Angular's dependency injection subsystem takes care of the rest.


Have it Your Way

Just like with directives, we can write custom services. Let's take the code from the Ionic blog post, and add a custom service that uses RhoMobile's barcode API


Go into build.yml and add the  "- barcode" extension.


extensions:
  - rhoconnect-client
  - mediacapture
  - barcode





Next, add the factory method for the service into Controller.js and add the necessary dependencies to the Profile Controller:


.controller('ProfileCtrl', ['$scope', '$stateParams', '$zebraBarcodeScanner', function($scope, $stateParams,$zebraBarcodeScanner) {
  $scope.dataUriModel = "data:image/svg+xml;base64,PD94bWwgdmVyc2lvbj0iMS4wIiBlbmNvZGluZz0iVVRGLTgiIHN0YW5kYWxvbmU9Im5vIj8+CjwhLS0gQ3JlYXRlZCB3aXRoIElua3NjYXBlIChodHRwOi8vd3d3Lmlua3NjYXBlLm9yZy8pIC0tPgoKPHN2ZwogICB4bWxuczpkYz0iaHR0cDovL3B1cmwub3JnL2RjL2VsZW1lbnRzLzEuMS8iCiAgIHhtbG5zOmNjPSJodHRwOi8vY3JlYXRpdmVjb21tb25zLm9yZy9ucyMiCiAgIHhtbG5zOnJkZj0iaHR0cDovL3d3dy53My5vcmcvMTk5OS8wMi8yMi1yZGYtc3ludGF4LW5zIyIKICAgeG1sbnM6c3ZnPSJodHRwOi8vd3d3LnczLm9yZy8yMDAwL3N2ZyIKICAgeG1sbnM9Imh0dHA6Ly93d3cudzMub3JnLzIwMDAvc3ZnIgogICB4bWxuczpzb2RpcG9kaT0iaHR0cDovL3NvZGlwb2RpLnNvdXJjZWZvcmdlLm5ldC9EVEQvc29kaXBvZGktMC5kdGQiCiAgIHhtbG5zOmlua3NjYXBlPSJodHRwOi8vd3d3Lmlua3NjYXBlLm9yZy9uYW1lc3BhY2VzL2lua3NjYXBlIgogICB3aWR0aD0iNjAwLjAwMDA2IgogICBoZWlnaHQ9IjYwMCIKICAgaWQ9InN2ZzIiCiAgIHZlcnNpb249IjEuMSIKICAgaW5rc2NhcGU6dmVyc2lvbj0iMC40OC40IHI5OTM5IgogICBzb2RpcG9kaTpkb2NuYW1lPSJQcm9maWxlUGxhY2Vob2xkZXJTdWl0LnN2ZyIKICAgaW5rc2NhcGU6ZXhwb3J0LWZpbGVuYW1lPSIvaG9tZS9uYXVnaHQxMDEvRG9jdW1lbnRzL2FydC9Qcm9maWxlUGxhY2Vob2xkZXJTdWl0LnBuZyIKICAgaW5rc2NhcGU6ZXhwb3J0LXhkcGk9IjMwIgogICBpbmtzY2FwZTpleHBvcnQteWRwaT0iMzAiPgogIDxkZWZzCiAgICAgaWQ9ImRlZnM0IiAvPgogIDxzb2RpcG9kaTpuYW1lZHZpZXcKICAgICBpZD0iYmFzZSIKICAgICBwYWdlY29sb3I9IiNmZmZmZmYiCiAgICAgYm9yZGVyY29sb3I9IiM2NjY2NjYiCiAgICAgYm9yZGVyb3BhY2l0eT0iMS4wIgogICAgIGlua3NjYXBlOnBhZ2VvcGFjaXR5PSIwLjAiCiAgICAgaW5rc2NhcGU6cGFnZXNoYWRvdz0iMiIKICAgICBpbmtzY2FwZTp6b29tPSIwLjciCiAgICAgaW5rc2NhcGU6Y3g9IjYxNy4yMTEyNSIKICAgICBpbmtzY2FwZTpjeT0iMzI3LjQ1ODQ4IgogICAgIGlua3NjYXBlOmRvY3VtZW50LXVuaXRzPSJweCIKICAgICBpbmtzY2FwZTpjdXJyZW50LWxheWVyPSJsYXllcjEiCiAgICAgc2hvd2dyaWQ9ImZhbHNlIgogICAgIGlua3NjYXBlOndpbmRvdy13aWR0aD0iMTYwMCIKICAgICBpbmtzY2FwZTp3aW5kb3ctaGVpZ2h0PSI4NTQiCiAgICAgaW5rc2NhcGU6d2luZG93LXg9Ii0yIgogICAgIGlua3NjYXBlOndpbmRvdy15PSItMyIKICAgICBpbmtzY2FwZTp3aW5kb3ctbWF4aW1pemVkPSIxIgogICAgIGZpdC1tYXJnaW4tdG9wPSIwIgogICAgIGZpdC1tYXJnaW4tbGVmdD0iMCIKICAgICBmaXQtbWFyZ2luLXJpZ2h0PSIwIgogICAgIGZpdC1tYXJnaW4tYm90dG9tPSIwIiAvPgogIDxtZXRhZGF0YQogICAgIGlkPSJtZXRhZGF0YTciPgogICAgPHJkZjpSREY+CiAgICAgIDxjYzpXb3JrCiAgICAgICAgIHJkZjphYm91dD0iIj4KICAgICAgICA8ZGM6Zm9ybWF0PmltYWdlL3N2Zyt4bWw8L2RjOmZvcm1hdD4KICAgICAgICA8ZGM6dHlwZQogICAgICAgICAgIHJkZjpyZXNvdXJjZT0iaHR0cDovL3B1cmwub3JnL2RjL2RjbWl0eXBlL1N0aWxsSW1hZ2UiIC8+CiAgICAgICAgPGRjOnRpdGxlPjwvZGM6dGl0bGU+CiAgICAgIDwvY2M6V29yaz4KICAgIDwvcmRmOlJERj4KICA8L21ldGFkYXRhPgogIDxnCiAgICAgaW5rc2NhcGU6bGFiZWw9IkxheWVyIDEiCiAgICAgaW5rc2NhcGU6Z3JvdXBtb2RlPSJsYXllciIKICAgICBpZD0ibGF5ZXIxIgogICAgIHRyYW5zZm9ybT0idHJhbnNsYXRlKC03NDMuMjAxNTUsOTcuNTY2MzU0KSI+CiAgICA8cGF0aAogICAgICAgc3R5bGU9Im9wYWNpdHk6MC41O2ZpbGw6Izk5OTk5OTtzdHJva2U6bm9uZSIKICAgICAgIGQ9Im0gMTAyNi41MTg0LC0zNC4wNDM4NTQgYyAtMTQuOTExMywxLjI3MTk5IC0zMC40NTU2NCw0Ljc1NjYxNSAtNDIuOTk1OTEsMTIuOTI0MTE1IC0xMC45NzIxNiw3LjE0NjI0OSAtMTkuMjMzMzcsMTguMzY3NjM5MSAtMjUuNTUyMjksMjkuODM2Mjc5MSAtNC42OTAxMiw4LjUxMjQ2ODkgLTYuOTkyNDIsMTguMjc2NDYyOSAtOC41ODc4MywyNy44NjM2NDk5IC0yLjUyNDU0LDE1LjE3MDQ1OSAtMS40MjIyOCw0Ni4xMTUzNTMgLTEuNDIyMjgsNDYuMTE1MzUzIGwgLTUuNDA2MTcsOC44Njk0OTEgYyAtMS4zNjMzOCwxMC43Mjg1NjYgMC4zNzk1MSwyMS4xMTU3ODYgMC43NzMwMSwzMS44NDQzNDYgMC4zMDY2Niw4LjM2MTk2IDEuMjQ0OTgsMTYuNzIzOTQgMi45Njc3MywyNS4wODU5MSBsIDguNTA3NjEsOS45NzEwNSBjIDAsMCAxLjk3ODk3LDExLjg1MTY2IDUuNDYxMDYsMjAuMDU1MzEgMy40ODIwNiw4LjIwMzYzIDE3LjA5Mjc5LDI2Ljk5NTIyIDE3LjA5Mjc5LDI2Ljk5NTIyIC0xMi41MzcwNCw0LjMzNTE4IC0zMS4xNTQ2LDguMDQ4OTcgLTM3LjU4OTc2LDEzLjAwODU5IC00LjY3Mjg0LDMuNjAxNCAtNS43NjIyOSwxMC42MjUxNSAtOC4xOTM3MiwxNi4zODc0NSBsIC0xMTUuMzAzMzgsMjEuMTE3ODMgLTE0LjM2MDEyLDIxLjIwMjMxIDAsMzAuNjYzMSAtNTguNzA3NTksMTk0LjUzNzQ4IDYwMC4wMDAwNSwyZS01IC0xOC40MTQ5LC02Mi4wODY0NCAtMjIuNTUzOCwtMTI2LjI4NDY1IC0xLjM1MTUsLTI1LjI1Njk0IC04Ljg2OTYsLTE1LjAzNTkgLTQ2LjM3NDcsLTE3LjA2MzIxIC02Ni4yMjU1LC0xMS41NzI1OCBjIC03LjA2NzUsLTcuMjkyNyAtMTUuOTk5OSwtMTcuNDMwMiAtMjEuMjAyMywtMjEuODc4MDcgLTUuMTg5MSwtNC40MzY0MyAtMjguNjY0LC0xMC45MjQ5NyAtNDIuOTk1OSwtMTYuMzg3NDQgbCAtMi43MDMxLC05LjU0NTI3IGMgMCwwIDcuNjY4MiwtOS4yNTI4MSAxMC4yMjEsLTE2LjM4NzQzIDIuNTUyOCwtNy4xMzQ2MyAzLjM3ODgsLTI1LjkzMjcxIDMuMzc4OCwtMjUuOTMyNzEgbCA0LjgxNDksMS4zNTE1NSA0LjgxNDksLTcuNTE3OTYgMi4wMjczLC0yNy4yODQyNCBjIDAsMCAwLjM5NjksLTMyLjM0MDMzMiAtMS4zNTE1LC0zNi4xNTM3MzQgLTEuNzQ4NSwtMy44MTM0MDEgLTUuNDkwNywtNC44MTQ4NjcgLTUuNDkwNywtNC44MTQ4NjcgMCwwIDAuOTk3MiwtMjkuNTYzODA4IC0yLjcwMzEsLTQzLjY3MTY4NCAtMy44NDk5LC0xNC42NzgzMzYgLTEwLjQyNDksLTI5LjA3NjE3MjEgLTE5Ljg1MDcsLTQwLjk2ODYwMjEgLTcuNzI4MywtOS43NTA2MTQ5IC0xNy41MzQ2LC0xOC42NTE1NDI5IC0yOC45ODYyLC0yMy41MTYwMzc5IC0xNi4zNDA1LC02Ljk0MTMyOCAtMzUuMTc3MSwtNy45ODAyNTggLTUyLjg2NjYsLTYuNDcxMjg5IHogbSAtNDcuMTM1LDI1MS44OTM1NDQgMTAuODk2ODEsMTkuNzY2MyAzOC45NDEyOSwzMi43NzQ4OCAxOS4wOTA1LDEuMzUxNTQgNDQuNDMxOSwtMjMuOTA1MzkgMTkuNzY2NCwtMjcuMjg0MjQgLTIuMDI3NCwxMC4yMjEwMyAtMjMuOTA1Myw2OC45Mjg2MiAtMTkuODUwOCw2NC44NzM5OCAtMTIuOTI0MSw1OS4zODMzNiAtMTMuMDA4Niw3Mi4zOTE5NCAtMzIuMDE0NiwtMTkzLjE4NTk2IC0xOS4xNzUwMSwtNDAuMjkyODMgeiBtIDg0LjY0OTMsMTQ1LjM2NTgzIC0xNi4zODMyLDgxLjkxNTc3IC02LjgyNjMsNDkuNTI0NDQgLTIyLjgzNDksLTE1NC4xMTY4MyA3Ljg1NDMsLTIwLjczNzM1IDIwLjE4MywtMi4wMDEwMSAtMTkuMTk2NCwtMC4zMjEzNCAtMTIuMzE3LC0yNS42MDY1MiAtNi42MjYsNS4yOTgyMyAxNy45MTkxLC0yMy4zODAxMyAyNC41NzQ3LDEuMzY1MjcgMjYuOTYzOSwzMS43NDIzNiAtMTUuNjQ2NiwtMTMuMDUwODQgLTE0LjczMDUsMjMuNjMxNjMgMTYuMzgzMiwzNC44MTQyMiB6IgogICAgICAgaWQ9InBhdGgyOTk2IgogICAgICAgaW5rc2NhcGU6Y29ubmVjdG9yLWN1cnZhdHVyZT0iMCIKICAgICAgIHNvZGlwb2RpOm5vZGV0eXBlcz0ic3Nzc2Njc2NjemNzY2NjY2NjY2NjY2Njc2NjemNjY2N6Y3Nzc3NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2MiIC8+CiAgPC9nPgo8L3N2Zz4K";
  $scope.barcode = "Scan";
  $scope.takePicture = function(){
    Rho.Camera.takePicture({
      outputFormat: Rho.Camera.OUTPUT_FORMAT_DATAURI
      },
      function(resp){
          $scope.dataUriModel = resp.imageUri;
          $scope.$apply();
    });
  }


  $scope.scanBarcode = function(){
    $zebraBarcodeScanner
      .scan()
      .then(function(barcodeData) {
        // Success! Barcode data is here
        $scope.barcode = barcodeData;
      }, function(error) {
        // An error occurred
        alert(error)
      });
  }


}])


.factory('$zebraBarcodeScanner', ['$q', function ($q) {


    return {
      scan: function (config) {
        var q = $q.defer();


        if(Rho.Barcode){
          Rho.Barcode.take({},
            function(resp){
              if(resp.status=='ok'){
                q.resolve(resp.barcode);
              }else{
                q.reject('user cancelled or timeout occured');
              }
            });
        }
        else{
          q.reject('API not found - Make sure to add barcode extension and perform clean build.')
        }


        return q.promise;
      }
    };
  }]);





Now if you go into profile.html inside of Public/templates and remove the ng-if statement from the page and compile your code, your profile page should have a spiffy new scanner!


</div>
    <div class="list">
    <div class="item">
    <button class="button button-full button-positive icon-left ion-ios-barcode-outline" ng-click="scanBarcode()">{{barcode}}</button>
    </div>
    </div>
  </ion-content>
</ion-view>





Screen Shot 2015-07-31 at 1.05.54 PM.png

 

As the code above suggests, services are used more in the controller layer then in presentation, while directives are used mostly to influence what your users see. Directives and Services are both great ways to tidy up your HTML and JavaScript files and to keep everything organized and effective. Start looking into these options as a way to bring your RhoMobile apps to the next level.