Can I call a Service from a Directive? - angularjs

I have the following service:
myapp.service('myService', function () {
var vm = this;
vm.returnChoreList = function () {
console.log('returnChoreList : ' + vm.chore.length);
return vm.chore;
}});
Here is my directive:
myapp.directive("applyplugin", function (myService) {
return {
link: function (scope, element, attr) {
scope.$watch(function () {
$(element).bootstrapSwitch();
});
$(element).bind("switchChange.bootstrapSwitch", function (event, state) {
if (state == true) {
var clistArr = myService.returnChoreList;
console.log(clistArr.chore.length);
}
})
}
}
});
I want to be able to use the chore array in my directive. But I'm having difficulties getting it.
How can I get this array so I can use it in the directive?

You're missing the parentheses on the function call. Try: var clistArr = myService.returnChoreList();

Related

How can I use a function from a directive inside a controller function?

I'm a newbie in AngularJS and I'm trying to use the goToUserLocation() function from the userLocation directive in the getMyPosition() function in the MapController. The reason I want to do this is that once the user clicks a button I want to take his location, zoom in to 40 and place it at the center of the map.
Can someone please help me with this?
Thank you.
Here are the directive, the controller and a service that the directive uses:
(function ()
{
'use strict';
angular
.module('app.map')
.directive('userLocation', userLocation);
function userLocation(geolocation)
{
return {
restrict: "A",
link: function(scope, element, attrs){
var ctrl = scope['vm'];
var goToUserLocation = UserLocationFactory();
goToUserLocation(ctrl, geolocation, ctrl.defaultLocation );
}
};
}
//Factory to build goToUserLocation function with callbacks configuration
function UserLocationFactory(cantGetLocation, notSupportedBrowser)
{
return goToUserLocation;
//function to make the map go to user location
function goToUserLocation(vm, geolocation, defaultLocation)
{
resolveErrorCallbacks();
geolocation.goToUserLocation(success, cantGetLocation, notSupportedBrowser);
function success(position)
{
var location = {
lat: position.lat,
lng: position.lng,
zoom: 15
};
configureLatlng(location);
}
function configureLatlng(location)
{
vm.map = {
center: location
};
}
function resolveErrorCallbacks(){
if( !cantGetLocation || !( typeof cantGetLocation === "function" ) )
{
cantGetLocation = function()
{
configureLatlng(defaultLocation);
};
}
if( !notSupportedBrowser || !( typeof notSupportedBrowser === "function" ) )
{
notSupportedBrowser = function()
{
configureLatlng(defaultLocation);
};
}
}
}
}
})();
Here is the controller:
(function ()
{
'use strict';
angular
.module('app.map')
.controller('MapController', MapController);
/** #ngInject */
function MapController($mdDialog, $mdSidenav, $animate, $timeout, $scope, $document, MapData,
leafletData, leafletMapEvents, api, prototypes, $window, appEnvService, geolocation) {
var vm = this;
vm.getMyPosition = getMyPosition;
function getMyPosition(){
console.log("Here is your location.");
}
Here is a service that the directive us:
(function() {
'use strict';
angular
.module('app.map')
.service('geolocation', geolocation);
function geolocation() {
/*
success - called when user location is successfully found
cantGetLocation - called when the geolocation browser api find an error in retrieving user location
notSupportedBrowser - callend when browser dont have support
*/
this.goToUserLocation = function(success, cantGetLocation, notSupportedBrowser)
{
if (navigator.geolocation)
{
navigator.geolocation.getCurrentPosition(currentPosition, function() {
cantGetLocation();
});
}
else
{
// Browser doesn't support Geolocation
notSupportedBrowser();
}
function currentPosition(position)
{
var pos =
{
lat: position.coords.latitude,
lng: position.coords.longitude
};
success(pos);
}
};
}
})();
To call a directive function from a controller you can bind a object from the controller onto the directive using the scope '='.
<body ng-controller="MainCtrl">
<div my-directive control="directiveControl"></div>
<button ng-click="directiveControl.foo()">Call Directive Func</button>
<p>{{directiveControl.fooCount}}</p>
</body>
then
app.controller('MainCtrl', function($scope) {
$scope.directiveControl = {};
});
app.directive('myDirective', function factory() {
return {
restrict: 'A',
scope: {
control: '='
},
link: function(scope, element, attrs) {
scope.directiveControl = scope.control ? scope.control : {};
scope.directiveControl.fooCount=0;
scope.directiveControl.foo = function() {
scope.directiveControl.fooCount++;
}
}
};
});
See this example:
https://plnkr.co/edit/21Fj8dvfN0WZ3s9OUApp?p=preview
and this question:
How to call a method defined in an AngularJS directive?

Custom asyncvalidator is not getting executed

Hi I am trying to create an angular asyncValidator but I think I am doing something wrong becausse it does not get executed.Here is my code:
(function () {
'use strict';
angular
.module('project')
.directive('imageValidator', imageValidator);
imageValidator.$inject = ['utilitiesService', '$q'];
function imageValidator(utilitiesService, $q) {
var directive = {
restrict: 'A',
require: 'ngModel',
link: link,
};
return directive;
function link(scope, element, attrs, ngModel) {
ngModel.$asyncValidators.imageValidator = function (url) {
var deferred = $q.defer();
if (url) {
var image = new Image();
if (utilitiesService.isNotExternalFile(url)) {
image.src = utilitiesService.getUrl(url)
} else {
image.src = url;
}
image.onload = function () {
deferred.resolve(true);
scope.$apply();
}
image.onerror = function () {
deferred.reject(false);
scope.$apply();
}
} else {
deferred.resolve(true);
}
return deferred.promise;
}
}
}
})();
The code gets executed oance but it does not get executed when I change things in the input.
When it first gets executed it sets the class ng-valid-image-validator which is correct I want it to be valid if there is nothing in the input.
But when I write something in the input ng-valid-image-validator gets removed but it does not add the ng-invalid-image-validator and I asume this happens because the custom validator code does not get executed.
Does anyone have any ideeas what I am doing wrong?
EDIT : I just noticed that the validator gets executed again if emptying the input.

AngularJS directives require parent not working [duplicate]

This question already has answers here:
Controller Required By Directive Can't Be Found
(2 answers)
Closed 7 years ago.
I have 2 directives that I want to share functions between, so I figured I would create a parent directive.
I did it like this:
.directive('kdAlert', function () {
return {
restrict: 'A',
scope: {
},
link: function (scope, element) {
// Set our dismiss to false
scope.dismiss = false;
// Have to use a watch because of issues with other directives
scope.$watch(function () {
// Watch the dismiss
return scope.dismiss;
// If the value changes
}, function (dismiss) {
// If our value is false
if (dismiss === false || dismiss === 'false') {
// Remove the class from the element
element.removeClass('ng-hide');
// Else, if the value is true (or anything else)
} else {
// Add the class to the element
element.addClass('ng-hide');
}
});
// Get our buttons
var buttons = element.find('button');
// Binds our close button
self.bindCloseButton = function (callback) {
// If we have a button
for (var i = 0; i < buttons.length; i++) {
// Get our current button
var button = angular.element(buttons[i]);
// If our button is the close button
if (button.hasClass('close')) {
// If the button is clicked
button.on('click', function (e) {
console.log('clicked');
// Prevent any default actions
e.preventDefault();
// Callback
callback()
// Remove our element
element.remove();
});
}
}
};
}
};
})
.directive('cookie', function () {
return {
restrict: 'A',
require: 'kdAlert',
templateUrl: '/assets/tpl/directives/cookie.html',
link: function (scope, element, attr, controller) {
// Dismiss the alert
scope.dismissAlert = function () {
// Set our cookie
scope.dismiss = $cookies.dismissCookieAlert = true;
};
// Bind our close button
scope.bindCloseButton(scope.dismissAlert);
}
};
})
.directive('newsletter', function () {
return {
restrict: 'A',
require: 'kdAlert',
controller: 'NewsletterController',
templateUrl: '/assets/tpl/directives/newsletter.html',
link: function (scope, element, attr, controller) {
// Saves our email address
scope.subscribe = function (valid) {
// If we are not valid
if (!valid) {
// Return from the function
return;
}
// Subscribe
controller.subscribe(scope.email);
};
// Dismiss the alert
self.dismissAlert = function () {
// Set our cookie
self.dismiss = $cookies.dismissNewsletterAlert = true;
};
// Bind our close button
scope.bindCloseButton(scope.dismissAlert);
}
};
})
The newsletter has a controller also, which just looks like this:
.controller('NewsletterController', ['$q', '$cookies', 'SubscriberService', 'toastr', function ($q, $cookies, service, toastr) {
var self = this;
// Saves our email address
self.subscribe = function (email) {
// Create our deferred promise
var deferred = $q.defer();
// Subscribe
service.subscribe(email).success(function () {
// If we succeed, display a message
toastr.success('You will now recieve occasional newsletters.');
// Resolve our promise
deferred.resolve();
});
// Return our promise
return deferred.promise;
};
}])
but when I run my application I get an error:
Controller 'kdAlert', required by directive 'newsletter', can't be found!
does anyone know how I can get it to work?
You have to modify require: 'kdAlert', to require: '^kdAlert', and add a controller to your kdAlert in order to make the require work, require will try to find the controller of the kdAlert directive and pass it as a parameter to the directive link function.

$watch does not work when changing scope variables inside a service

I am using a service to change some of scope A's variables. When I try to $watch for changes on those variables nothing happens.
The basic setup is shown below. I would like to use $watch in my own custom directive that I add to the element. But if that is impossible I would at least like to be able to use $watch from inside the controller.
I made a plunkr here. As you can see $scope.someVar changes but $watch is never fired on either the controller or the directive.
app.factory("changerService", function() {
var $scope;
function change(to) {
$scope.someVar = to;
}
function setScope(scope) {
$scope = scope;
}
return {
Change: change,
SetScope: setScope
}
});
app.controller("bar", ["$scope", "changerService", function ($scope, changerService) {
$scope.someVar = true;
changerService.SetScope($scope);
$scope.showImg = function (val) {
changerService.Change(val);
$scope.state = $scope.someVar;
};
$scope.$watch($scope.someVar, function (newVal, oldVal) {
$scope.watchController = newVal ? newVal : "undefined";
});
}]);
app.directive("myDirective", function () {
return {
link: function (scope, element, attrs) {
scope.$watch(scope.someVar, function (newVal, oldVal) {
scope.watchDirective = newVal ? newVal : "undefined";
});
}
}
});
After examining your code i noticed that your watch expression is an object but it must be a string.
Example:
app.controller("bar", ["$scope", "changerService", function ($scope, changerService) {
$scope.someVar = true;
changerService.SetScope($scope);
$scope.showImg = function (val) {
changerService.Change(val);
$scope.state = $scope.someVar;
};
$scope.$watch("someVar", function (newVal, oldVal) {
$scope.watchController = newVal ? newVal : "undefined";
});
}]);
app.directive("myDirective", function () {
return {
link: function (scope, element, attrs) {
scope.$watch("someVar", function (newVal, oldVal) {
scope.watchDirective = newVal ? newVal : "undefined";
});
}
}
});

Changes event does not trigger in angular directive

I'm writing an angular directive. Here is the code:
'use strict';
app.directive('mcategory', function (MainCategory, $rootScope) {
return {
restrict: 'E',
replace: true,
template: '<select data-ng-model="selectedMainCategory" data-ng-options="mainCategory.mainCategoryId as mainCategory.mainCategoryName ' +
'for mainCategory in mainCategories" data-ng-change="mainCategoryChanged()"></select>',
link: function(scope, element, attr, controller) {
var elm = angular.element(element);
elm.attr('id', attr['id']);
elm.attr('name', attr['name']);
elm.attr('class', attr['class']);
MainCategory.get().then(function (mainCategories) {
scope.mainCategories = mainCategories;
});
scope.selectedMainCategory = false;
scope.mainCategoryChanged = function () {
if (!scope.selectedMainCategory) {
return;
}
$rootScope.$broadcast("mainCategoryChanged", { mainCategory: scope.selectedMainCategory });
};
}
};
})
MainCategory is a service and it works ok.
The problem is that selectedMainCategory is always undefined and mainCategoryChanged() event is not triggered when user selects another category in the select element. I think I have made a silly mistake but it is more than 2 hours that I can't solve the problem. Any help is appreciated in advance.
UPDATE
Here is the service:
'use strict';
app.factory('MainCategory', function ($http, $q) {
return {
get: function() {
var deferred = $q.defer();
$http.get('/MainCategory/GetMainCategories').success(deferred.resolve).error(deferred.reject );
return deferred.promise;
}
};
})
When I '/MainCategory/GetMainCategories' url in the browser I get all the categories in the correct json format.

Resources