AngularJS: basic error-handling - javascript

I would like to reflect post request status by showing/hiding success/error html element with the error description. I have following controller with use of $http service:
$ctrl.addCorporateTransport = function() {
var postStatusBar = angular.element('postStatusBar');
$http.post('/post_corporate_transport', $ctrl.corporateTransport)
.success(function () {
// throw success alert
})
.error(function (error) {
// throw error alert
});
};
I'm looking for having possibility to throw <div class="alert"><p>my error here</p> if I hit error callback.
I tried this:
var statusBar = angular.element('postStatusBar');
//...
.success(function () {
statusBar.setClass("alert-success")
})
.error(function (error) {
statusBar.setClass("alert-danger");
statusBar.setParameter("text", error);
});
But it doesn't work obviously and looks like anti-pattern. What is the best solution for doing the thing?

If the alert component is outside controller scope than you need make the alert a directive and use broadcast to notify and update properties like visibility.
else you can bind properties from controller like:
<div ng-controller="AwesomeController as AwesomeCtrl">
<div class="alert" ng-show="AwesomeCtrl.show.error">....
<div class="alert" ng-show="AwesomeCtrl.show.success">....
<div class="alert" ng-class="{ 'succes' : AwesomeCtrl.show.success }">....
enter code here
angular
.module('app')
.controller('AwesomeController', controller);
controller.$inject = ['$http'];
function controller($http) {
var vm = this;
vm.corporateTransport = {};
vm.show = {
error = false;
success = false;
}
vm.oneCoolMethod = addCorporateTransport;
// test
addCorporateTransport();
function addCorporateTransport() {
$http.post('/post_corporate_transport', vm.corporateTransport)
.success(onTransportSuccess)
.error(onTransportError);
};
function onTransportSuccess(result) {
toggleAlert('success');
}
function onTransportError(result) {
toggleAlert('error');
}
function toggleAlert(level) {
angular.forEach(vm.show, function(value, key) {
vm.show[key] = false;
});
vm.show[level] = true;
}

at the first you must using $scope.statusBar
and also addClass except setClass

Related

Call function in angular controller after clickin on a dynamiclly created element in DOM

Hi I want to call a function after clicking on a button which is added to dom after angular is loaded. I dont know if this is possible in the way I am trying it, but I do know that my current code doesn't call the alert function.
After sending a search request to my backend, I get a list data entrys, which I display as hrefs.
my_form.setAttribute("href", result[i].url)
my_form.setAttribute("ng-href",'#here')
my_form.setAttribute("ng-click", "alert(1)")
my_form.setAttribute("style", "display:block;")
results in
John Doe
Complete Code:
var appModule = angular.module('graph', [])
appModule.controller('graphCtrl', ['$scope', '$http', '$compile', function ($scope, $http, $compile) {
$scope.search = function () {
var data = {
}
$http.get('/api/search/?q=' + $scope.searchfield, data).success(function (data, status, headers, config) {
var result = data;
var searchResultsContainer = document.getElementById("dropdownId");
while (searchResultsContainer.firstChild) {
searchResultsContainer.removeChild(searchResultsContainer.firstChild);
}
for (i in result) {
var my_form = document.createElement("a");
my_form.setAttribute("href", result[i].url)
my_form.setAttribute("ng-href",'#here')
my_form.setAttribute("ng-click", "alert(1)")
my_form.setAttribute("style", "display:block;")
my_text = document.createTextNode(result[i].caption)
my_form.appendChild(my_text)
searchResultsContainer.appendChild(my_form)
}
})
}
$scope.alert = function(){
alert("Hello! I am an alert box!!");
}
}

Angular infinite scroll adding broken directive templates every time it gets new data

I am working on a social feed that displays charitable activities. It's supposed to look like the second activity in this image:
But as you can see, every time that angular-infinite-scroll goes to fetch the next batch of activities, it adds a broken template to the top of the feed.
This is the function that's called to get more activities:
feedService.prototype.nextPage = function () {
var fs = this;
if (fs.busy) return;
fs.busy = true;
fs.params.limit = fs.params.limit || _feedLimit;
if (fs.activities.length > 0)
fs.params.idLessThan = fs.activities[fs.activities.length - 1].id;
$http({ url: serviceBase + 'api/stream/getflatfeed', method: 'GET', params: fs.params })
.then(function (response) {
var feed = response.data;
console.dir(feed.results);
console.dir(fs.activities);
if (feed) {
fs.duration = feed.duration;
fs.gStreamMessage = feed.gStreamMessage;
fs.unread = feed.unread;
fs.unseen = feed.unseen;
fs.noMoreActivity = false;
if (response.data.results && response.data.results.length === 0)
fs.noMoreActivity = true;
else {
var acts = _decorateFeedActivities(response.data.results, fs.params);
acts.forEach(function (act) {
var alreadyExists = false;
fs.activities.forEach(function (e, i) {
if (e.id === act.id) {
console.log('alreadyExists!');
alreadyExists = true;
}
});
if (!alreadyExists) {
fs.activities.push(act);
}
});
};
}
fs.busy = false;
}.bind(this));
};
This is the directive used for activities:
feedModule.directive('feedCard', ['$compile', '$http', '$filter', function ($compile, $http, $filter) {
var getTemplate = function (contentType) {
var templateLoader,
baseUrl = 'app/areas/feed/cards/',
templateMap = {
donated: 'general-donation-card-tpl.html',
image: 'image-card-tpl.html',
video: 'video-card-tpl.html',
quote: 'quote-card-tpl.html',
link: 'link.html',
chat: 'chat.html',
audio: 'audio.html',
answer: 'answer.html'
};
var templateUrl = baseUrl + templateMap[contentType];
templateLoader = $http.get(templateUrl);
return templateLoader;
};
return {
restrict: 'E',
scope: {
activity: '=',
user: '='
},
replace: true,
link: linker
};
function linker(scope, element) {
var loader = getTemplate(scope.activity.verb);
var promise = loader.success(function (html) {
element.html(html);
}).then(function (response) {
element.replaceWith($compile(element.html())(scope));
console.log('---------------');
});
}
}]);
And this is the HTML for the infinite-scroll directive and the activities within:
<div class="infinite-scroll" infinite-scroll='feed.nextPage()' infinite-scroll-disabled='feed.busy || feed.noMoreActivity'>
<feed-card class="portlet light bordered feed-card message-card" ng-repeat="activity in feed.activities" activity="activity" user="data.user"></feed-card>
<div class="well" ng-show='feed.busy'>Loading data...</div>
<div class="well" ng-show='feed.noMoreActivity'>There is no more activity on your feed...</div>
</div>
I'm at a loss for what's happening. The additional, broken activities don't appear in any arrays of API returns. I would assume that it's maybe some sort of scoping issue that would cause the directive to fire twice, with one of them being broken?
If anyone has experienced anything like this, I would love to hear your advice. Thank you.
Fixed this by adding "ng-if='activity'" to the feed-card element.

Jhipster generated app, default AngularJS register form

I created an app using JHipster and try to edit the `register.html'. The code where I need help is shows below:
<div class="alert alert-success" ng-show="vm.success" data translate="register.messages.success">
<strong>Registration saved!</strong> Please check your email for confirmation.
</div>
<div class="alert alert-danger" ng-show="vm.error" data-translate="register.messages.error.fail">
<strong>Registration failed!</strong> Please try again later.
</div>
I omitted the rest of the code as they are equal to these two, only with different messages and ng-models . & the register.controller.js :
(function() {
'use strict';
angular
.module('MyApp')
.controller('RegisterController', RegisterController);
RegisterController.$inject = ['$translate', '$timeout', 'Auth', 'LoginService'];
function RegisterController ($translate, $timeout, Auth, LoginService) {
var vm = this;
vm.doNotMatch = null;
vm.error = null;
vm.errorUserExists = null;
vm.login = LoginService.open;
vm.register = register;
vm.registerAccount = {};
vm.success = null;
$timeout(function (){angular.element('#login').focus();});
function register () {
if (vm.registerAccount.password !== vm.confirmPassword) {
vm.doNotMatch = 'ERROR';
} else {
vm.registerAccount.langKey = $translate.use();
vm.doNotMatch = null;
vm.error = null;
vm.errorUserExists = null;
vm.errorEmailExists = null;
Auth.createAccount(vm.registerAccount).then(function () {
vm.success = 'OK';
}).catch(function (response) {
vm.success = null;
if (response.status === 400 && response.data === 'login already in use') {
vm.errorUserExists = 'ERROR';
} else if (response.status === 400 && response.data === 'e-mail address already in use') {
vm.errorEmailExists = 'ERROR';
} else {
vm.error = 'ERROR';
}
});
}
}
}
})();
My question is by default the error handling messages must be hidden, and once the form is valuated, they should be shown based on the condition. But I cannot figure out how to make this work...
Below is the default register.html page:
The generated register.html does not show those messages by default. It looks like you are loading just the HTML file into the browser, but you need to run the app and load the index.html from there to run the Angular code.
Run ./mvnw or ./gradlew and access the frontend at http://localhost:8080
You can also run gulp which will serve your frontend at http://localhost:9000 with live-reloading when you make changes. More info can be found in the Using JHipster in development documentation
The register page looks like the following image when ran correctly:

Angularjs - hide div with "if" and "else"

I would only like to show a div when user is logged in and on their profile but disabled when logged off and on another users profile.
I attempted to do this below but was unsuccessful. I would like to know what is the best possible way of going about this?
Service.js
(function () {
'use strict';
angular
.module('app.authentication.services')
.factory('Authentication', Authentication);
Authentication.$inject = ['$cookies', '$http'];
function Authentication($cookies, $http) {
var Authentication = {
getAuthenticatedAccount: getAuthenticatedAccount,
isAuthenticated: isAuthenticated
};
return Authentication;
function getAuthenticatedAccount() {
if(!$cookies.authenticatedAccount) {
return;
}
return JSON.parse($cookies.authenticatedAccount);
}
function isAuthenticated() {
return !!$cookies.authenticatedAccount;
}
})();
Controller.js
(function () {
'use strict';
angular
.module('app.profiles.controllers')
.controller('ProfileController', ProfileController);
ProfileController.$inject = ['$location', '$routeParams', 'Posts', 'Profile', 'Snackbar'];
function ProfileController($location, $routeParams, Posts, Profile, Authentication, Snackbar) {
var vm = this;
activate();
function activate() {
var authenticatedAccount = Authentication.getAuthenticatedAccount();
var username = $routeParams.username.substr(1);
// This will show Cog settings button
// when user is logged in and on their profile,
// but hidden when logged off and also when on
// another users profile
if (!authenticatedAccount) {
vm.profileCog = false;
// console.log('User not logged in');
}
else {
if(authenticatedAccount.username !== username) {
vm.profileCog = false;
// console.log('Not logged in user');
}
else {
vm.profileCog = true;
//console.log('logged in user');
}
}
}
})();
profile.html
<div ng-controller="ProfileCogController">
<div ng-show="!profileCog"></div>
</div>
According to your comment that getAuthenticatedAccount is always asynchronous:
This means you'll need to either A) explicitly watch it, or B) evaluate it once it completes. Something like this:
function activate() {
Authentication.getAuthenticatedAccount().then(function(account) {
var username = $routeParams.username.substr(1);
if(!account || account.username !== username) {
vm.profileCog = false;
}
});
// rest of code omitted
You'll need to make sure that Authentication.getAuthenticatedAccount returns a promise for this to work (by default, async calls using AngularJS internal libraries should always return a promise, aka, something that is thenable).
Solved:
controller.js
(function () {
'use strict';
angular
.module('resonanceinn.profiles.controllers')
.controller('ProfileCogController', ProfileCogController);
ProfileCogController.$inject = ['Authentication', '$routeParams', 'Profile'];
function ProfileCogController(Authentication, $routeParams, Profile) {
var vm = this;
vm.profileCog = false;
activate();
function activate() {
var authenticatedAccount = Authentication.getAuthenticatedAccount();
var username = $routeParams.username.substr(1);
if (!authenticatedAccount) {
vm.profileCog = false;
// console.log('User not logged in');
}
else {
if(authenticatedAccount.username !== username) {
vm.profileCog = false;
// console.log('Not logged in user');
} else {
vm.profileCog = true;
// console.log('logged in user');
}
}
}
}
})();
profile.html
<div ng-controller="ProfileCogController">
<div ng-show="vm.profileCog"></div>
</div>
you need to specify the controller and app name in your html file:
1) specify the controller and app name in any parent tag of current div tag if any
2) otherwise, specify the same with in the same div tag
Like:
angular.module('showApp', [])
.controller('mainController', function($scope) {
$scope.isvisible=false;
$scope.showDiv=function()
{
if(!$scope.isvisible)
$scope.isvisible=true
else
$scope.isvisible=false
}
});
<!doctype html>
<html lang="en" >
<head>
<meta charset="UTF-8">
<title>Example</title>
<script src="//ajax.googleapis.com/ajax/libs/angularjs/1.4.4/angular.min.js"></script>
<script src="//ajax.googleapis.com/ajax/libs/angularjs/1.4.4/angular-animate.js"></script>
</head>
<body ng-app="showApp" ng-controller="mainController">
Show me: <input type="checkbox" ng-click="showDiv()" ><br/>
<div ng-show="isvisible">I show up when your checkbox is checked.
</div>
</body>
</html>
Thanks,

angularJS using service variable

I need to call the service variable in controller.
I tried to call $scope.userData1.data.name outside the Service function , it is undefined.
If I put {{userData1}} in template Messages Ctrl , it shows up all the data array including names.
I need to load the i-frame using the user_name variable.
angular.module('starter.controllers', [])
.factory('UserService', function($http) {
var data;
return{
getData: function($http) {
return $http.get("http://www.website.com/index.php/id/user/call12").
success(function(response) {
/// console.log(JSON.stringify(response));
userData=response.data;
return userData;
}).error(function(data, status, headers, config) {
// log error
});
}
}
})
.controller('MessagesCtrl',function ($scope, Messages,$http,$ionicPopup,$timeout,$window,UserService,Outbox,$sce) {
$scope.userData1 = {}; // updated
$scope.myCtrl2= function(UserService,$http) {
UserService.getData($http).then(function(data) {
$scope.userData1 = data;
console.log($scope.userData1.data.name); // USERNAME exist
var name= $scope.userData1.data.name;
});
}
$scope.myCtrl2(UserService,$http);
var name= $scope.userData1.data.name; //undefined
$scope.formData4.upload_url = $sce.trustAsResourceUrl("http://www.website.com/index.php/id/user/view_form/"+ name);
})
template :
<form ng-controller="MessagesCtrl" ng-disabled="isRequesting">
<span class="item item-input" >
<span class="input-label"> </span>
<iframe id="iframe-123" src="{{formData4.upload_url}}" style="border: 0px none; height: 80px; margin: auto; width: 100%; overflow: hidden;" frameborder=0></iframe></span>
</form>
You got undefined because at this point, the answer (http.get) not yet return from the server.
You have to ensure this function $scope.myCtrl2(UserService,$http) received the answer asynchronous before you can call to the next line (var name= $scope.userData1.data.name;).
The best solution is to use promise - $q service like this:
.controller('MessagesCtrl',function ($scope, Messages,$http,$ionicPopup,$timeout,$window,UserService,Outbox,$sce,$q) {
$scope.userData1 = {}; // updated
$scope.myCtrl2= function(UserService, $http)
{
var deferred = $q.defer();
UserService.getData($http).then(function(data)
{
$scope.userData1 = data;
console.log($scope.userData1.data.name); // USERNAME exist
var name= $scope.userData1.data.name;
deferred.resolve();
});
return deferred.promise;
}
$scope.myCtrl2(UserService,$http).then(function(){
var name= $scope.userData1.data.name; //Now you got the answer!!!
$scope.formData4.upload_url = $sce.trustAsResourceUrl("http://www.website.com/index.php/id/user/view_form/"+ name);
});
})

Categories

Resources