Custom asyncvalidator is not getting executed - angularjs

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.

Related

InAppBrowser passing a callback function

I have a InAppBrowser working fine in my app
$scope.openInAppBrowser = function (url) {
var ref = window.open(encodeURI(url), '_blank', 'location=yes');
ref.addEventListener('loadstop', function (event) {
if (event.url.match("close")) {
$scope.refreshGamePage = 1; // this variable is under watch in a directive
ref.close();
}
});
}
here is the directive written to refresh the page
module.directive('reloadPage', ['$http', function ($http) {
return {
restrict: 'A',
link: function ($scope, element, attrs) {
$scope.refreshPage = function () {
if($scope.refreshGamePage ==1)
return true;
else
return false;
};
$scope.$watch($scope.refreshPage, function (v) {
if (v) {
$scope.setGamePage(); // this function will contains code to refresh game page
}
});
}
};
}]);
but it seems like loadstop event listener is unable to update scope variable.
Can anyone help me with this?
Basically idea is I want to refresh current page (one from which InAppBrowser opened) in my app as soon as InAppBrowser closes itself.
Any better way to achieve this will be appreciated.
Just use angular $apply() method to change the value of angular
variables because it is changed out of angularjs turn.
$scope.openInAppBrowser = function (url) {
var ref = window.open(encodeURI(url), '_blank', 'location=yes');
ref.addEventListener('loadstop', function (event) {
if (event.url.match("close")) {
$scope.$apply(function () {
$scope.refreshGamePage = 1;
});
ref.close();
}
});
}

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.

Can I call a Service from a Directive?

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();

how to pass a value from attrs.$observe in an angular directive

Currently the console.log(value) outputs the value of 'lat' but if I try and access that value elsewhere in my directive it will not work. I have tried to set a variable equal to attrs.$observe as well as putting the attrs.$observe within a function. In addition for some reason I cannot return the value of data. Any thoughts
angular.module('Ski').directive('mapCanvas', function() {
function link (scope, element, attrs) {
attrs.$observe('lat', function(data) {
console.log(data);
});
}
}
Simply you can do this by making some global variable, using scope or var
CODE
angular.module('Ski').directive('mapCanvas', function() {
function link (scope, element, attrs) {
scope.lat = ''; //or it can be var lat = '';
attrs.$observe('lat', function(data) {
scope.lat = data; //or it can be var scope.lat = '';
console.log(data);
});
scope.test = function(){
//when it gets called
console.log(scope.lat);
}
}
}
Hope this could help you. Thanks.

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