19 Feb 2015
Exploring Boostrap Angular UI components
AngularJs is starting to impose itself as the reference JavaScript framework to develop SPA - Single Page (Web) Applications. And probably for a reason, that stuff acts like magic :)
Boostrap, another world famous framework for building websites, allows you to quickly create nice looking UI components.
I'm working on building a demo website featuring our viewing technology entirely relying on Angular-friendly components, so today I'm taking a look at two Bootstrap libraries offering Angular UI directives:
Both offer some pretty cool UI components and you can directly test them on their webpage, which makes it very explicit to see what you can achieve.
I decided to pick up one and integrate our viewer in it to see how they can get along: a nice one is the Bootstrap UI Carousel, a component that displays a collection of slides rotating on a timer. You can see a plunker demo of the carousel there. Not that I don't like kittens, but I think 3D models on the web are cooler ;)
The integration ended up being more challenging and instructive than I initially thought. Here are the highlights of the sample:
Following code illustrates how to perform a jsonP call from the angular controller:
1 //jsonP call to get total number of models in the Gallery 2 function getGalleryModelCount(onSuccess) { 3 4 var url = 'http://gallery.autodesk.io/api/models/count'; 5 6 $http.jsonp(url + "?callback=JSON_CALLBACK"). 7 success(function(data, status, headers, config) { 8 onSuccess(data.count); 9 }). 10 error(function(data, status, headers, config) { 11 console.log('Error: ' + status); 12 }); 13 }
This is needed because invoking the Gallery REST API from a different domain requires a cross domain call. Also needed, the activation of cors and jsonp on my node.js server:
1 var app = express(); 2 3 //CORS middleware 4 var cors = function (req, res, next) { 5 6 res.header("Access-Control-Allow-Origin", "*"); 7 8 res.header("Access-Control-Allow-Headers", 9 "Origin, X-Requested-With, Content-Type, Accept"); 10 11 res.header('Access-Control-Allow-Methods', 12 'GET,PUT,POST,DELETE'); 13 14 next(); 15 } 16 17 app.use(cors); 18 19 app.set("jsonp callback", true);
An angular filter is also required because I bind the iframe ng-source to a scope.member, so the url as to be trusted...
1 // needs that filter to bind iframe ng-src to scope member 2 app.filter('trustAsResourceUrl', ['$sce', function($sce) { 3 return function(url) { 4 return $sce.trustAsResourceUrl(url); 5 }}]);
Just for fun, I wanted to set up a listener for the carousel slide changed event, that thread gives a pretty exhaustive solution:
1 // a directive to watch carousel slide changed event 2 app.directive('onCarouselChange', function ($parse) { 3 return { 4 require: 'carousel', 5 link: function (scope, 6 element, 7 attrs, 8 carouselCtrl) { 9 var fn = $parse(attrs.onCarouselChange); 10 var origSelect = carouselCtrl.select; 11 carouselCtrl.select = 12 function (nextSlide, direction) { 13 if (nextSlide !== this.currentSlide) { 14 fn(scope, { 15 nextSlide: nextSlide, 16 direction: direction 17 }); 18 } 19 return origSelect.apply(this, arguments); 20 }; 21 } 22 }; 23 });
Here is the full code of the final result and the live demo: that carousel will fetch iframe slides of models from my Gallery, you can hit the "Add Slide" button to randomly add a new model slide.
style="height: 490px; width: 490px">
on-carousel-change="onSlideChanged(nextSlide, direction)">
Enter a negative number or 0 to stop the interval.