I want to know how to call a directive when an event on the backend in fire to false...
here is where I am capturing the event
.factory('AuthInterceptor', function($q, $injector, $rootScope) {
return {
response: function(response) {
if (response.data.lineStatus) {
$rootScope.$broadcast('line:lineStatus', response.data.lineStatus);
}
return response;
}
});
then I am catching the broadcast here
.factory('BetSlipFactory', function($rootScope) {
var processingLineMoves = false;
$rootScope.$on('line:lineStatus', function(ev, status) {
status.selections = _.map(status.selections, function(selection) {
selection.display = false;
return selection;
});
if (!status.linesOK) {
if (!processingLineMoves) {
processingLineMoves = true;
$rootScope.linesMovedModal = $popover(angular.element('#linesMovedModal'), {
template: 'views/linesMovedModal.html',
html: true,
autoClose: false,
placement: 'left',
trigger: 'manual',
animation: 'fx-fade-down',
scope: _.assign($rootScope.$new(), status, {
okPicks: function(selection, selections, index) {
if (selections[index + 1] || selections.length > 1) {
$rootScope.betLoader = true;
selections.splice(index, 1);
$rootScope.betLoader = false;
}else {
$rootScope.linesMovedModal.hide();
processingLineMoves = false;
selections.splice(index, 1);
}
},
removePick: function(selection, selections, index) {
console.log('selections', selections);
betSlipSelectionRequest('/betSlip/removeSelection', {
game: selection.game,
pair: selection.pair,
line: selection.line
}).then(function() {
selections.splice(index, 1);
$rootScope.$broadcast('lines:removeAllLines');
if (selections[index + 1] || selections.length > 1) {
$rootScope.betLoader = true;
$rootScope.betLoader = false;
}else {
$rootScope.linesMovedModal.hide();
processingLineMoves = false;
}
}, function(err) {
console.log(err);
});
}
})
});
$timeout(function() {
$rootScope.linesMovedModal.show();
}, 800);
}
}
});
});
so basically, that $rootScope.$on is the part that I need to put in the directive. What I need is to fire up a popover displaying some info, that popover starts on this $rootScope variable: $rootScope.linesMovedModal
the main reason why I should put that into a directive, is because I am using the DOM here $popover(angular.element('#linesMovedModal')
Just in case this is the popover component I am using
.directive('newDirective', function($rootScope, $popover, $timeout, BetSlipFactory) {
return {
restrict: 'E',
link: function(scope, element, attrs) {
var processingLineMoves = false;
scope.$on('line:lineStatus', function(ev, status) {
status.selections = _.map(status.selections, function(selection) {
selection.display = false;
return selection;
});
if (!status.linesOK) {
if (!processingLineMoves) {
processingLineMoves = true;
scope.linesMovedModal = $popover(element, {
template: 'views/linesMovedModal.html',
html: true,
autoClose: false,
placement: 'bottom',
trigger: 'manual',
animation: 'fx-fade-down',
scope: _.assign(scope.$new(), status, {
okPicks: function(selection, selections, index) {
if (selections[index + 1] || selections.length > 1) {
scope.betLoader = true;
selections.splice(index, 1);
$timeout(function() {scope.betLoader = false;}, 100);
}else {
scope.linesMovedModal.hide();
processingLineMoves = false;
selections.splice(index, 1);
}
},
removePick: function(selection, selections, index) {
//HERE YOU NEED TO CREATE NEW FN IN THE SERVICE, OTHERWISE
//YOU WILL GET AN ERROR LIKE:
//betSlipSelectionRequest is not define **
CreateFnOnService(selection).then(function() {
$rootScope.$broadcast('lines:removeAllLines');
if (selections[index + 1] || selections.length > 1) {
selections.splice(index, 1);
$rootScope.betLoader = true;
$timeout(function() {scope.betLoader = false;}, 100);
}else {
$rootScope.linesMovedModal.hide();
processingLineMoves = false;
selections.splice(index, 1);
}
}, function(err) {
console.log(err);
});
}
})
});
$timeout(function() {
scope.linesMovedModal.show();
}, 200);
}
}
});
}
};
});
and that's it. Try it and let me know
Related
I'm loading a page with 3 collapsible panels, all containing a grid.
I can successfully load the panel as expanded (also tested with collapsed), using this code:
var component = {
bindings: {
configurationMigrationLogs: '<'
},
template: require("./reMigrationConfiguration.template.html"),
controller: ControllerFn,
controllerAs: 'vm'
};
ControllerFn.$inject = ['$timeout'];
function ControllerFn($timeout) {
const vm = this;
vm.isCardOpen = true; //Does work.
$timeout(function (vm) {
vm.isCardOpen = false; //Doesn't work.
console.log(vm);
}, 3000, true, vm);
}
export default function (app) {
app.component('reMigrationConfiguration', component);
}
However, when I try to collapse the panel in the $timeout function, it doesn't work.
I can see the vm.isCardOpen property is updated to false, in the console window.
But the panel remains expanded.
Here's the HTML:
<re-card is-collapsed="true" is-open="vm.isCardOpen" ng-repeat="configurationMigrationLog in vm.configurationMigrationLogs">
<!--grid code here-->
</re-card>
The re-card component is set up in this .js:
(function() {
'use strict';
angular.module('app.components')
.directive('reCard', directiveFn);
directiveFn.$inject = ['$timeout'];
function directiveFn($timeout) {
var directive = {
restrict:'EA',
scope:true,
priority:10,
controller:controllerFn,
transclude:true,
controllerAs:'reCard',
template: '<div>' +
'<div re-blocked="isBlocked" re-loading="isBusy"> ' +
'<div class="grid simple fadeIn animated" ' +
'ng-class="{collapsible:isCollapsible, \'is-open\':!isCollapsed }" ' +
're-transclude></div>' +
'</div></div>',
link:{
pre:preLinkFn,
post:postLinkFn
}
};
return directive;
function preLinkFn(scope, ele, attrs) {
if (attrs.isCollapsed) {
scope.isCollapsed = scope.$eval(attrs.isCollapsed);
scope.isCollapsible = attrs.isCollapsed;
scope.isOpen = scope.$eval(attrs.isOpen);
}
}
function postLinkFn(scope, ele, attrs, ctrl) {
var blockWatcher, obsv;
scope.isBusy = false;
if (attrs.notifyOfToggle) {
ctrl.registerNotifyOfToggle(attrs.notifyOfToggle);
}
if (attrs.isBlocked) {
blockWatcher = scope.$parent.$watch(attrs.isBlocked, function(val) {
scope.isBlocked = val;
});
}
if (attrs.hasOwnProperty('isBusy')) {
obsv = attrs.$observe('isBusy', function(val) {
if (val && scope.$eval(val)) {
scope.isBusy = true;
}
else {
scope.isBusy = false;
}
});
}
scope.$on('destroy', function() {
blockWatcher();
});
attrs.$observe('isOpen', function(val) {
if (typeof(val) !== 'undefined') {
ctrl.toggleCollapsed(!scope.$eval(val));
}
});
}
}
controllerFn.$inject = ['$scope'];
function controllerFn($scope) {
var notifyOfToggle = null;
this.getScope = function() {
return $scope;
};
this.toggleCollapsed = function(val) {
if (typeof($scope.isCollapsed) !== 'undefined') {
if (angular.isDefined(val)) {
$scope.isCollapsed = val;
} else {
$scope.isCollapsed = !$scope.isCollapsed;
}
if (notifyOfToggle) {
$scope.$eval(notifyOfToggle);
}
}
};
this.registerNotifyOfToggle = function(notifyOfToggleFromAttrs) {
notifyOfToggle = notifyOfToggleFromAttrs;
};
}
})();
Binding your is-open attribute should fix it:
<re-card is-collapsed="true" is-open="{{vm.isCardOpen}}" ng-repeat="configurationMigrationLog in vm.configurationMigrationLogs">
<!--grid code here-->
</re-card>
For some reason the label for select input field is not showing. I have made a custom directive for it, which looks like this:
angular.module('quiz.directives')
.directive('fancySelect', function($rootScope, $timeout) {
return {
restrict: 'E',
templateUrl: 'templates/directives/fancySelect.html',
scope: {
title: '#',
model: '=',
options: '=',
multiple: '=',
enable: '=',
onChange: '&',
class: '#'
},
link: function(scope) {
scope.showOptions = false;
scope.displayValues = [];
scope.$watch('enable', function(enable) {
if (!enable && scope.showOptions) {
scope.toggleShowOptions(false);
}
});
scope.toggleShowOptions = function(show) {
if (!scope.enable) {
return;
}
if (show === undefined) {
show = !scope.showOptions;
}
if (show) {
$rootScope.$broadcast('fancySelect:hideAll');
}
$timeout(function() {
scope.showOptions = show;
});
};
scope.toggleValue = function(value) {
if (!value) {
return;
}
if (!scope.multiple) {
scope.model = value;
return;
}
var index = scope.model.indexOf(value);
if (index >= 0) {
scope.model.splice(index, 1);
}
else {
scope.model.push(value);
}
if (scope.onChange) {
scope.onChange();
}
};
scope.getDisplayValues = function() {
if (!scope.options || !scope.model) {
return [];
}
if (!scope.multiple && scope.model) {
return scope.options.filter(function(opt) {
return opt.id == scope.model;
});
}
return scope.options.filter(function(opt) {
return scope.model.indexOf(opt.id) >= 0;
});
};
$rootScope.$on('fancySelect:hideAll', function() {
scope.showOptions = false;
});
}
};
});
And in my template I am inserting the directive like this:
<fancy-select
title="Klassetrinn"
model="selected.year"
ng-model="user.year"
options="years"
enable="true"
on-change="onChangeYears()"
active="yearsActive"
name="playerYear"
form-name="registerForm"
>
</fancy-select>
And then in my profile I am getting the value for selected year like this:
$http.get(AppSettings.apiUrl + '/years')
.then(function(result) {
$scope.years = result.data;
});
$scope.selected = {
year: []
};
user.player.year = $scope.selected.year;
But for some reason the label "Klassetrinn" is not shown in the template, not sure why is that?
in animation Module.directive I have a array that save data in options array an I take it to the from controller file script.js and to be located in linkfunction
My question is that I want to pass the array into animationModule.animation
how make this
this file of contoller script.js
var myApp = angular.module('myApp', ['ngMaterial', 'ngAnimate', 'customAnimation']);
/*angular.element(document).ready(function() {
angular.bootstrap(document, ['myApp']);
});
*/
myApp.controller('View', function ($scope , $rootScope , mySharedService) {
// start
var vm = this;
vm.in = false;
vm.direction = 'left';
vm.optionsanimate = [
{
type: 'slide',
direction: vm.direction,
parameters: {
x: {
start: '-100%',
end: '0'
},
opacity: {
start: 0,
end: 1
}
}
},
{
type: 'fade',
direction: vm.direction,
parameters: {
opacity: {
start: 0,
end: 1
},
x: {
start: '0',
end: '0'
}
}
}
];
vm.changeState = function (direction) {
$scope.in = vm.in = !vm.in;//handle the ng-if
/* $scope.direction='left';*/
vm.optionsanimate.animationInstance
console.table(vm);
}
});
myApp.factory('mySharedService', function($rootScope) {
var sharedService = {};
sharedService.message = '';
sharedService.prepForBroadcast = function(msg) {
this.message = msg;
};
sharedService.broadcastItem = function() {
$rootScope.$broadcast('handleBroadcast');
};
console.log(sharedService)
return sharedService;
});
this file of directive
var animationModule = angular.module('customAnimation', ['ngAnimate']);
var xStartglobal='';
var xendglobal='';
animationModule.factory('customAnimationFactory', ['$animateCss', function ($animateCss) {
function parseOptions(element, options ) {
console.log(options[0]);
var xstart=options[0].parameters.x.start;
/* var oAnimData = customAnimationClass.prototype.setCSSParamsEnter(options[1].parameters.x.start, options[1].parameters.x.end,options[1].parameters.opacity.start, options[1].parameters.opacity.end);*/
}
//constructor
var customAnimationClass = function customAnimationClass(params, element) {
this.params = params;
this.element = element;
//parseOptions(element, this.params);
//parseOptions(element, this.params, $animate ,paramend);
}
customAnimationClass.prototype = {
parseOptions: parseOptions,
//xStart: xStart,
setCSSParamsEnter: function (xStart, xEnd,oStart,oEnd) {
var params = this.params;
//start , end
angular.forEach(params, function (param, index) {
});
return {
//structural: true,
from: {
opacity: oStart,
transform: 'translate3d(' + xStart + ', 0, 0)'
},
to: {
opacity: oEnd,
transform: 'translate3d(' + xEnd + ', 0, 0) '
}
}
},
setCssParamsLeave: function (xStart, xEnd,oStart,oEnd) {
var params = this.params;
angular.forEach(params, function (param, index)
{ });
return {
//structural: true,
from: {
opacity: oEnd,
transform: 'translate3d(' + xStart + ', 0, 0)'
},
to: {
opacity: oStart,
transform: 'translate3d(' + xEnd + ', 0, 0)'
}
}
}
}
return customAnimationClass;
}]);
animationModule.factory('data', function ($animateCss) {
var dataservice = function dataservice(params1,$scope) {
this.params1 = params1;
var start= this.params1;
console.log(this.params1);
//parseOptions(element, this.temp);
//parseOptions(element, this.params, $animate ,paramend);
}
return dataservice;
});
animationModule.directive('customAnimation', ['customAnimationFactory', 'mySharedService','$animate' ,'data', function (customAnimationFactory , mySharedService,$animateCss,data) {
var flag=false;
return {
restrict: 'A',
controller:'View',
controllerAs:'vm',
bindToController:true,
link: function ($scope, $element, attrs,$ctrl,controller) {
var ctrl = this;
console.log($ctrl.in);
ctrl.options = $scope.$eval(attrs['animation']);
console.log(ctrl.options);
//$scope.xStart= ctrl.options[0].parameters.x.start;
xStartglobal= ctrl.options[0].parameters.x.start;
////$scope.xSEnd= ctrl.options[0].parameters.x.end;
xendglobal= ctrl.options[0].parameters.x.end;
var xx = new data(ctrl.options,$scope);
//ctrl.options.animationInstance =new slide(ctrl.options);
$element.addClass(ctrl.options[0].type);
//ctrl.options.animationInstance = new customAnimationFactory(ctrl.options, $element, mySharedService.message);
//if($ctrl.in==false) {
// //ctrl.options.animationInstance = new customAnimationFactory(ctrl.options, $element, mySharedService.message);
///* ctrl.options.animationInstance.setCSSParamsEnter('-100%','0','0','1');
// ctrl.options.animationInstance.setCssParamsLeave('0','-100%','0','1');
// flag=true;*/
//
//}
console.log("dori");
}
};
}]);
animationModule.animation('.slide', ['$animateCss', 'customAnimationFactory','data' ,function ($animateCss, customAnimationFactory,data) {
var x= new customAnimationFactory(0,0);
return {
enter: function (element,$scope) {
$scope.temp=data.start;
console.log("this x");
console.log($scope.temp);
//console.log($scope.xstart);
console.log(element[0].attributes.vm);
//console.table();
console.log(xStartglobal);
return $animateCss(element, x.setCSSParamsEnter('-100%','0','0','1' ));
//return $animateCss(element, customAnimationService.setCSSParamsEnter());
},
leave: function (element) {
return $animateCss(element, x.setCssParamsLeave('0','-100%','0','1' ));
}
}
}]);
this my plunker
http://plnkr.co/edit/Qywbt7bvKfs9b5lpvRY9?p=info
I am trying to get long press event in angular js .I found the solution from here
https://gist.github.com/BobNisco/9885852
But I am not able to get log on console .here is my code.
http://goo.gl/ZpDeFz
could you please tell me where i am getting wrong ..
$scope.itemOnLongPress = function(id) {
console.log('Long press');
}
$scope.itemOnTouchEnd = function(id) {
console.log('Touch end');
}
It is a good implementation:
// pressableElement: pressable-element
.directive('pressableElement', function ($timeout) {
return {
restrict: 'A',
link: function ($scope, $elm, $attrs) {
$elm.bind('mousedown', function (evt) {
$scope.longPress = true;
$scope.click = true;
// onLongPress: on-long-press
$timeout(function () {
$scope.click = false;
if ($scope.longPress && $attrs.onLongPress) {
$scope.$apply(function () {
$scope.$eval($attrs.onLongPress, { $event: evt });
});
}
}, $attrs.timeOut || 600); // timeOut: time-out
// onTouch: on-touch
if ($attrs.onTouch) {
$scope.$apply(function () {
$scope.$eval($attrs.onTouch, { $event: evt });
});
}
});
$elm.bind('mouseup', function (evt) {
$scope.longPress = false;
// onTouchEnd: on-touch-end
if ($attrs.onTouchEnd) {
$scope.$apply(function () {
$scope.$eval($attrs.onTouchEnd, { $event: evt });
});
}
// onClick: on-click
if ($scope.click && $attrs.onClick) {
$scope.$apply(function () {
$scope.$eval($attrs.onClick, { $event: evt });
});
}
});
}
};
})
Usage example:
<div pressable-element
ng-repeat="item in list"
on-long-press="itemOnLongPress(item.id)"
on-touch="itemOnTouch(item.id)"
on-touch-end="itemOnTouchEnd(item.id)"
on-click="itemOnClick(item.id)"
time-out="600"
>{{item}}</div>
var app = angular.module('pressableTest', [])
.controller('MyCtrl', function($scope) {
$scope.result = '-';
$scope.list = [
{ id: 1 },
{ id: 2 },
{ id: 3 },
{ id: 4 },
{ id: 5 },
{ id: 6 },
{ id: 7 }
];
$scope.itemOnLongPress = function (id) { $scope.result = 'itemOnLongPress: ' + id; };
$scope.itemOnTouch = function (id) { $scope.result = 'itemOnTouch: ' + id; };
$scope.itemOnTouchEnd = function (id) { $scope.result = 'itemOnTouchEnd: ' + id; };
$scope.itemOnClick = function (id) { $scope.result = 'itemOnClick: ' + id; };
})
.directive('pressableElement', function ($timeout) {
return {
restrict: 'C', // only matches class name
link: function ($scope, $elm, $attrs) {
$elm.bind('mousedown', function (evt) {
$scope.longPress = true;
$scope.click = true;
$scope._pressed = null;
// onLongPress: on-long-press
$scope._pressed = $timeout(function () {
$scope.click = false;
if ($scope.longPress && $attrs.onLongPress) {
$scope.$apply(function () {
$scope.$eval($attrs.onLongPress, { $event: evt });
});
}
}, $attrs.timeOut || 600); // timeOut: time-out
// onTouch: on-touch
if ($attrs.onTouch) {
$scope.$apply(function () {
$scope.$eval($attrs.onTouch, { $event: evt });
});
}
});
$elm.bind('mouseup', function (evt) {
$scope.longPress = false;
$timeout.cancel($scope._pressed);
// onTouchEnd: on-touch-end
if ($attrs.onTouchEnd) {
$scope.$apply(function () {
$scope.$eval($attrs.onTouchEnd, { $event: evt });
});
}
// onClick: on-click
if ($scope.click && $attrs.onClick) {
$scope.$apply(function () {
$scope.$eval($attrs.onClick, { $event: evt });
});
}
});
}
};
})
li {
cursor: pointer;
margin: 0 0 5px 0;
background: #FFAAAA;
}
.pressable-element {
-khtml-user-select: none;
-moz-user-select: none;
-ms-user-select: none;
user-select: none;
-webkit-touch-callout: none;
-webkit-user-select: none;
}
<div ng-app="pressableTest">
<div ng-controller="MyCtrl">
<ul>
<li ng-repeat="item in list"
class="pressable-element"
on-long-press="itemOnLongPress(item.id)"
on-touch="itemOnTouch(item.id)"
on-touch-end="itemOnTouchEnd(item.id)"
on-click="itemOnClick(item.id)"
time-out="600"
>{{item.id}}</li>
</ul>
<h3>{{result}}</h3>
</div>
</div>
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.2.23/angular.min.js"></script>
JSFiddle: https://jsfiddle.net/reduardo7/u47ok38e/
Based on: https://gist.github.com/BobNisco/9885852
Your code is not working because the directive binds to the elements touchstart and touchend events which you're probably not using if you're testing in a browser.
When I changed them to mousedown and mouseup your script worked fine on my computer's browser.
app.directive('onLongPress', function($timeout) {
return {
restrict: 'A',
link: function($scope, $elm, $attrs) {
$elm.bind('mousedown', function(evt) { // <-- changed
/* ... */
});
$elm.bind('mouseup', function(evt) { // <-- changed
/* ... */
});
}
};
})
Go through the below URL for the angular directive and the implementation approaches,
Source code for long press Directive:
// Add this directive where you keep your directives
.directive('onLongPress', function($timeout) {
return {
restrict: 'A',
link: function($scope, $elm, $attrs) {
$elm.bind('touchstart', function(evt) {
// Locally scoped variable that will keep track of the long press
$scope.longPress = true;
// We'll set a timeout for 600 ms for a long press
$timeout(function() {
if ($scope.longPress) {
// If the touchend event hasn't fired,
// apply the function given in on the element's on-long-press attribute
$scope.$apply(function() {
$scope.$eval($attrs.onLongPress)
});
}
}, 600);
});
$elm.bind('touchend', function(evt) {
// Prevent the onLongPress event from firing
$scope.longPress = false;
// If there is an on-touch-end function attached to this element, apply it
if ($attrs.onTouchEnd) {
$scope.$apply(function() {
$scope.$eval($attrs.onTouchEnd)
});
}
});
}
};
})
Your HTML Should be like this:
<ion-item ng-repeat="item in list" on-long-press="itemOnLongPress(item.id)" on-touch-end="itemOnTouchEnd(item.id)">
{{ item }}
</ion-item>
Controller JS functions to make the definitions that you would prefer:
$scope.itemOnLongPress = function(id) {
console.log('Long press');
}
$scope.itemOnTouchEnd = function(id) {
console.log('Touch end');
}
https://gist.github.com/BobNisco/9885852
Hi I am newbie to angular I am trying to update using ng-click directive and $watch function. On first click it is getting updated but second time it doesn't get updated. Bare my english and little knowledge Here is my code.
angular.module('charts', [])
.factory('socket', ['$rootScope', function ($rootScope) {
var safeApply = function(scope, fn) {
if (scope.$$phase) {
fn(); // digest already in progress, just run the function
} else {
scope.$apply(fn); // no digest in progress, run with $apply
}
};
var socket = io.connect('http://localhost:5000/');
return {
on: function (eventName, callback) {
socket.on(eventName, function () {
var args = arguments;
safeApply($rootScope, function () {
callback.apply(socket, args);
});
});
},
emit: function (eventName, data, callback) {
socket.emit(eventName, data, function () {
var args = arguments;
safeApply($rootScope, function () {
if (callback) {
callback.apply(socket, args);
}
});
})
},
disconnect: function () {
socket.disconnect();
},
socket: socket
};
}])
.controller('mainCtrl',['$scope','socket', function AppCtrl ($scope, socket) {
$scope.options = {width: 500, height: 300, 'bar': 'aaa'};
$scope.data = {"angular":12,"js":15};
$scope.hovered = function(d){
$scope.barValue = d.name;
//$scope.$apply();
};
$scope.barValue = 'None';
}])
.directive('barChart', function(){
var chart = d3.custom.barChart();
return {
restrict: 'E',
replace: true,
template: '<div class="chart"></div>',
scope:{
height: '=height',
data: '=data',
hovered: '&hovered'
},
link: function(scope, element, attrs) {
var chartEl = d3.select(element[0]);
chart.on('customHover', function(d, i){
scope.hovered({args:d});
});
scope.$watch('data', function (newVal, oldVal) {
console.log(newVal);
chartEl.datum(newVal).call(chart);
});
scope.$watch('height', function(d, i){
chartEl.call(chart.height(scope.height));
})
}
}
})
.directive('chartForm', function(){
return {
restrict: 'E',
replace: true,
controller: function AppCtrl ($scope, socket) {
$scope.start = function(d, i) {
$scope.btnIsDisabled = true;
socket.on("connected",function(r){ console.log('breakpoint 1');/*console.log(r);*/ });
socket.on("new tweet", function(tweet) {
var hashtags = tweet.entities.hashtags;
if(hashtags.length) {
_.each(hashtags, function(hashtag) {
hashtag = hashtag.text.toLowerCase();
// if(hashtag == 'food' || hashtag == 'pizza' || hashtag == 'samosa') {
// console.log(hashtag);
if(_hashtags[hashtag]) {
_hashtags[hashtag]++;
}
else {
_hashtags[hashtag] = 1;
}
//}
});
}
num_tweets++;
});
};
$scope.update = function(d, i) {
$scope.safeApply = function(fn) {
var phase = this.$root.$$phase;
if(phase == '$apply' || phase == '$digest') {
if(fn && (typeof(fn) === 'function')) {
fn();
}
} else {
this.$apply(fn);
}
};
$scope.safeApply( function() {
console.log(JSON.stringify(_hashtags));
$scope.data = _hashtags;
});
};
},
template: '<div class="form">' +
'Height: {{options.height}}<br />' +
'<input type="range" ng-model="options.height" min="100" max="800"/>' +
'<br /><button ng-click="start()" ng-disabled="btnIsDisabled">Start</button>'+
'<button ng-click="update()" ng-disabled="false">Update Data</button>' +
'<br />Hovered bar data: {{barValue}}</div>'
}
});