While rendering displaying Loading Icon doesnt work - javascript

<div ng-if="!loading">
//some code
</div>
<div ng-if="loading">
<loading></loading>
</div>
angular.module('indexApp.directives')
.directive('loading', function () {
return {
restrict: 'E',
replace:true,
template: '<div class="loading"><img src="../../../cim/images/projIcons/loading.gif" width="250px" height="45px" /></div>',
link: function (scope, element, attr) {
scope.$watch('loading', function (val) {
if (val)
$(element).show();
else
$(element).hide();
});
}
}
});
This code work well as expected showing loading while data is less.In js written code for loading variable for making it true and false when data gets received. As soon as data is more loading icon is not showing. After some check found that, loading icon can be showed only when data is not received from back-end.
Once data is received loading icon gets removed. So in larger data case, time taken was for rendering. So for rendering it is not showing loading icon. Is it any mechanism by which we keep loading icon till browser complete data rendering.

Try this
Actually this code worked fine for me.
app.config(function ($httpProvider) {
$httpProvider.responseInterceptors.push('myHttpInterceptor');
var spinnerFunction = function spinnerFunction(data, headersGetter) {
$(".loader").show();
return data;
};
$httpProvider.defaults.transformRequest.push(spinnerFunction);
});
//Defining Factory
app.factory('myHttpInterceptor', function ($q, $window) {
return function (promise) {
return promise.then(function (response) {
$(".loader").hide();
return response;
}, function (response) {
$(".loader").hide();
return $q.reject(response);
});
};
});

Related

$timeout() not calling inappbrowser [Ionic]

