Extending the jQuery prototype to access Bootstrap components
October 2nd, 2013
Easily accessing the HTML and objects of Bootstrap components by extending the jQuery prototype.
I recently wrote a blog post with some basic lessons learned after using AngularJS for a while. In it I briefly described a pattern of using broadcast messages with services to share data between controllers in AngularJS. This method can be useful when you have multiple controllers on a page, some of which need to know when data managed by another controller has been changed. I was asked if there were any examples online. I have since posted an example to GitHub. I will explain the example in a little more detail here.
This example consists of an index.html file, two JavaScript files (one for the controllers and one for the service), and a basic CSS file. You can just open the index.html file in a browser to see it work. The page consists of 3 divs, each controlled by its own controller, with all controllers sharing data via the service.
The HTML is fairly simple:
<div data-ng-controller="TopController">
Top Value: <input data-ng-model="topValue" /><br/>
Middle Value: {{middleValue}}<br/>
Bottom Value: {{bottomValue}}
</div>
<div data-ng-controller="MiddleController">
Top Value: {{topValue}}<br/>
Middle Value: <input data-ng-model="middleValue" /><br/>
Bottom Value: {{bottomValue}}
</div>
<div data-ng-controller="BottomController">
Top Value: {{topValue}}<br/>
Middle Value: {{middleValue}}<br/>
Bottom Value: <input data-ng-model="bottomValue" /><br/>
</div>
Here we have three divs. Each is bound to its own controller. Each controller is responsible for managing one piece of data. However, each controller wants to display the values handled by the other two. How do we do that?
Let’s start by taking a look at the service. We create this service to hold our values and announce to the app that they have changed.
angular.module('demoService', []).factory('DemoService', function($rootScope){
var service = {};
service.topValue = 0;
service.middleValue = 0;
service.bottomValue = 0;
service.updateTopValue = function(value){
this.topValue = value;
$rootScope.$broadcast("valuesUpdated");
}
service.updateMiddleValue = function(value){
this.middleValue = value;
$rootScope.$broadcast("valuesUpdated");
}
service.updateBottomValue = function(value){
this.bottomValue = value;
$rootScope.$broadcast("valuesUpdated");
}
return service;
});
This service is really just a JavaScript object that lives outside of any one scope. It is setup as an Angular module so that it can be wired into your app module (see the code for how this is done, as it’s outside the scope of this discussion). This object contains variables for all three of our values, and update methods for each one. Note that I call these “updaters” and not “setters”. They do not follow the typical setter pattern in that they do more work than just set a value. These methods set the value, and then send out a broadcast message announcing to the world that a value has changed.
Next, let’s take a look at one of the controllers.
function TopController($scope, DemoService) {
$scope.topValue = 0;
$scope.middleValue = 0;
$scope.bottomValue = 0;
$scope.$watch('topValue', function() {
DemoService.updateTopValue($scope.topValue);
});
$scope.$on('valuesUpdated', function() {
$scope.middleValue = DemoService.middleValue;
$scope.bottomValue = DemoService.bottomValue;
});
}
This is the controller for our top div. Notice we have wired in our DemoService. This gives us access to it in the controller, just like a standard AngularJS service (such as $scope, $location, etc). We use $scope’s $watch method to watch the value we care about. This is just the easiest for this demo. You can process the changed value however you like (perhaps with ng-click or ng-change, or in the middle of some other method that executes after some business logic — it really depends on your app). All that our $watch method does is call the updater method on our service.
The next section is the $on method that listens for the broadcast message. Remember, this message will get broadcast every time a value in the service is updated. When the message is fired, each controller will receive it and update the values it cares to by getting them from the service.
That is all there is to it. Hopefully this helps organize your inner-controller data sharing in AngularJS!
Easily accessing the HTML and objects of Bootstrap components by extending the jQuery prototype.
Looking at the basic concepts of using D3 to manipulate the DOM.
The Angular.js JavaScript MVC framework has a powerful directive mechanism that can be used to create reusable HTML widgets.
Insert bio here