angularJS interceptor: access parent controller method - javascript

In my app i have different manipulations with http request's, for example:
$scope.getArticle = function(id) {
$http.get('/app/' + id, {
headers: {
'Content-Type': 'application/json',
}
})
.success(function(response) {
})
.error(function(data, status, headers, config) {
});
};
$scope.displayAlert = function (message) {
var modalHtml = '<div class="modal-header"><h3>Warning</h3></div>';
modalHtml += '<div class="modal-body"><strong>' + message + '</strong></div>';
modalHtml += '<div class="modal-footer"><button class="btn-md btn-green pull-right" ng-click="$dismiss()">OK</button></div>';
$scope.modalInstance = $modal.open({
template: modalHtml,
size: 'sm',
backdrop: 'static',
keyboard: false
});
$timeout(function () {
$scope.modalInstance.close('closing');
}, 5000);
};
and i have written such interceptor:
var responseError = function (rejection) {
var rootScope = rootScope || $injector.get('$rootScope');
console.log(rootScope.displayAlert('123'));
***
return $q.reject(rejection);
};
but how could i in this interceptor when i have error call $scope.displayAlert() method?
sure i could do it so:
$scope.getArticle = function(id) {
$http.get('/app/' + id, {
headers: {
'Content-Type': 'application/json',
}
})
.success(function(response) {
})
.error(function(data, status, headers, config) {
$scope.displayAlert('error');
});
};
but this is bad idea... how to be?

