I have a directive but I am facing problem in watching an attribute from the directive controller.
angular.module('app',[])
.directive('timer1', function () {
return {
template: '<div class="timerCont1"><div class="progressBar"></div></div>',
restrict: 'E',
replace:true,
scope: true,
controller: function ($scope, $element, $attrs) {
$scope.$watch($attrs.timerevent, function (value) {
switch ($attrs.timerevent)
{
case "start":
$scope.timeoutId = null;
$scope.countdown = Number($attrs.timer);
$scope.tick();
break;
case "stop":
$scope.stop();
break;
case "destroy":
alert()
$scope.stop();
$scope.$emit('destroy_pizza', {
});
}
},true);
$scope.tick = function () {
$scope.timeoutId = setTimeout(function () {
if ($scope.countdown <= 0) {
$scope.$apply(function () {
$attrs.$set('timerevent', 'destroy')
});
}
else {
$scope.countdown--;
$scope.tick();
}
$scope.$apply();
}, $attrs.interval);
};
$scope.stop = function () {
clearTimeout($scope.timeoutId);
$scope.timeoutId = null;
};
}
};
});
And here goes my hTML
<timer1 interval="1000" timerevent="start" timer="10"></timer1>
When I am setting the attribute timerevent to "destroy" my watch is not getting called, whereas the attribute is updated successfully.
If you are going to get changes in $watch use the scope instead of $attrs.
angular.module('abc').directive('timer1', function () {
return {
template: '<div class="timerCont1"><div class="progressBar"></div></div>',
restrict: 'E',
replace:true,
scope: {
timerevent:"=",
timer:"#",
interval:"#"
},
controller: function (scope, $element, $attrs) {
scope.$watch('timerevent', function () {
//this section will be run after chnaging the timerevent
},true);
}
};
});
I managed to get a solution to my own problem :)
Instead of watch I tried observing the attribute
Here is my working code https://plnkr.co/edit/LKuYcCU5z5wa7dTe1Uzo
Since its a long piece of code I am writing my controller
<timer1 interval="1000" timer-event="start" timer="10"></timer1>
$attrs.$observe('timerEvent', function(value) {
switch (value.toLowerCase()) {
case "start":
$scope.timeoutId = null;
$scope.countdown = Number($attrs.timer);
$scope.tick();
break;
case "stop":
$scope.stop();
break;
case "destroy":
alert("It is watched")
$scope.stop();
$scope.$emit('destroy_pizza', {
});
}
}, true);
For more information, see AngularJS $compile Attributes API Reference - $observe.
Related
I'm new in creating an angularjs directive. This directive is working. But when i try to use gulp test its saying $ is not define
.directive('backToTop', function () {
return {
restrict: 'E',
replace: true,
templateUrl: 'src/client/app/directives/backtop.html',
link: function ($scope, element, attrs) {
$(window).scroll(function () {
if ($(window).scrollTop() <= 0) {
$(element).fadeOut();
}
else {
$(element).fadeIn();
}
});
$(element).on('click', function () {
$('html, body').animate({ scrollTop: 0 }, 'fast');
});
}
};
})
Any Suggestions to make it work ? Thanks
The following code works as expected and the scope.checked value is reflected in the UI normally
.directive('comparisonSlider',
function () {
return{
restrict: 'E',
templateUrl: '/app/reports/comparison-slider.html',
controller: function ($scope, $rootScope) {
$scope.checked = false;
$rootScope.$on('compare',
function () {
$scope.checked = true;
},
true);
}
}
}
)
but the following code also works, but the changes to scope aren't reflected in the UI.
.directive('comparisonSlider',
function () {
return{
restrict: 'E',
templateUrl: '/app/reports/comparison-slider.html',
controller: function ($scope, $rootScope) {
$scope.checked = false;
$rootScope.$on('compare',
function () {
$scope.checked = !$scope.checked;
},
true);
}
}
}
)
Any ideas?
This works as expected, not sure why the other one doesn't
.directive('comparisonSlider',
function () {
return{
restrict: 'E',
templateUrl: '/app/reports/comparison-slider.html',
controllerAs: 'sliderCtrl',
controller: function ($scope, $rootScope) {
var self = this;
self.checked = false;
$rootScope.$on('compare',
function () {
self.checked = !self.checked;
},
true);
}
}
}
)
Try changing:
self.checked = !self.checked;
to:
self.checked = false;
I am using the following code to broadcast a route change to a directive:
function run($rootScope) {
$rootScope.$on('$routeChangeSuccess',
function(event, current, previous, rejection) {
if (current.$$route.originalPath !== '') {
$rootScope.$broadcast(event.name, { loadedTemplateUrl: current.loadedTemplateUrl });
}
});
}
The directive is receiving the broadcast twice. The directive is placed upon an html template. There is no controller. How can I prevent from firing twice in directive?
function optimizely($compile) {
var directive = {
restrict: 'E',
link: function (scope, element) {
scope.$on('$routeChangeSuccess',
function (event, data) {
var template = '';
switch (data.loadedTemplateUrl) {
case '/app/views/china.html':
template = '<script src=""></script>';
break;
default:
template = '<script src="App/optimizelyTest.js"></script>';
}
scope.$apply(function () {
var content = $compile(template)(scope);
element.append(content);
});
});
}
};
return directive;
}
Thanks,
Mark
I have directive that use another directive that is setting his property 'gridWidth', but I'm trying to watch that property changes and its not working at all. Can anyone explain what I'm doing wrong?
angular.module('myApp')
.directive('myGrid', function () {
'use strict';
return {
restrict: 'E',
replace: true,
scope: {
gridWidth: '='
},
controller: ['$scope', function(scope) {
scope.$watch('gridWidth', function (newValue, oldValue) {
console.log("width is changed");
}, true);
}],
template: '<div element-resize gridWidth="{{windowWidth}}"></div>'
};
});
The 'windowWidth' is changes fine and I can see it in HTML dom changes, but the $watch not working for some reason so I can't do anything when it is being updated. Here is the another directive updating the first one with width:
angular.module('myApp')
.directive('elementResize', function () {
'use strict';
return {
restrict: 'A',
controller: ['$scope', '$element', function($scope, $element) {
$scope.getElementDimensions = function () {
return { 'h': $element.height(), 'w': $element.width() };
};
$scope.$watch($scope.getElementDimensions, function (newValue, oldValue) {
$scope.windowHeight = newValue.h;
$scope.windowWidth = newValue.w;
}, true);
}]
};
});
I'm using this simple directive to know the size (height/width) of an DOM element:
angular.module('myApp')
.directive('elementResize', function () {
'use strict';
return {
restrict: 'A',
controller: ['$scope', '$element', function($scope, $element ) {
$scope.getElementDimensions = function () {
return { 'h': $element.height(), 'w': $element.width() };
};
$scope.$watch($scope.getElementDimensions, function (newValue, oldValue) {
$scope.windowHeight = newValue.h;
$scope.windowWidth = newValue.w;
}, true);
}]
};
});
This is the HTML template:
<div element-resize>Element1.width:{{windowWidth}}</div><div element-resize>Element2.width:{{windowWidth}}a div with more width space</div>
I have two divs that are brothers, but using my directive I get the same sizes of the latest, instead of getting each one of them the real size. What did I missed here?
UPDATE:
If I had ng-controller to the first div it will work. Why?
Why not just use link instead of controller. Here's an example plunker.
app.directive('elementResize', function() {
'use strict';
return {
restrict: 'A',
template: 'Element.width:{{windowWidth}}',
scope: {},
link: function(scope, element, ctrl) {
console.log(element)
scope.getElementDimensions = function() {
return {
'h': element[0].clientHeight,
'w': element[0].clientWidth
};
};
scope.$watch(scope.getElementDimensions, function(newValue, oldValue) {
scope.windowHeight = newValue.h;
scope.windowWidth = newValue.w;
}, true);
}
};
});