I am using an initial screen(initial.html) and i want it to act as a splashscreen and then call the inappbrowser.
But inappbrowser is not opening. If i place it directly it works.
No error is also coming. The required functionality is to have a splash screen view getting redirected to inappbrowser, user will log in and upon successful login will be redirected to the view.( Individual parts are working, but when i put it inside a TimeOut function it is not working ).
Is there any better way to achieve this functionality.
controller.js
.controller('LoginCtrl', function($scope,$timeout,$rootScope,LoginService, $ionicPopup, $state,$location,$ionicPopup) {
$timeout(function(){
LoginService.loginUser().success(function(data) {
console.log(data);
$location.path('app/playlists');
}).error(function(data) {
var alertPopup = $ionicPopup.alert({
title: 'Login failed!',
template: 'Please check your credentials!'
});
});
}, 3000);
})
services.js
angular.module('starter.services', [])
.service('LoginService', function($q,$rootScope,$cordovaInAppBrowser,$http,$state,jwtHelper,$location) {
return {
loginUser: function() {
var deferred = $q.defer();
var promise = deferred.promise;
console.log("Hi Service"); // IT IS REACHING HERE THEN STUCK
$cordovaInAppBrowser.open(URL, '_self',options).then(function(event){
console.log(event);
// success
})
.catch(function(event) {
console.log(event);
// error
});
$rootScope.$on('$cordovaInAppBrowser:loadstop', function(e, event){
if(userValid){
deferred.resolve(username); }
else{
deferred.reject('Auth Failed');
}
});
//promise created outside
promise.success = function(fn) {
promise.then(fn);
return promise;
}
promise.error = function(fn) {
promise.then(null, fn);
return promise;
}
return promise;
}
});
I removed and reinstalled the inappbrowser plugin and it worked correctly. I apologize for the confusion

Angular.JS onclick function only called on first click

I am currently working on a small aplication using Angular.JS
In my view i have following button
<md-button class="md-primary" ng-click="editUser(user, $event)">Edit</md-button>
the editUser method looks something like this:
$scope.editUser = function (user, $event) {
$scope.userToEdit = user;
$mdDialog.show({
controller: DialogController,
targetEvent: $event,
templateUrl: '/js/modules/user/views/edit.tmpl.html',
parent: angular.element(document.body),
clickOutsideToClose: true,
scope: $scope
})
.
then(function (answer) {
if (answer == "save") {
for (right in $scope.allSystemRightsStatements) {
if ($scope.allSystemRightsStatements[right].selected) {
if( $scope.userToEdit.rights==null){
$scope.userToEdit.rights = [];
}
$scope.userToEdit.rights.push($scope.allSystemRightsStatements[right]);
}
}
$scope.updateUser($scope.userToEdit);
}
$scope.userToEdit = {};
}, function () {
$scope.userToEdit = {};
});
};
$scope.updateUser = function (user) {
//userService.updateUser makes a $http PUT request
var promise = userService.updateUser(user);
promise.then(function (result) {
$mdToast.show(
$mdToast.simple(result.message)
.position($scope.getToastPosition())
.hideDelay(3000)
);
}, function (reason) {
$mdToast.show(
$mdToast.simple(reason)
.position($scope.getToastPosition())
.hideDelay(3000)
);
}, function (update) {
});
};
Now the dialog is nicely shown and the answer function is also called, everything as expected.
However, when I click the button a second time the editUser funciton is not executed. As if the onClick event from the button had been removed at dialog close.
Any help on solving this problem is greatly appreciated,
Thanks
As said here
it is probably a good idea to explicitly mention that the scope will be destroyed upon hiding the dialog (so people shouldn't pass a controller's $scope directly).
(regarding the scope you are passing to mdDialog)
So, as the scope is destroyed, angular is not binding your button with any action

Disable items in ng-repeat list on click of one other item

Here is my plnkr with my progress so far: http://plnkr.co/edit/iEHMUMlASZaqdMQUeF7J?p=preview
I'm having problems implementing the following functionality however.
When an item on the list is clicked, I need to disable the remaining items on the list. ie, another request should not take place, and these remaining items' colour should change to indicate the disabled state.
Once the request has taken place, then the entire list should go back to the original state.
Edit: I've made some progress. Although a bit messy it's getting me a bit closer. My problem is the following line:
$(this).parent().addClass('item-selected').children().unbind('click').removeClass('pending');
This prevents the click event running more than once at a time. However it's stopping the click event from running all together once its run for the first time. I would like to be able to re-run the process once it is complete an unlimited amount of times.
Directive:
app.directive('listItem', function (ListService, $timeout, $location) {
return {
restrict: 'ACE',
controller : 'ItemController',
template: '<p>{{item}} {{foo}}</p>',
link: function (scope, element, attrs) {
$(element).bind('click', function (e) {
$(this).parent().addClass('item-selected').children().unbind('click').removeClass('pending');
$(this).addClass('pending');
var elem = $(this);
$timeout(function () {
ListService
.selectItem(scope.item)
.then( function () {
console.log('success');
elem.removeClass('pending').addClass('success');
//$location.path('foo.html')
scope.foo = 'not bar';
}, function () {
console.log('error');
elem.removeClass('pending').addClass('error');
elem.parent().removeClass('item-selected');
});
;
}, 2000);
});
}
};
});
The entire app code including directive:
var app = angular.module('listtestApp', []);
app.service('ListService', function ($http) {
var data = [
'alpha',
'bravo',
'charlie',
'delta',
'foxtrot'
];
return {
getData : function () {
return data;
},
selectItem : function () {
return $http({ method: 'GET', url : '/data/list.json'});
}
}
});
app.controller('ListController', function ($scope, ListService) {
$scope.list = ListService.getData();
$scope.foo = 'Bar';
});
app.controller('ItemController', function ($scope, ListService) {
});
app.directive('listItem', function (ListService, $timeout, $location) {
return {
restrict: 'ACE',
controller : 'ItemController',
template: '<p>{{item}} {{foo}}</p>',
link: function (scope, element, attrs) {
$(element).bind('click', function (e) {
$(this).parent().addClass('item-selected').children().unbind('click').removeClass('pending');
$(this).addClass('pending');
var elem = $(this);
$timeout(function () {
ListService
.selectItem(scope.item)
.then( function () {
console.log('success');
elem.removeClass('pending').addClass('success');
//$location.path('foo.html')
scope.foo = 'not bar';
}, function () {
console.log('error');
elem.removeClass('pending').addClass('error');
});
;
}, 2000);
});
}
};
});
html markup below:
<body ng-app="listtestApp">
<div ng-controller="ListController">
<div ng-repeat="item in list" list-item>
</div>
</div>
</body>
You have several solutions at your disposal :
Check that any element has the pending or success or error class
use your function scope to store it in a variable
EDIT : if you want to re-enable selection after the request has been posted, you could use something like this (variant of version #1)

Angular page doesn't refresh after data is added or removed

I'm having a recurrent problem with my angular app whereby it doesn't refresh the page after data has been added, edited or removed. So if I add a new item to a list of subjects, the new item doesn't appear on the list unless I navigate away from the page and then come back to it. I've tried using route.reload and then resetting the scope of the subjects list below. I put in an alert to see if it get fired- but the alert appears before the page redirects back to the list of subjects, which is strange as $location.path('/subjects') is two lines before it. Here's my controller:
angular.module('myApp.controllers')
.controller('SubjectEditCtrl', ['$scope', '$routeParams', 'SubjectFactory', 'SubjectsFactory', '$location', '$route',
function ($scope, $routeParams, SubjectFactory, SubjectsFactory, $location, $route) {
// callback for ng-click 'updateSubject':
$scope.updateSubject = function () {
//Performs an update to the server
SubjectFactory.update($scope.subject);
//Redirects to list of all subjects
$location.path('/subjects/');
//Should reset the scope of the subject list
$scope.subjects = SubjectsFactory.query();
//Should reload the page
$route.reload();
//For debugging- the alert appears BEFORE the redirect to list of all subjects happens
alert('route reload happening');
};
SubjectFactory.show({id: $routeParams.subjectId}).$promise.then(function(subject) {
$scope.subject = subject;
}, function(err) {
console.error(err);
});
}]);
Can anyone suggest a solution?
EDIT: Subjects Service
var app = angular.module('myApp.services');
app.factory('SubjectsFactory', function ($resource) {
return $resource('https://myapiurl.com/subjects', {}, {
query: { method: 'GET', isArray: true },
create: { method: 'POST' }
})
});
app.factory('SubjectFactory', function ($resource) {
return $resource('https://myapiurl.com/subjects/:id', {}, {
show: { method: 'GET', isArray: false },
update: { method: 'PATCH', params: {id: '#id'} },
delete: { method: 'DELETE', params: {id: '#id'} }
})
});
Some times you need to apply changes to scope this is done by the following code:
$scope.$apply();
But this can be done only if it's not in "$digest" phase, otherwise it will throw exception. So you need to check first it's not in "$digest" phase then you can apply it. Here is the example of the code I use for safe applying changes:
safeApply: function (scope, callback) {
if (scope.$$phase != '$apply' && scope.$$phase != '$digest' &&
(!scope.$root || (scope.$root.$$phase != '$apply' && scope.$root.$$phase != '$digest'))) {
scope.$apply();
}
if (angular.isFunction(callback)) {
callback();
}
}
I can suggest next way:
You can't get data from database, after adding, you can easly push new added object to $scope.items.
Example:
$scope.add = function (newItem) {
DataService.addItem(newItem).then(function(){
$scope.items.push(newItem);
//or for removing
//$scope.items.splice($scope.items.indexOf(newItem), 1);
});
};
And adjust your factory:
addItem: function (newProject) {
$http.post('Api/Controller/Post').then(function(successResult){
...
}, function (errorResult) {
...
});
}
Item will be added in $scope.items only after success calling of server-side method.
Changing the structure of the requests slightly fixed the problem- so instead of
$scope.updateSubject = function () {
SubjectFactory.update($scope.subject);
$location.path('/subjects/');
$scope.subjects = SubjectsFactory.query();
$route.reload();
};
It is now
$scope.updateSubject = function () {
SubjectFactory.update($scope.subject).$promise.then(function (subject) {
$scope.subject = subject;
$location.path('/subjects/');
$route.reload();
}, function (err) {
console.error(err);
});
};

Calling function immedietaly at AngularJS

I am totally newbie to AngularJs.
I have pretty good example of ngClick which is calling a Facebook function.
I would like to change it and programmatically to call registerWithFacebook function after my controller will be ready. What is the way for it?
Here is the sample: http://jsfiddle.net/IgorMinar/Hxbqd/5/
angular.module('HomePageModule', []).service('facebookConnect', function($rootScope) {
this.askFacebookForAuthentication = function(fail, success) {
FB.login(function(response) {
if (response.authResponse) {
FB.api('/me', function() { $rootScope.$apply(success) });
} else {
$rootScope.$apply(function() {
fail('User cancelled login or did not fully authorize.')
});
}
});
}
});
function ConnectCtrl(facebookConnect, $scope, $resource) {
$scope.user = {}
$scope.error = null;
$scope.registerWithFacebook = function() {
facebookConnect.askFacebookForAuthentication(
function(reason) { // fail
$scope.error = reason;
}, function(user) { // success
$scope.user = user
});
}
// Tried this but no success
// $scope.registerWithFacebook();
}
ConnectCtrl.$inject = ['facebookConnect', '$scope', '$resource'];
Thanks
If you want to load the FB library asynchronously, you need to let angular know after it initializes. Here is one way to do it:
http://plnkr.co/edit/YO4duxL1Mh3dwYEEpprV?p=preview

Categories