How to make function to be fired when directive loaded? - angularjs

I define this directive:
(function () {
"use strict";
angular.module("inspectionReview").directive("inspectionsReviewsList", ["config",inspectionsReviewsList]);
function inspectionsReviewsList(config) {
var directive = {
restrict: "E",
scope: {
objectId: "=",
region: "="
},
templateUrl: config.baseUrl + "app/InspectionReview/templates/inspectionsReviewsList.templ.html",
controller: "inspectionsReviewsListController",
controllerAs: "list"
}
return directive;
}
angular.module("inspectionReview").controller("inspectionsReviewsListController", ["$scope",
"$uibModal",
"inspectionReviewServices",
"toaster",
inspectionsReviewsListController]);
function inspectionsReviewsListController($scope, $uibModal, inspectionReviewServices, toaster) {
//===============================check status of site object================================
$scope.$watch('inspectionReviews', function () {
_.each($scope.inspectionReviews, function (value, key) {
if (!value.IsNormal) {
return $scope.status = false;
}
$scope.status = true;
})
}, true)
//===================================modal window============================================
$scope.open = function (size) {
var modalInstance = $uibModal.open({
animation: $scope.animationsEnabled,
templateUrl: 'app/siteObjects/templates/myModalContent.tmpl.html',
controller: 'myModalWindowController',
size: 'sm',
resolve: {
items: function () {
return $scope.items;
}
}
});
modalInstance.result.then(function (selectedItem) {
$scope.selected = selectedItem;
}, function () {
//$log.info('Modal dismissed at: ' + new Date());
});
};
}
})();
In the view:
<inspections-reviews-list id="object.Id"></inspections-reviews-list>
How can I make this function:
inspectionReviewServices.getValues(objectId).then(function (result) {
$scope.inspectionReviews = result.data;
});
to be fired when when directive is loaded.

You can assign a function to the directive's link property, as follows:
link : getValues;
The getValues functions is like this:
function getValues(scope, element, attributes) {
inspectionReviewServices.getValues(attributes.id).then(function (result) {
scope.inspectionReviews = result.data;
});
}

