-
Notifications
You must be signed in to change notification settings - Fork 3
AngularJS: Example Deckster Directives
A custom Angular directive will allow you to insert one piece of HTML into another via an HTML tag or attribute. See here for an explanation of Angular directives. Deckster uses directives to place the deck into the HTML of your app.
Define your custom directive and call it 'decksterDeck', attaching it to the module in your app where you wish to place the Deckster deck.
angular.module('app').directive('decksterDeck', function ($parse, $timeout) {Then, within this function, you might want to define your defaults for Gridster, the jQuery plug-in that Deckster is based on. These defaults can be overridden as you configure each deck, but they should be defined at least in once of those places. See Gridster Documentation for additional options.
var defaults = {
gridsterOpts: {
max_cols: 4, // max columns
widget_margins: [10, 10], // x, y margins between each card
widget_base_dimensions: ['auto', 250], // x, y dimensions of rows and columns. 'auto' will set width to be responsive to page size
responsive_breakpoint: 850 // responsiveness of when cards change position when one card is dragged
}
};Then define the directive itself:
return {
restrict: 'EA', // restricts directive to be usable via element tag and attribute
replace: true,
scope: { // sets two-way binding between parent and isolated scope for 'deck' and 'initialized' variables
deck: '=',
initialized: '='
},Reference a template file for your Deckster deck
templateUrl: '/partials/decksterDeck.html', // insert path to your template fileWithin that template file (decksterDeck.html), include the following HTML:
<div class="deckster-deck-wrapper">
<div class="deckster-deck" deck-options="deck">
<deckster-card ng-repeat="cardOpts in deck.cards" card-options="cardOpts"></deckster-card>
</div>
</div>'These controller functions will properly set up your Deckster deck:
controller: function($scope) {
$scope.deckInitialized = false;
$scope.$on('deckster:resize', function () {
if ($scope.deckster) {
$timeout(function () {
$scope.deckster.$gridster.recalculate_faux_grid();
});
}
});
this.addCard = function (card, callback) {
$scope.deckster.addCard(card, function (card) {
if (callback) callback(card);
});
};
this.init = function (element, opts) {
$scope.deckster = $(element).deckster(opts).data('deckster');
$scope.deckInitialized = true;
};
},
link: function (scope, element, attrs, ctrl) {
var deckOptions = $.extend(true, {}, defaults, scope.deck);
var $deckEl = $(element).find('.deckster-deck');
scope.$watch('initialized', function(init) {
if (init && !scope.deckInitialized) {
ctrl.init($deckEl, deckOptions);
}
});
scope.$on('$destroy', function() {
scope.deckster.destroy();
scope.deckInitialized = false;
});
}
};
})The instantiation of the Deckster Deck directive should call the Deckster Card directive using ng-repeat.
angular.module('app').directive('decksterCard', function ($parse, $q, $http, $timeout) {
return {
restrict: 'E',
require: ['^decksterDeck', 'decksterCard'],
controller: function ($scope, $compile) {Within the controller, there are several default functions that you may define if you wish. None of these are necessary for basic Deckster functionality.
// Default summaryContentHtml function
this.getSummaryContent = function (card, cb) {
$timeout(function() {
cb($compile('<div></div>')($scope));
});
};
// Default detailsContentHtml function
this.getDetailsContent = function (card, cb) {
$timeout(function() {
cb($compile('<div></div>')($scope));
});
};
// Default leftControlsHtml function
this.getLeftControlsContent = function (card, cb) {
$timeout(function() {
cb($compile('<div></div>')($scope));
});
};
// Default rightControlsHtml function
this.getRightControlsContent = function (card, cb) {
$timeout(function() {
cb($compile('<div></div>')($scope));
});
};
// Default centerControlsHtml function
this.getCenterControlsContent = function (card, cb) {
$timeout(function() {
cb($compile('<div></div>')($scope));
});
};
this.onReload = function (card) {
console.log('card reloaded', card);
};
this.onResize = function (card) {
console.log('card resized', card);
};
this.onExpand = function (card) {
console.log('card expanded', card);
};
this.scrollToCard = function () {
$scope.card.scrollToCard();
};
this.toggleCard = function () {
$scope.card.hidden ? $scope.card.showCard() : $scope.card.hideCard();
};This function IS necessary, and will set up your defaults as well as create the card itself.
this.setUpCard = function (cardOpts) {
if(!cardOpts.summaryViewType && !cardOpts.detailsViewType) {
cardOpts.summaryContentHtml = cardOpts.summaryContentHtml || this.getSummaryContent;
cardOpts.detailsContentHtml = cardOpts.detailsContentHtml || this.getDetailsContent;
cardOpts.onResize = cardOpts.onResize || this.onResize;
cardOpts.onReload = cardOpts.onReload || this.onReload;
}
cardOpts.showFooter = false;
cardOpts.leftControlsHtml = this.getLeftControlsContent;
cardOpts.rightControlsHtml = this.getRightControlsContent;
cardOpts.centerControlsHtml = this.getCenterControlsContent;
$scope.$on('deckster-card:scrollto-' + cardOpts.id, this.scrollToCard);
$scope.$on('deckster-card:toggle-' + cardOpts.id, this.toggleCard);
return cardOpts;
};
},The link function will then set up the event listeners.
link: function (scope, element, attrs, ctrls) {
var deckCtrl = ctrls[0];
var cardCtrl = ctrls[1];
var cardOpts = $parse(attrs.cardOptions || {})(scope);
scope.$watch('deckInitialized', function (initialized) {
if (initialized) {
deckCtrl.addCard(cardCtrl.setUpCard(cardOpts), function (card) {
scope.card = card;
// When the deck is resize resize this card as well
scope.$on('deckster:resize', function () {
// TODO code to resize cards
});
scope.$on('deckster:redraw', function () {
$timeout(function () {
// TODO code to redraw cards
});
});
});
}
});
}
};
})This directive should configure the Deckster popout functionality, if you wish you use that.
angular.module('app').directive('decksterPopout', ['$injector', '$compile', '$http', 'Deckster', function($injector, $compile, $http, Deckster) {
return {
restrict: 'E',
link: function(scope, element) {
var cardId, section;
var $routeParams = $injector.get('$routeParams');
cardId = $routeParams.id;
section = $routeParams.section;
var getSummaryTemplate = function(cardConfig, cb) {
// Not using the cardConfig here but you could use it to make request
$http.get('partials/testSummaryCard.html').success(function(html) {
if (cb) cb($compile(html)(scope));
});
};
var getDetailsTemplate = function(cardConfig, cb) {
// Not using the cardConfig here but you could use it to make request
$http.get('partials/testDetailsCard.html').success(function (html) {
if (cb) cb($compile(html)(scope));
});
};
// Get card config from server or angular constants using cardId
var cardConfig = {
title: 'Photos',
id: 'photoCard',
summaryContentHtml: getSummaryTemplate,
detailsContentHtml: getDetailsTemplate,
position: {
size_x: 1,
size_y: 1,
col: 1,
row: 1
}
};
Deckster.generatePopout(element, cardConfig, section);
}
};
}]);See the directive file for the Github Pages' Angular example for a complete example of these directives.