You can use the $rootScope along with $broadcast and $on as an event bus to communicate between components. Note that this may have performance impact, so you should take care when employing these methods.
in your service:
var responseError = function (rejection) {
var rootScope = rootScope || $injector.get('$rootScope');
....
$rootScope.$broadcast('responseError',{
message: 'Rejection Reason' });
and in the controller:
$scope.$on('responseError', function(event, data){
$scope.displayAlert(data.message); });

Related

Textbox binding not working when page has loaded AngularJS [duplicate]

This question already has answers here:
How to get promise result using AngularJS
(2 answers)
Closed 3 years ago.
I'm trying to set textbox value based on the result of promise values when page has loaded. The values on textbox set only if I click on it and then out of it (just like blur event).
Controller
(function() {
'use strict'
var newPurchasingCardController = function($scope, $rootScope, $filter, $window, $location, $timeout, requestService) {
$scope.actionTitle = "";
$scope.gin = "";
$scope.fullName = "";
$scope.workEmail = "";
$scope.msg = "";
var getCurrentUserData = function () {
var dfd = new $.Deferred();
var queryUrl = _spPageContextInfo.webAbsoluteUrl + "/_api/SP.UserProfiles.PeopleManager/GetMyProperties";
$.ajax({
url: queryUrl,
method: "GET",
headers: { "Accept": "application/json; odata=verbose" },
success: onSuccess,
error: onError,
cache: false
});
function onSuccess(data) {
dfd.resolve(data);
}
function onError(data, errorCode, errorMessage) {
dfd.reject(errorMessage);
}
return dfd.promise();
}
var _init = function () {
$scope.actionTitle = "New Card Request"
var promise = getCurrentUserData();
promise.then(function (data) {
$.each(data.d.UserProfileProperties.results,function(i,property){
if(property.Key === "EmployeeNumber")
{
$scope.gin = property.Value;
}
if(property.Key === "FirstName")
{
$scope.fullName = property.Value;
}
else if (property.Key === "LastName") {
$scope.fullName += " " + property.Value;
}
if(property.Key === "WorkEmail") {
$scope.workEmail = property.Value;
}
console.log(property.Key+":"+property.Value);
});
}, function(error) {
console.log("An error has occurred trying to get employee information." + error);
});
}
$scope.$on('$viewContentLoaded', function(event)
{
_init();
});
}
angular.module('myApp').controller('newPurchasingCardController', ['$scope', '$rootScope', '$filter', '$window', '$location', '$timeout', 'requestService', createnewPurchasingCardController]);
}());
And in the html view I just have
HTML
<input ng-model="gin" type="gin" class="form-control" id="gin" placeholder="GIN">
<input ng-model="fullName" type="name" class="form-control" id="name" placeholder="Name">
<input ng-model="workEmail" type="email" class="form-control" id="email" placeholder="Email">
I have tried with viewContentLoaded but not working, what would be a good approach to accomplish this? Thanks.
You are mixing angularjs with Jquery and that causes all the problems.
Use $http service for get request : https://docs.angularjs.org/api/ng/service/$http#get
var getCurrentUserData = function () {
var queryUrl = _spPageContextInfo.webAbsoluteUrl + "/_api/SP.UserProfiles.PeopleManager/GetMyProperties";
$http({
url: queryUrl,
method: "GET",
headers: { "Accept": "application/json; odata=verbose" },
cache: false
})
.then(function(response) {
$scope.gin = response.data.EmployeeNumber;
// here set scope variables directly
})
.catch(function(response) {
console.error('error', response.status, response.data);
})
.finally(function() {
console.log("finally ");
});
}

$http feed showing cannot read property 'protocol'

I'm at a loss on this. I have checked the forums and can't seem to find a solution.
I'm working on creating an ionic app to pull json feeds into the app and have them process. I have one feed setup, in one angular module, that is pulling some data perfectly fine. But when I try to create this second module, the feed var it errors, but if I hard code the URL in the $http.get it works fine.
This code errors with TypeError: Cannot read property 'protocol' of undefined:
angular.module('mwre.services', [])
.factory('PropertyFeed', function($http) {
var listings = {
residential: "http://somewebsite/api-access/get/mostwantedrealestate/categories/1?limit=2",
land: "http://somewebsite/api-access/get/mostwantedrealestate/categories/1?limit=2"
};
var content = "http://somewebsite/api-access/get/mostwantedrealestate/properties/"
return {
getPropertiesContent: function(section, successCallback, errorCallback){
$http.get(listings[section])
.success(function(data, status, headers, config) {
successCallback(data);
})
.error(function(data, status, headers, config) {
errorCallback(status);
});
},
getPropertyItem: function(id, successCallback, errorCallback){
$http.get(smalldesc + id)
.success(function(data, status, headers, config) {
successCallback(data);
})
.error(function(data, status, headers, config) {
errorCallback(status);
});
}
}
});
However, making the following change to the $http.get works:
angular.module('mwre.services', [])
.factory('PropertyFeed', function($http) {
var listings = {
residential: "http://somewebsite/api-access/get/mostwantedrealestate/categories/1?limit=2",
land: "http://somewebsite/api-access/get/mostwantedrealestate/categories/1?limit=2"
};
var content = "http://somewebsite/api-access/get/mostwantedrealestate/properties/"
return {
getPropertiesContent: function(section, successCallback, errorCallback){
$http.get("http://somewebsite/api-access/get/mostwantedrealestate/categories/1?limit=2")
.success(function(data, status, headers, config) {
successCallback(data);
})
.error(function(data, status, headers, config) {
errorCallback(status);
});
},
getPropertyItem: function(id, successCallback, errorCallback){
$http.get(smalldesc + id)
.success(function(data, status, headers, config) {
successCallback(data);
})
.error(function(data, status, headers, config) {
errorCallback(status);
});
}
}
});
I can't seem to figure out what I've got wrong in my code.
Here is the controller that is running that feed. It works perfectly fine when the URL is hardcoded.
angular.module('mwre.controllers', [])
.controller('PropertiesCtrl', function($scope, $state, $stateParams, $log, $ionicPopup, PropertyFeed) {
$scope.items = [];
$scope.successGetPropertiesContent = function(data) {
$scope.maxIntro = 100;
$scope.items = data.properties;
for (var i = 0; i < $scope.items.length; i++) {
$scope.items[i].smalldesc = $scope.items[i].smalldesc.replace(/<[^>]+>/gm, '');
if ($scope.items[i].smalldesc.length > $scope.maxIntro) {
$scope.items[i].smalldesc = $scope.items[i].smalldesc.substr(0, $scope.maxIntro) + '...';
}
}
};
$scope.errorGetPropertiesContent = function(status) {
$scope.showAlert = function() {
var alertPopup = $ionicPopup.alert({
title: 'Error reading property category content',
template: 'Please check your network connection'
});
alertPopup.then(function(res) {
$log.debug('Error reading property category content');
});
};
$scope.showAlert();
};
PropertyFeed.getPropertiesContent($stateParams.propertiesId, $scope.successGetPropertiesContent, $scope.errorGetPropertiesContent);
$scope.goToContent = function(id) {
$state.go('app.properties', { propertiesId: id });
};
})
.controller('PropertyCtrl', function($scope, $state, $stateParams, $log, $ionicPopup, PropertyFeed) {
$scope.item = null;
$scope.successGetPropertyItem = function(data) {
$scope.item = data;
};
$scope.errorGetPropertyItem = function(status) {
$scope.showAlert = function() {
var alertPopup = $ionicPopup.alert({
title: 'Error reading property listing',
template: 'Please check your network connection'
});
alertPopup.then(function(res) {
$log.debug('Error reading property listing');
});
};
$scope.showAlert();
};
PropertyFeed.getPropertyItem($stateParams.propertyId, $scope.successGetPropertyItem, $scope.errorGetPropertyItem);
});

AngularJS function from service is being called twice

I'm having trouble running a function from a service, because it is being called twice.
I've noticed that most of the problems of this nature are because people tend to call their controller twice (one time in the router and another in the view with ng-controller). But I checked, and my controller is not being invoked twice. Also: only on function from the service is being called twice.
Here it is:
.factory('findingsService', ['$http', '$log', '$q', '$cookies', function ($http, $log, $q, $cookies) {
return {
// THIS FUNCTION IS WORKING FINE!
list_findings: function(examId) {
var defer = $q.defer();
var session_token = $cookies.get('ACCESS_TOKEN');
$http.get(WS + URI_FINDINGS, {
headers: {
'sessionToken': session_token,
'Content-Type': 'application/json'
},
params: {
'examId': examId
}
})
.then(function (response) {
defer.resolve(response.data);
})
.catch(function (data) {
defer.reject(data);
});
return defer.promise;
},
// THIS FUNCTION IS BEING CALLED TWICE
attach_findings_to_exam: function(examId, findingsObj) {
var defer = $q.defer();
var session_token = $cookies.get('ACCESS_TOKEN');
$http.post(WS + URI_FINDINGS, findingsObj, {
headers: {
'sessionToken': session_token,
'Content-Type': 'application/json'
},
params: {
'examId': examId
}
})
.then(function (response) {
defer.resolve(response.data);
})
.catch(function (data) {
defer.reject(data);
});
return defer.promise;
}
}
}])
Since it's the same service and only one function is being called twice, and think that discarding the controller issue is fine. Can it be something about the global configuration of the $http.post?

Angular: Retrieve updated value in directive

I am filling my template named commentRecipe.html with data.
And i can call controller.add(1,2,'comment here') from inside the template.
The item gets updated in the db and returns my new result.
The Question is: How can i update ex mhRecipeId with the retrieved data.
var app = angular.module('myApp');
app.directive('mhCommentRecipe', ['$log', 'commentService', function ($log, commentService) {
var commentController = function () {
var that = this;
that.add = function (commentId, recipeId, commentText) {
if (recipeId && commentText.length > 0) {
var resultObj = commentService.add(commentId, recipeId, commentText);
}
};
}
return {
restrict: 'A',
templateUrl: '/app/templates/commentRecipe.html',
scope: {
mhRecipeId: '=',
mhCommentId: '=',
mhCommentText: '='
},
controller: commentController,
controllerAs: 'controller'
}
}]);
(function () {
app.factory('commentService', [
'$log', 'httpService', function ($log, httpService) {
var baseEndpointPath = '/myRecipes';
return {
add: function (commentId, recipeId, commentText) {
$log.debug(commentId, 'c');
var data = {
commentId,
recipeId,
commentText
}
var promise = httpService.post(baseEndpointPath + '/comment', data);
promise.then(function (response) {
// added
},
function (error) {
$log.error(error);
});
},
remove: function (commentId) {
if (commentId) {
var data = {
commentId,
recipeId,
commentText
}
data.commentId = commentId;
var promise = httpService.post(baseEndpointPath + '/removeComment', data);
promise.then(function (response) {
$log(response, 'removed response');
},
function (error) {
$log.error(error);
});
}
}
};
}
]);
})();
app.factory('httpService', ['$http', '$q',
function ($http, $q) {
return {
get: function (endpoint) {
var deferred = $q.defer();
$http.get(endpoint)
.success(function (response) {
deferred.resolve(response);
})
.error(function () {
deferred.reject('Failed to fetch response from endpoint');
});
return deferred.promise;
},
post: function (endpoint, data, config) {
var deferred = $q.defer();
$http.post(endpoint, data, config)
.success(function (response) {
deferred.resolve(response);
})
.error(function () {
deferred.reject('Failed to post data to endpoint');
});
return deferred.promise;
},
put: function (endpoint, data, config) {
var deferred = $q.defer();
$http.put(endpoint, data, config)
.success(function (response) {
deferred.resolve(response);
})
.error(function () {
deferred.reject('Failed to put data to endpoint');
});
return deferred.promise;
}
};
}]);
You place the values you want to send to the directive into a variable:
// in controller
that.mhRecipeId = whateverValueHere;
that.mhCommentId = whateverValueHere;
that.mhCommentText = 'comment text';
then on the directive in html you would put:
<mh-comment-recipe mh-recipe-id="controller.mhRecipeId" mh-comment-id="controller.mhCommentId" mh-comment-text="controller.mhCommentText"></mh-comment-recipe>
This will pass the variables into the directive for use.
Unless I misunderstood your question :)
Solved the issue and i am quite embarrassed to tell the solution!
In my view i just used ex: mhRecipeId when i should have used the controllers value.

