I have a question about the directives and the .then method.
Here is my controller code (I use it to pass variables to my directive) :
angular
.module('thermofluor')
.controller('ExperimentsController', ExperimentsController)
ExperimentsController.$inject = ['$state', '$stateParams', 'PlatesService', '$timeout', '$q', '$scope'];
function ExperimentsController($state, $stateParams, PlatesService, $timeout, $q, $scope) {
var exp = this;
//console.log($stateParams);
exp.barcode = $stateParams.barcode;
exp.plate = $stateParams.plate;
exp.current_user = "";
exp.users = [];
exp.curves = [];
exp.summary = [];
exp.selected_wells = [];
// liste experiments
console.log($stateParams.id);
getPlateById($stateParams.id);
function getUsers()
{
$timeout(function() {
exp.users = PlatesService.customShow(exp.plate.id, "users")
.then(getUsers)
.catch(getUsersFailed);
function getUsers ( data ) {
exp.users = data[0];
return exp.users;
}
function getUsersFailed ( e ) {
var newMessage = 'Failed To Retrieve the users';
if (e.data && e.data.description) {
newMessage = newMessage + '\n' + e.data.description;
}
console.log( e );
e.data = newMessage;
return $q.reject(e);
}
});
}
function getPlateById(id)
{
$timeout(function() {
exp.plate = PlatesService.show(id)
.then(getPlate)
.catch(getPlateFailed);
function getPlate ( data ) {
exp.plate = data;
exp.curves[exp.plate.experiments[0].well] = [exp.plate.experiments[0].points, exp.plate.experiments[0].tm];
getUsers();
return exp.plate;
}
function getPlateFailed ( e ) {
var newMessage = 'Failed To Retrieve the plate';
if (e.data && e.data.description) {
newMessage = newMessage + '\n' + e.data.description;
}
console.log( e );
e.data = newMessage;
return $q.reject(e);
}
});
}
}
1 - I have a simple directive :
angular
.module('thermofluor')
.directive('legend', legend)
legend.$inject = ['$timeout', '$q'];
function legend($timeout, $q) {
var directive = {
link: link,
restrict: 'E',
templateUrl: '/crims/thermofluor/experiments/legend.html',
scope: {
selected_wells: '=',
current_user: '=',
plate: '='
}
};
return directive;
function link(scope, element) {
console.log("TESTT");
console.log(scope);
scope.plate.then(function (res) {
console.log(scope.selected_wells);
});
}
}
What I don't understand is why the selected_wells and current_user are empty and the plate is not empty. And also why sometimes I have one of these two errors:
TypeError: Cannot read property 'then' of null
TypeError: Cannot read property 'then' of undefined
I thinks it's because the plate is not already loaded (it's loaded by an ajax call) but it's not the utility of the .then to launch the function after the object load ?
Edit:
Here is the PlateService (I use restangular) :
angular.module('thermofluor')
.factory( 'PlatesService', PlatesService);
PlatesService.$inject = ['Restangular', 'RepositoryService', '$cacheFactory', 'tmConfig', 'tmCache'];
function PlatesService( Restangular, RepositoryService, $cacheFactory, tmConfig, tmCache )
{
RepositoryService.extend( PlatesService )
return new PlatesService();
function PlatesService()
{
var service = this;
var cache = tmCache.plates();
//Restangular.setDefaultRequestParams({api_token: ChiefService.getCurrentToken()});
RepositoryService.call(service, Restangular.withConfig( config ), 'plates', cache );
return service;
function config( RestangularConfigurer )
{
Restangular.setDefaultHttpFields({cache: cache});
return RestangularConfigurer.setBaseUrl(tmConfig.api);
}
}
}
And this plateservice use this RepositoryService
function RepositoryService( $cacheFactory)
{
RepositoryService.prototype = {
all:all,
filterAll:filterAll,
show:show,
customShow:customShow,
store:store,
update:update,
destroy:destroy,
restore:restore,
};
RepositoryService.extend = function (repository) {
repository.prototype = Object.create(RepositoryService.prototype);
repository.prototype.constructor = repository;
};
return RepositoryService;
function RepositoryService(restangular, route, cache)
{
console.log( cache );
this.restangular = restangular;
this.route = route;
this.cache = cache;
}
function all()
{
return this.restangular.all(this.route).getList();
}
function filterAll( filters )
{
return this.restangular.all(this.route).customGETLIST('', filters );
}
function show(uuid)
{
return this.restangular.one(this.route, uuid ).get();
}
function customShow(uuid, extend)
{
return this.restangular.one(this.route, uuid).customGET( extend );
}
function store( resource )
{
clear( this.cache );
return this.restangular.all(this.route).post( resource );
}
function update( resource )
{
clear( this.cache );
return this.restangular.one(this.route, resource.uuid).customPUT( resource );
}
function destroy( resource )
{
clear( this.cache );
return this.restangular.one(this.route, resource.uuid).remove();
}
function restore( resource )
{
clear( this.cache );
return this.restangular.all(this.route + '/' + resource.uuid + '/restore' ).post();
}
function clear( cache )
{
if(_.isUndefined( cache )) {
return;
}
cache.removeAll();
}
}
Related
I have an existing project in AngularJS. There is an HTML page with client address. Its markup is:
<div class="text-left m-t-lg">
<h5>
Address
</h5>
<address>
<div ng-show="customerInfo.companyName != ''"><small>{{customerInfo.companyName}}</small><br /></div>
<div ng-show="customerInfo.customerName != ''"><small>{{customerInfo.customerName}}</small><br /></div>
<div ng-show="customerInfo.address != ''"><small>{{customerInfo.address}}</small><br /></div>
<div ng-show="customerInfo.email != ''"><small>{{customerInfo.email}}</small></div>
</address>
</div>
The directive:
app.directive('addressHeader', function () {
return {
scope: {
addressHeaderInfo: '=info'
},
templateUrl: 'address/addressHeader.html',
controller: 'addressHeaderController',
controllerAs: 'ahc'
};
});
My issue is In addressHeaderController.js I don't see addressHeaderInfo or info or customerInfo object. I need to update this object. Where is this object initialized from? I don't know much about AngularJS.
Controller:
app.controller('addressHeaderController', ['$http', 'APIService', '$scope', '$stateParams', '$sessionStorage', '$translate', '$state', '$rootScope', '$timeout', '$locale', 'tmhDynamicLocale',
function ($http, APIService, $scope, $stateParams, $sessionStorage, $translate, $state, $rootScope, $timeout, $locale, tmhDynamicLocale) {
var ctl = this;
$scope.followingAddress = false;
$scope.followData = {};
$scope.issueDisplay = '';
$scope.showResend = true;
$scope.showLoyaltyColumn = $sessionStorage.userObject.clientInfo.showLoyaltyColumnOnSurveyDetail;
ctl.isOpen = false;
ctl.dateOptions = { showWeeks: false };
$scope.businessUnits = null;
$scope.targetDealership = null;
$scope.realignComment = null;
$scope.$watch('addressHeaderInfo', function () {
debugger;
//Where is $scope.addressHeaderInfo coming from?
if (typeof ($scope.addressHeaderInfo) != 'undefined') {
//Some operations here. Not related to assigning anything to $scope.
}
});
function getDepartmentData() {
//No assignment here as well.
}
$scope.resendData = function () {
if ($sessionStorage.clientObject.requiresResendJustification) {
$('#resendJustificationModal').modal('show');
}
else {
var resendData = {};
resendData.recordId = $scope.addressHeaderInfo.addressID;
resendData.statusId = 24;
APIService.postData(resendData, 'Address/UpdateResendStatus')
.then(function (data) {
if (data.status == 200) {
$rootScope.$broadcast('resendRequest');
}
else {
toastr["error"]('Error');
}
});
}
}
$scope.nextAddress = function () {
$rootScope.$broadcast('addressNavigation', $scope.AddressList[$scope.recordNumber]);
$scope.recordNumber = $scope.recordNumber + 1;
}
$scope.previousAddress = function () {
$rootScope.$broadcast('addressNavigation', $scope.AddressList[$scope.recordNumber-2]);
$scope.recordNumber = $scope.recordNumber - 1;
}
$scope.followAddress = function () {
APIService.postData($scope.addressHeaderInfo, 'Address/follow')
.then(function (data) {
if (data.status == 200) {
toastr["success"]($translate.instant('AddressFollowedSaved'));
$scope.followData = data.data;
$scope.followingAddress = true;
}
else {
toastr["error"]($translate.instant('AddressFollowedErrored'));
}
})
}
$scope.unfollowAddress = function () {
APIService.deleteData('Address/follow/' + $scope.followData.AddressFavoriteId)
.then(function (data) {
if (data.status == 200) {
toastr["success"]($translate.instant('AddressUnfollowedSaved'));
$scope.followingAddress = false;
}
else if (data.status == 500) {
toastr["error"]($translate.instant('AddressUnfollowedErrored'));
}
});
}
$scope.AddressReminder = function () {
$('#setReminderPopup').modal('show');
}
$scope.saveReminder = function () {
$scope.followData.notificationDate = $scope.followData.displayDate;
APIService.postData($scope.followData, 'Address/follow/reminder')
.then(function (data) {
if (data.status == 200) {
toastr["success"]($translate.instant('AddressReminderSaved'));
$('#setReminderPopup').modal('hide');
}
else {
toastr["error"]($translate.instant('AddressReminderErrored'));
}
})
}
$scope.realignAddress = function () {
if ($scope.addressHeaderInfo) {
if (!$scope.businessUnits) {
getBusinessUnits();
}
var bu = $scope.addressHeaderInfo.businessUnit;
if (bu) {
bu.realignDisplayName = bu.name + ', ' + bu.shippingCity + ', ' + bu.suppliedBusinessUnitNumber;
}
$scope.realignComment = null;
$('#realignPopup').modal('show');
}
}
$scope.saveRealignRequest = function () {
var realignedAddress = $scope.addressHeaderInfo;
var realignData = {
AddressId: $scope.addressHeaderInfo.AddressID,
businessUnitId: $scope.targetDealership.businessUnitID,
notes: $scope.realignComment
};
APIService.postData(realignData, 'Address/requestRealignment')
.then(function (data) {
if (data.status == 200) {
toastr["success"]($translate.instant('AddressRealignRequestSaved'));
$('#realignPopup').modal('hide');
realignedAddress.realignmentStatus = 'Pending'; // cause Realign button to disappear and "Realignment is pending" message to show
} else {
toastr["error"]($translate.instant('AddressRealignRequestErrored'));
}
});
}
$scope.$on('advanceToNextIssue', function (event, data) {
if ($scope.AddressList && ($scope.recordNumber < $scope.AddressList.length)) {
$scope.nextAddress();
}
});
}]);
My html code is as follows.
<div class="panel-heading">
Select areas to be visited by the operator
<multiselect ng-model="selection" options="areanames" show-search="true"></multiselect>
</div>
My application's controller code is as follows. The function getArea is being called when a user inputs some details in the form (not included here).
this.getArea = function(){
$scope.areanames = [];
$http({
method: "GET",
url: "http://xx.xx.xx.xx/abc",
params:{city:$scope.city,circle:$scope.circle}
}).then(function(success){
for (i = 0; i < success.data.length; i++)
$scope.areanames.push(success.data[i].area);
},function(error){
console.log('error ' + JSON.stringify(error));
});
}
The directive multiselect is written as follows.
multiselect.directive('multiselect', ['$filter', '$document', '$log', function ($filter, $document, $log) {
return {
restrict: 'AE',
scope: {
options: '=',
displayProp: '#',
idProp: '#',
searchLimit: '=?',
selectionLimit: '=?',
showSelectAll: '=?',
showUnselectAll: '=?',
showSearch: '=?',
searchFilter: '=?',
disabled: '=?ngDisabled'
},
replace:true,
require: 'ngModel',
templateUrl: 'multiselect.html',
link: function ($scope, $element, $attrs, $ngModelCtrl) {
$scope.selectionLimit = $scope.selectionLimit || 0;
$scope.searchLimit = $scope.searchLimit || 25;
$scope.searchFilter = '';
if (typeof $scope.options !== 'function') {
$scope.resolvedOptions = $scope.options;
}
if (typeof $attrs.disabled != 'undefined') {
$scope.disabled = true;
}
$scope.toggleDropdown = function () {
console.log('toggleDown');
$scope.open = !$scope.open;
};
var closeHandler = function (event) {
console.log('closeHandler');
if (!$element[0].contains(event.target)) {
$scope.$apply(function () {
$scope.open = false;
});
}
};
$document.on('click', closeHandler);
var updateSelectionLists = function () {
console.log('updateSelectionList');
if (!$ngModelCtrl.$viewValue) {
if ($scope.selectedOptions) {
$scope.selectedOptions = [];
}
$scope.unselectedOptions = $scope.resolvedOptions.slice(); // Take a copy
} else {
$scope.selectedOptions = $scope.resolvedOptions.filter(function (el) {
var id = $scope.getId(el);
for (var i = 0; i < $ngModelCtrl.$viewValue.length; i++) {
var selectedId = $scope.getId($ngModelCtrl.$viewValue[i]);
if (id === selectedId) {
return true;
}
}
return false;
});
$scope.unselectedOptions = $scope.resolvedOptions.filter(function (el) {
return $scope.selectedOptions.indexOf(el) < 0;
});
}
};
$ngModelCtrl.$render = function () {
console.log('render called');
updateSelectionLists();
};
$ngModelCtrl.$viewChangeListeners.push(function () {
console.log('viewChangeListener');
updateSelectionLists();
});
$ngModelCtrl.$isEmpty = function (value) {
console.log('isEmpty');
if (value) {
return (value.length === 0);
} else {
return true;
}
};
var watcher = $scope.$watch('selectedOptions', function () {
$ngModelCtrl.$setViewValue(angular.copy($scope.selectedOptions));
}, true);
$scope.$on('$destroy', function () {
console.log('destroy');
$document.off('click', closeHandler);
if (watcher) {
watcher(); // Clean watcher
}
});
$scope.getButtonText = function () {
console.log('getButtonText');
if ($scope.selectedOptions && $scope.selectedOptions.length === 1) {
return $scope.getDisplay($scope.selectedOptions[0]);
}
if ($scope.selectedOptions && $scope.selectedOptions.length > 1) {
var totalSelected;
totalSelected = angular.isDefined($scope.selectedOptions) ? $scope.selectedOptions.length : 0;
if (totalSelected === 0) {
return 'Select';
} else {
return totalSelected + ' ' + 'selected';
}
} else {
return 'Select';
}
};
$scope.selectAll = function () {
console.log('selectAll');
$scope.selectedOptions = $scope.resolvedOptions;
$scope.unselectedOptions = [];
};
$scope.unselectAll = function () {
console.log('unSelectAll');
$scope.selectedOptions = [];
$scope.unselectedOptions = $scope.resolvedOptions;
};
$scope.toggleItem = function (item) {
console.log('toggleItem');
if (typeof $scope.selectedOptions === 'undefined') {
$scope.selectedOptions = [];
}
var selectedIndex = $scope.selectedOptions.indexOf(item);
var currentlySelected = (selectedIndex !== -1);
if (currentlySelected) {
$scope.unselectedOptions.push($scope.selectedOptions[selectedIndex]);
$scope.selectedOptions.splice(selectedIndex, 1);
} else if (!currentlySelected && ($scope.selectionLimit === 0 || $scope.selectedOptions.length < $scope.selectionLimit)) {
var unselectedIndex = $scope.unselectedOptions.indexOf(item);
$scope.unselectedOptions.splice(unselectedIndex, 1);
$scope.selectedOptions.push(item);
}
};
$scope.getId = function (item) {
console.log('getID');
if (angular.isString(item)) {
return item;
} else if (angular.isObject(item)) {
if ($scope.idProp) {
return multiselect.getRecursiveProperty(item, $scope.idProp);
} else {
$log.error('Multiselect: when using objects as model, a idProp value is mandatory.');
return '';
}
} else {
return item;
}
};
$scope.getDisplay = function (item) {
console.log('getDisplay');
if (angular.isString(item)) {
return item;
} else if (angular.isObject(item)) {
if ($scope.displayProp) {
return multiselect.getRecursiveProperty(item, $scope.displayProp);
} else {
$log.error('Multiselect: when using objects as model, a displayProp value is mandatory.');
return '';
}
} else {
return item;
}
};
$scope.isSelected = function (item) {
console.log('isSelected');
if (!$scope.selectedOptions) {
return false;
}
var itemId = $scope.getId(item);
for (var i = 0; i < $scope.selectedOptions.length; i++) {
var selectedElement = $scope.selectedOptions[i];
if ($scope.getId(selectedElement) === itemId) {
return true;
}
}
return false;
};
$scope.updateOptions = function () {
console.log('updateOptions');
if (typeof $scope.options === 'function') {
$scope.options().then(function (resolvedOptions) {
$scope.resolvedOptions = resolvedOptions;
updateSelectionLists();
});
}
};
// This search function is optimized to take into account the search limit.
// Using angular limitTo filter is not efficient for big lists, because it still runs the search for
// all elements, even if the limit is reached
$scope.search = function () {
console.log('search');
var counter = 0;
return function (item) {
if (counter > $scope.searchLimit) {
return false;
}
var displayName = $scope.getDisplay(item);
if (displayName) {
var result = displayName.toLowerCase().indexOf($scope.searchFilter.toLowerCase()) > -1;
if (result) {
counter++;
}
return result;
}
}
};
}
};
}]);
When areanames is getting updated asynchronously its values are not getting displayed in multiselect. The inner scope's options value is becoming undefined though I am using '=' with same attribute name i.e., options in the html code.
I have a template and I'm changing the way to Inject dipendecies. It has the 'classic' way to inject. I want to replace it with the compact form. I can't do these line of code. I've tried but I can't understand the struscture. Because I am accustomed in the other form. Can somebody help me?
(function() {
'use strict';
angular.module('app.data')
.factory('postResource', postResource)
.factory('postsUtils', postsUtils);
postResource.$inject = ['$resource'];
function postResource($resource) {
return $resource('/api/posts/:id', {id: '#id'}, {
update: {
method: 'PUT'
}
});
}
postsUtils.$inject = ['postResource'];
function postsUtils(postResource) {
function postsDuringInterval(posts, days) {
var today = new Date();
var interval = 86400000 * days;
var postsDuringInterval = [];
posts.forEach(function(post) {
var postDate = new Date(post.date);
today - postDate < interval && postsDuringInterval.push(post);
});
return postsDuringInterval;
}
function recent(posts, postsNum) {
posts.sort(function(a, b) {
if (a.date < b.date) return 1;
else if (a.date == b.date) return 0;
else return -1;
});
return posts.slice(0, postsNum || 1);
}
function lastEdited(posts) {
var lastEdited = posts[0];
posts.forEach(function(post) {
lastEdited = lastEdited.date < post.date ? lastEdited : post;
});
return lastEdited;
}
return {
postsDuringInterval: postsDuringInterval,
lastEdited: lastEdited,
recent: recent
}
}
})();
Here is an example of how you would inject dependencies.
var app = angular.module('myApp',
['ngRoute', 'ngSanitize', 'ui.bootstrap', 'angular-flexslider',
'ng-backstretch', 'angular-parallax', 'fitVids', 'wu.masonry', 'timer',
'uiGmapgoogle-maps', 'ngProgress']);
An example of a controller that has a service injected into it.
app.controller('ContactController',['$scope','contactService',
function($scope, contactService) {
var self = this;
self.contact = {id:null, name:"",lastName:"",email:"",subject:"",message:""};
this.submit = function(){
contactService.submit(self.contact);
self.contact = {id:null, name:"",lastName:"",email:"",subject:"",message:""};
};
}]);
The factory:
app.factory('contactService',['$http','$q', function($http,$q){
return {
submit: function (contact) {
return $http.post('/sendForm/', contact)
.then(
function (response) {
return response;
},
function (errResponse) {
console.error("Error while submitting form" + errResponse);
return $q.reject(errResponse);
}
)
}
}
}]);
I think this is the way you were referring too. Hope this helps.
I have a function which makes a service call. I have the code like below. But from success function i am unable to return the data back to calling function. How do i do this?
$scope.getData = function()
{
var successFunc = function(serverResponse)
{
if(serverResponse.header.status === "success" )
{
return serverResponse.data;
}
else
{
errorFunc("Error occured:");
}
}
var errorFunc = function(jsonResponse)
{
console.log( "Error occured:" + JSON.stringify(jsonResponse));
};
utils.svcall('abc/new', successFunc, errorFunc);
};
var data = $scope.getData();
Prettyphoto stopped working after I changed the href url to an angular tag: {{something.uri}}
Javascript:
jQuery(".prettyphoto").prettyPhoto({
theme: 'pp_default',
overlay_gallery: false,
social_tools: false,
deeplinking: false,
theme: 'dark_rounded'
});
$("a[rel^='prettyPhoto']").prettyPhoto();
HTML:
<div ng-show="model.fileList" ng-repeat="fileList in model.fileList">
<a ng-href="{{fileList.uri}}" class="prettyphoto">
<img ng-src="{{fileList.uri}}" class="img-thumbnail" width="100" alt="" />
</a>
</div>
Angular scope from blobstorage:
fileList: [
{
parentContainerName: documents
uri: https://xxxxxx.blob.core.windows.net/documents/20140702.jpg
filename: 20140702.jpg
fileLengthKilobytes: 293
}
]
app.factory('storageService',
["$http", "$resource", "$q",
function ($http, $resource, $q) {
//resource to get summaryRoles
var resourceStorageManager = $resource('/api/storageManager/:id', { id: '#id' });
return {
getFileList: function () {
var deferred = $q.defer();
resourceStorageManager.query(, function (data) {
deferred.resolve(data);
}, function (status) {
deferred.reject(status);
}
);
return deferred.promise;
}
};
}]);
app.controller('startController', ['$scope', '$http', '$timeout', '$upload', 'storageService', 'settings',
function startController($scope, $http, $timeout, $upload, storageService, settings, profileRepository, notificationFactory, $q) {
$http.defaults.headers.common = { 'RequestVerificationToken': $scope.__RequestVerificationToken };
$scope.model = {};
$scope.model.fileList = null;
$scope.model.roundProgressData = {
label: 0,
percentage: 0.0
};
$scope.$on("pic_profileone_main", function (event, profileExtInfo1) {
$scope.changeprofilepicmodel1 = angular.copy(profileExtInfo1);
refreshServerFileList();
});
$scope.$on("pic_profiletwo_main", function (event, profileExtInfo2) {
$scope.changeprofilepicmodel2 = angular.copy(profileExtInfo2);
refreshServerFileList2();
});
$scope.onFileSelect = function ($files, callernumber, foldername, blobtype) {
if (callernumber == 1) {
$scope.blobModel = angular.copy($scope.changeprofilepicmodel1);
$scope.blobModel.folderName = foldername;
$scope.blobModel.blobTypeCode = blobtype;
} else if (callernumber == 2) {
$scope.blobModel = angular.copy($scope.changeprofilepicmodel2);
$scope.blobModel.folderName = foldername;
$scope.blobModel.blobTypeCode = blobtype;
}
$scope.selectedFiles = [];
$scope.model.progress = 0;
// Assuming there's more than one file being uploaded (we only have one)
// cancel all the uploads
if ($scope.upload && $scope.upload.length > 0) {
for (var i = 0; i < $scope.upload.length; i++) {
if ($scope.upload[i] != null) {
$scope.upload[i].abort();
}
}
}
$scope.upload = [];
$scope.uploadResult = [];
$scope.selectedFiles = $files;
// Ok, we only want one file to be uploaded
// let's take the first one and that's all
var $file = $files[0];
// Only first element, single file upload
(function (index) {
$scope.upload[index] = $upload.upload({
url: settings.constants.uploadURL,
headers: { 'myHeaderKey': 'myHeaderVal' },
method: 'POST',
data: $scope.blobModel,
file: $file,
fileFormDataName: 'myFile'
}).then(function (response) {
var look = response;
$scope.model.progress = 100;
// you could here set the model progress to 100 (when we reach this point we now that the file has been stored in azure storage)
$scope.uploadResult.push(response.data);
$scope.$emit('ClearUploadPics');
refreshServerFileList();
}, null, function (evt) {
// Another option is to stop here upadting the progress when it reaches 90%
// and update to 100% once the file has been already stored in azure storage
$scope.model.progress = parseInt(100.0 * evt.loaded / evt.total);
$scope.model.roundProgressData.label = $scope.model.progress + "%";
$scope.model.roundProgressData.percentage = ($scope.model.progress / 100);
});
})(0);
};
function refreshServerFileList() {
storageService.getFileList().then(function (data) {
$scope.model.fileList = data;
}
);
}
function initialize() {
refreshServerFileList();
}
initialize();
$scope.$on("ClearProgressBar", function (event) {
$scope.selectedFiles = null;
});
}]);
I hope this is okay and more readable.