use like this... it will work..
function () {
angular.module("inspectionReview").directive("inspectionsReviewsList", ["config",inspectionsReviewsList]);
function inspectionsReviewsList(config) {
var directive = {
restrict: "E",
scope: {
objectId: "=",
region: "="
},
link : function getValues(scope, element, attributes) {
inspectionReviewServices.getValues(attributes.id).then(function (result) {
scope.inspectionReviews = result.data;
});
},
templateUrl: config.baseUrl + "app/InspectionReview/templates/inspectionsReviewsList.templ.html",
controller: "inspectionsReviewsListController",
controllerAs: "list"
}
return directive;
}

Related

angularjs nested cascading directive for dropdown

I want to create a cascading dropdown directive .
<my-dropdown label="states" url="http://statelisturl">
<my-dropdown label="cities" url="http://citylisturl">
</my-dropdown>
</my-dropdown>
But states will be list first, when I select a state cities will be get from url.
Is this possible for angularjs technically? Or I should be seperated directive for every dropdown?
You could do something like this:
.directive("myDropdown", function() {
return {
restrict: "E",
require: ["myDropdown", "?^^myDropdown"],
template: "<select ng-options='opt as opt.label for opt in $ctrl.options' ng-model='$ctrl.selectedOption' ng-change='$ctrl.changed($ctrl.selectedOption)'></select><div ng-transclude></div>",
scope: true,
bindToController: {
url: "#",
label: "#"
},
controller: function($scope, $http) {
var _self = this;
_self.init = function() {
$http.get(_self.url).then(function(response) {
_self.options = response.data;
});
}
_self.parentChanged = function(item) {
var id = item.id;
$http.get(_self.url + "?id=" + id).then(function(response) {
_self.options = response.data;
});
}
},
link: function(scope, element, attrs, ctrls) {
var ctrl = ctrls[0];
var parentCtrl = ctrls[1];
if (parentCtrl) {
scope.$watch(function() {
return parentCtrl.selectedOption;
}, function(newval) {
if (newval) {
ctrl.parentChanged(newval);
}
});
} else {
ctrl.init();
}
},
controllerAs: "$ctrl",
transclude: true
}
});
EDIT: I have a working example here

How to make `$ocLazyLoad` work with `ui.router` in Angular 1.5?

I am trying to lazy load ($ocLazyLoad) some non-angular libraries (jQuery + css files) through the route (using angular ui.router).
In this code snippet I am trying to load the iCheck library, and only use it in my InputsCtrl
here's my config:
.state('dashboard.inputs', {
url: "/elements/inputs",
templateUrl: templateProvider.getTemplate('inputs'),
controller: 'InputsCtrl',
controllerAs: 'inputs',
resolve: {
loadPlugin: function ($ocLazyLoad) {
return $ocLazyLoad.load([
{
files: [
'bower_components/iCheck/skins/polaris/polaris.css',
'bower_components/iCheck/icheck.min.js'
]
}
]);
}
}
})
and it is causing the following error:
here's my empty controller:
(function () {
'use strict';
angular
.module('mega-app')
.controller('InputsCtrl', ctrl);
function ctrl() {
var vm = this;
}
})();
and here's the directive I am using:
(function () {
'use strict';
angular
.module('mega-app')
.directive('icheck', icheck);
function icheck($timeout) {
return {
restrict: 'A',
require: 'ngModel',
link: function($scope, element, $attrs, ngModel) {
return $timeout(function() {
var value;
value = $attrs['value'];
$scope.$watch($attrs['ngModel'], function(newValue){
$(element).iCheck('update');
})
return $(element).iCheck({
checkboxClass: 'icheckbox_square-green',
radioClass: 'iradio_square-green'
}).on('ifChanged', function(event) {
if ($(element).attr('type') === 'checkbox' && $attrs['ngModel']) {
$scope.$apply(function() {
return ngModel.$setViewValue(event.target.checked);
});
}
if ($(element).attr('type') === 'radio' && $attrs['ngModel']) {
return $scope.$apply(function() {
return ngModel.$setViewValue(value);
});
}
});
});
}
};
}
})();

Unit Testing a watch method call in Directive link function

I have the following Directive
.directive("myContainer", function (myContainerService,$window) {
return {
restrict: 'A',
templateUrl: "myContainer/MyContainer.tpl.html",
controller: 'myCtrl',
controllerAs: 'myCtrl',
scope: {
items: '='
},
link: function (scope, element) {
var timeout;
scope.$watch('myCtrl.items', function (items) {
var windowWidth = $window.innerWidth - 65;
window.clearTimeout(timeout);
timeout = window.setTimeout(function () {
myContainerService.saveItems(items);
}, 1000);
}, true);
}
};
})
And here is the Unit Test i have.
describe("myCtrl", function(){
var myCtrl;
var dirEle ;
var myScope;
// var to store the Mock Items
var myContainerService = $injector.get('myContainerService');
var items = [..]
beforeEach(inject(function($compile, $httpBackend){
$httpBackend.whenGET(/.*my-app\/restful-services\/items*./).respond({...});
scope.items = myContainerService.getItems();
dirEle = $compile('<div my-container items="items"></div>')(scope);
scope.$digest();
myScope = dirEle.isolateScope();
myCtrl = myScope.myCtrl;
}));
fit("Saving Items", inject(function($timeout){
spyOn(myContainerService, 'saveItems');
//$timeout.flush();
myScope.$digest();
$timeout.flush();
expect(myContainerService.saveItems).toHaveBeenCalledWith(myCtrl.items);
}));
});
And my test is failing as the saveItems is not getting called at all. Not sure what i am doing wrong.
Appreciate any inputs.
Thanks
You need to be using angulars $timeout that way in your test your $timeout.flush() will work:
.directive("myContainer", function (myContainerService,$window, $timeout) {
return {
restrict: 'A',
templateUrl: "myContainer/MyContainer.tpl.html",
controller: 'myCtrl',
controllerAs: 'myCtrl',
scope: {
items: '='
},
link: function (scope, element) {
var timeout;
scope.$watch('myCtrl.items', function (items) {
var windowWidth = $window.innerWidth - 65;
$timeout.cancel(timeout);
timeout = $timeout(function () {
myContainerService.saveItems(items);
}, 1000);
}, true);
}
};
})

Angular directive not rendering scope values in view

My directive uses a service which returns a promise, I need to display the scope attributes geoZip, geoCity and geoState in the template.
The issue is that those scope variables are not being shown in the template, I just see the comma.
What should I do to make it display the scope variables?
This is my directive code:
.directive('cityStateZip', function() {
return {
restrict: 'A',
transclude: true,
scope: {
zip: '=',
},
template: '<p>{{geoCity}}, {{geoState}} {{geoZip}}</p>',
controller: ['$scope', 'GeolocationService', function ($scope, GeolocationService) {
GeolocationService.geocode($scope.zip).then(function(result) {
if (result) {
console.log(result);
$scope.geoZip = result['address_components'][0]['long_name'];
$scope.geoCity = result['address_components'][1]['long_name'];
$scope.geoState = result['address_components'][2]['short_name'];
}
});
}]
};
})
.service('GeolocationService', ['underscore', '$q', function (underscore, $q) {
var gs = {};
gs.geocode = function(address) {
var geocoder = new google.maps.Geocoder();
var deferred = $q.defer();
geocoder.geocode( { "address": address }, function(results, status) {
if (status == google.maps.GeocoderStatus.OK && results.length > 0) {
return deferred.resolve(underscore.first(results));
}
return deferred.reject();
});
return deferred.promise;
}
return gs;
}]);
I found that I have to use the $timeout service to make it work:
.directive('cityStateZip', function() {
return {
restrict: 'A',
transclude: true,
scope: {
zip: '=',
},
template: '<p>{{geoCity}}, {{geoState}} {{geoZip}}</p>',
controller: ['$scope', '$timeout', 'GeolocationService', function ($scope, $timeout, GeolocationService) {
GeolocationService.geocode($scope.zip).then(function(result) {
if (result) {
console.log(result);
$timeout(function() {
$scope.geoZip = result['address_components'][0]['long_name'];
$scope.geoCity = result['address_components'][1]['long_name'];
$scope.geoState = result['address_components'][2]['short_name'];
});
}
});
}]
};
})
Please let me know if there is best alternative (not using $timeout), Thanks!

Inject service into directive

Cant inject the comment service into comment directive getting errorComment service not found
// Code goes here
var noBlogApp = angular.module("noBlogApp", ['ngRoute', 'ngSanitize', 'commentSystem']);
noBlogApp.config(['routeProvider', function(routeProvider) {
routeProvider.null when('/', {
controller: "noBlogController", null templateUrl: 'post.html',
}).when('/post/:id', {
controller: 'singlePostController',
templateUrl: 'singlepost.html',
});
}]);
noBlogApp.service('commentService', ['http', function(http) {
http.get('js/assureBlog.JSON').success(function(data) {
this.getComment = function(id) {
scope.comment = data[id];
return scope.comment;
}
var addComment = function() {
}
var addReply = function() {
}
var deleteComment = function() {
}
var deleteReply = function() {
}
});
}]);
noBlogApp.controller('noBlogController', ['scope', 'http', function(scope, http) {
scope.message = "hello";
http.get('js/assureBlog.JSON').success(function(data) {
scope.post = data;
});
}]);
nullnoBlogApp.controller('singlePostController', ['scope', 'http', 'routeParams', 'commentService', function(scope, http, routeParams, commentService) {
null http.get('js/assureBlog.JSON').success(function(data) {
scope.post = data[routeParams.id];
});
scope.commentService = commentService;
console.log("this is the" + commentService) null
}]);
noBlogApp.directive('comments', ["commentService", function(commentService) {
return {
scope: {
id: '#'
},
template: id: {
{
id
}
}
link: function(scope, element, attrs, commentService) {
console.log(scope.commentService);
}
};
}]);
Although the question is poorly formatted, it looks like your issue is this:
link:function(scope,element,attrs,commentService)
Remove the commentService from the link function. You've already added the dependency to the directive construction.

Resources