AngularJS $http.delete broke in "TypeError: Cannot assign to read only property 'method' .."

I'm new to JavaScript and AngularJS. I'm tryin' to build up a very simple CRUD application. Here is the code of my controller:
(function() {
var app = angular.module('form.user', []);
app.directive('formusergui', [function(){
return {
restrict: 'E',
templateUrl: './js/views/user.form.html',
controller: function($scope, $http) {
this.formToBean = function() {
var ent = {};
ent.id = null;
ent.name = $scope.name;
ent.desc = $scope.desc;
ent.reg = Date.now;
ent.linkImgProfile = null;
ent.type = null;
return ent;
};
this.create = function() {
$http.post('./services/users', JSON.stringify(this.formToBean()))
.success(function(data, status, headers, config) {
$scope.esito = "success: " + JSON.stringify(data);
})
.error(function(data, status, headers, config) {
$scope.esito = "error: " + JSON.stringify(data);
});
};
this.delete = function() {
$http.delete('./services/users', JSON.stringify(this.formToBean()))
.success(function(data, status, headers, config) {
$scope.esito = "success: " + JSON.stringify(data);
})
.error(function(data, status, headers, config) {
$scope.esito = "error: " + JSON.stringify(data);
});
};
...
},
controllerAs: 'userForm'
};
}]);
})();
formToBean function collects data by the form. As the create function works well (REST service is called), the delete function broke with this error:
TypeError: Cannot assign to read only property 'method' of {"id":null,"name":"john","desc":"doe","linkImgProfile":null,"type":null}
I found similar questions about this kind of error but still I can't get what's going wrong.
for the delete method in the $http, the second parameter is a configuration, in your request instead of configuration related data, simple the json object is passed, refer the api for the $http.delete
https://docs.angularjs.org/api/ng/service/$http#delete
$http.delete('./services/users/:idtodelete')
.success(function(data, status, headers, config) {
$scope.esito = "success: " + JSON.stringify(data);
});

Categories

Resources