I have a page in which which has multiple tabs. I want to add the feature that the tab is reloaded automatically after a fixed duration. I have the following:
<uib-tab index="$index + 1" ng-repeat="environmentRegionTab in ctrl.environmentRegionTabs"
heading="{{environmentRegionTab.environmentRegionName}}"
select="ctrl.onEnvironmentRegionSelect(environmentRegionTab.id);">
<div class="panel-body tab-content">
<div class="alert alert-success" ng-show="ctrl.deployStatus[ctrl.environmentRegion.name].show">
<strong>Launched deployment with execution id
{{ctrl.deployStatus[ctrl.environmentRegion.name].id}}</strong>
</div>
...................
And the following controller:
export function ServiceDetailController(ecsServiceResponse, teamListResponse, productListResponse, businessSubOwnerListResponse, serviceInstancesResponse, businessOwnerListResponse, EcsService, SecretsService, $location, $stateParams, $uibModal, $scope, $state, $window) {
'ngInject';
var self = this;
var serviceInstanceId;
self.ecsAuthControl = {};
self.initialize = _initialize;
self.clearMessages = _clearMessages();
self.onEnvironmentRegionSelect = _onEnvironmentRegionSelect;
$scope.reloadRoute = function() {
$state.reload();
};
function _onEnvironmentRegionSelect(serviceInstanceId) {
self.selectedserviceInstanceId = serviceInstanceId;
if (serviceInstanceId) {
$location.search('serviceInstanceId', serviceInstanceId);
_loadEnvironmentRegion();
} else {
$location.search('serviceInstanceId', null);
_loadSummary();
}
}
}
I am not able to understand how to add the fixed time duration? I also would like to show a counter ticking down from 5 to 0 after which the page is reloaded. How can I do it? I declared the reload function but I am not able to figure out how to add a fixed timer? Thanks!
Make use of $interval service in angularjs:
$interval(function () {
$scope.reloadRoute();
}, 5000);
(make sure to pass $interval as a dependency to controller)
Example Plunker
Here is one of the safest way through which you can achieve the functionality.
Function which does the refresh:-
var poll = function() {
console.log("polling");
$scope.doRefresh(); // Your refresh logic
};
Call the poll from StartPollar:
var startPoller = function() {
if (angular.isDefined(stop)) {
stopPoller();
}
stop = $interval(poll, $scope.intervalTime); //$scope.intervalTime : refresh interval time
};
If you want to Stop it:
var stopPoller = function() {
if (angular.isDefined(stop)) {
$interval.cancel(stop);
stop = undefined;
console.log("cancelled poller operation");
} else {
console.log("do nothing");
}
};
Related
I have a div which shows whether the user is online or offline when the status changes.
<div ng-show="showStatus">
Status:
<div ng-show="online">You're online</div>
<div ng-hide="online">You're offline</div>
</div>
Setting status on $rootScope variable:
checkInternetApp.run(function ($window, $rootScope) {
$rootScope.online = navigator.onLine;
$window.addEventListener("offline", function () {
$rootScope.$apply(function () {
$rootScope.online = false;
});
}, false);
$window.addEventListener("online", function () {
$rootScope.$apply(function () {
$rootScope.online = true;
});
}, false);
});
Showing the div which contains divs showing online or offline:
checkInternetApp.controller("checkInternetController", ["$scope", "$http", "$timeout", function ($scope, $http, $timeout) {
$scope.showStatus = false;
$scope.$watch("online", function () {
$scope.showStatus = true; //set to true for 2 seconds
$timeout(function () {
$scope.showStatus = false; //hiding after 2 seconds
console.log("timeout");
}, 2000)
console.log($scope.showStatus);
})
$scope.showDialog = function () {
console.log($scope.showStatus);
}
}])
But setting the showStatus to true and setting it to false again in the controller is not working. I don't see the div containing the 2 divs. Setting <div ng-show = "true"> works but <div ng-show = "showStatus"> doesn't work. What am I doing wrong?
You have some simple mistakes in your code. While you using $scope.showStatus and $rootScope.online your code should be like this:
Watch $rootScope
.... instead of $scope while $rootScope.online is an $rootScope param.
$rootScope.$watch("online", function (newValue, oldValue) {
if (newValue) {
$scope.showStatus = true; //set to true for 2 seconds
$timeout(function () {
$scope.showStatus = false; //hiding after 2 seconds
$rootScope.online = false;
}, 2000)
}
});
View
Access $rootScope params in view with $root.<objectName>:
<div ng-show="showStatus">
Status:
<div ng-show="$root.online">You're online</div>
<div ng-hide="$root.online">You're offline</div>
</div>
--> Demo fiddle
You should change $scope.$watch to $rootScope.$watch, because of the online object is a rootScope object.
I guess the problem is you have using $scope.showStatus = false; within 2 seconds. So the div won't show. just remove the $scope.showStatus = false; line from $timeout function and check.
Also you should follow which I have mentioned you in the comment under your question.
Don't use $rootScope. If you refresh your browser, then the scope values are clear . I'll suggest you need go with $service or $Broadcast
And in my guess, you don't need to use $timeout, You may need this below logic.
$rootScope.$watch("online", function (oldValue,newValue) {
$scope.showStatus = false;
$scope.IsOnline= newValue;
if(newValue)
$scope.showStatus = true;
console.log($scope.showStatus);
})
$scope.showDialog = function () {
console.log($scope.showStatus);
}
and the HTML
<div ng-show="showStatus">
Status:
<div ng-show="IsOnline">You're online</div>
<div ng-hide="IsOnline">You're offline</div>
</div>
I am using angular modal service to show incoming call popup.
Everything seems to work but in particular case the popup closes leaving behind grey overlay blocking the whole UI.
Popup closes perfectly when i manually click reject and close button provided in popup but gives unusual behaviour when i use timeout to close the popup whithout doing any operation on it.
For reference i am giving my whole code.
----------------------------modal popup UI code---------------------------
<div class="modal fade">
<div class="modal-dialog modal-lg modal-dialog-custom">
<div class="modal-content modal-content-dialog">
<div class="modal-header">
<audio class="incoming-videoconference-audio" autoplay loop>
<source src="../images/dataCallIncoming.mp3" type="audio/mpeg">
</audio>
<button type="button" class="close" ng-click="vm.hangUp()" data-dismiss="modal" aria-hidden="true">×</button>
<h4 class="modal-title">Incoming Call</h4>
</div>
<img class="incoming-nowConf-logo" src="../images/new_nowconfer_e.png" />
<div id="state" class="grid_4 alpha">
<div class="gps_ring"></div>
</div>
<div class="modal-body modal-body-custom">
<div style="text-overflow:ellipsis;overflow:hidden;" class="call-from">
{{vm.confName}}
</div>
<div class="call-control">
<button type="button"class="btn-sm btn-sm-gray cancel-btn" ng-click="vm.hangUp()" data-dismiss="modal">Reject</button>
<span style="width:50px;"> </span>
<button type="button"class="btn-sm btn-sm-green" ng-click="vm.accept()" data-dismiss="modal">Answer</button>
</div>
</div>
</div>
</div>
</div>
-------------------------modal popup controller------------------------------
(function () {
'use strict';
angular
.module('incomingModule')
.controller('IncomingCallController', IncomingCallController);
IncomingCallController.$inject = ['$scope','$rootScope','plivoclient','$routeParams','$location','close','from', 'instId','confName','$timeout'];
function IncomingCallController($scope,$rootScope , plivoclient,$routeParams ,$location,close, from, instId,confName,$timeout) {
var vm = this;
vm.connecting = false;
vm.from = from;
vm.confName = confName;
vm.dismissModal = function(result) {
plivoclient.conn.reject();
console.log('vm.dismissModal::'+result);
close(result, 200); // close, but give 200ms for bootstrap to animate
};
activate();
function activate(){
$timeout(function(){
vm.dismissModal('cancel');
},25000);
}
vm.accept = function() {
plivoclient.conn.answer();
vm.connecting = true;
console.log("incoming call accept............");
vm.dismissModal('accept');
$timeout(function(){
$location.path( "/call/"+$rootScope.id2);
},300);
};
vm.hangUp = function() {
plivoclient.conn.reject();
vm.dismissModal('reject');
console.log("incoming call hangedup............");
};
}
}());
-------------------------opening modal code----------------------------------------
ModalService.showModal({
templateUrl: '../../partials/calls.incoming.popup.html',
controller: 'IncomingCallController',
controllerAs: 'vm',
inputs: {
from: dataNew.callerName || '',
instId: dataNew.extraHeaders['X-Ph-Instid'] || dataNew.extraHeaders['X-Ph-instid'],
confName:$rootScope.conferenceData.conf_name
}
}).then(function(modal) {
modal.element.modal();
modal.close.then(function(result) {
//$scope.message = result ? "You said Yes" : "You said No";
});
});
----------------------------------angular modal service code----------------------------------
'use strict';
let module = angular.module('angularModalService', []);
module.factory('ModalService', ['$animate', '$document', '$compile', '$controller', '$http', '$rootScope', '$q', '$templateRequest', '$timeout',
function($animate, $document, $compile, $controller, $http, $rootScope, $q, $templateRequest, $timeout) {
function ModalService() {
var self = this;
// Returns a promise which gets the template, either
// from the template parameter or via a request to the
// template url parameter.
var getTemplate = function(template, templateUrl) {
var deferred = $q.defer();
if (template) {
deferred.resolve(template);
} else if (templateUrl) {
$templateRequest(templateUrl, true)
.then(function(template) {
deferred.resolve(template);
}, function(error) {
deferred.reject(error);
});
} else {
deferred.reject("No template or templateUrl has been specified.");
}
return deferred.promise;
};
// Adds an element to the DOM as the last child of its container
// like append, but uses $animate to handle animations. Returns a
// promise that is resolved once all animation is complete.
var appendChild = function(parent, child) {
var children = parent.children();
if (children.length > 0) {
return $animate.enter(child, parent, children[children.length - 1]);
}
return $animate.enter(child, parent);
};
self.showModal = function(options) {
// Get the body of the document, we'll add the modal to this.
var body = angular.element($document[0].body);
// Create a deferred we'll resolve when the modal is ready.
var deferred = $q.defer();
// Validate the input parameters.
var controllerName = options.controller;
if (!controllerName) {
deferred.reject("No controller has been specified.");
return deferred.promise;
}
// Get the actual html of the template.
getTemplate(options.template, options.templateUrl)
.then(function(template) {
// Create a new scope for the modal.
var modalScope = (options.scope || $rootScope).$new();
var rootScopeOnClose = $rootScope.$on('$locationChangeSuccess', cleanUpClose);
// Create the inputs object to the controller - this will include
// the scope, as well as all inputs provided.
// We will also create a deferred that is resolved with a provided
// close function. The controller can then call 'close(result)'.
// The controller can also provide a delay for closing - this is
// helpful if there are closing animations which must finish first.
var closeDeferred = $q.defer();
var closedDeferred = $q.defer();
var inputs = {
$scope: modalScope,
close: function(result, delay) {
if (delay === undefined || delay === null) delay = 0;
$timeout(function() {
cleanUpClose(result);
}, delay);
}
};
// If we have provided any inputs, pass them to the controller.
if (options.inputs) angular.extend(inputs, options.inputs);
// Compile then link the template element, building the actual element.
// Set the $element on the inputs so that it can be injected if required.
var linkFn = $compile(template);
var modalElement = linkFn(modalScope);
inputs.$element = modalElement;
// Create the controller, explicitly specifying the scope to use.
var controllerObjBefore = modalScope[options.controllerAs];
var modalController = $controller(options.controller, inputs, false, options.controllerAs);
if (options.controllerAs && controllerObjBefore) {
angular.extend(modalController, controllerObjBefore);
}
// Finally, append the modal to the dom.
if (options.appendElement) {
// append to custom append element
appendChild(options.appendElement, modalElement);
} else {
// append to body when no custom append element is specified
appendChild(body, modalElement);
}
// We now have a modal object...
var modal = {
controller: modalController,
scope: modalScope,
element: modalElement,
close: closeDeferred.promise,
closed: closedDeferred.promise
};
// ...which is passed to the caller via the promise.
deferred.resolve(modal);
function cleanUpClose(result) {
// Resolve the 'close' promise.
closeDeferred.resolve(result);
// Let angular remove the element and wait for animations to finish.
$animate.leave(modalElement)
.then(function () {
// Resolve the 'closed' promise.
closedDeferred.resolve(result);
// We can now clean up the scope
modalScope.$destroy();
// Unless we null out all of these objects we seem to suffer
// from memory leaks, if anyone can explain why then I'd
// be very interested to know.
inputs.close = null;
deferred = null;
closeDeferred = null;
modal = null;
inputs = null;
modalElement = null;
modalScope = null;
});
// remove event watcher
rootScopeOnClose && rootScopeOnClose();
}
})
.then(null, function(error) { // 'catch' doesn't work in IE8.
deferred.reject(error);
});
return deferred.promise;
};
}
return new ModalService();
}]);
I have spent hours on internet to figure out why this is happening but failed to solve it,i feel when any click event happens then it works fine but fails to close properly when on operation is performed.Please help!!
thanks in advance
I had the same issue and it was due to a comment at the top of my HTML file. When I removed the comment, it worked fine.
I didn't get the reason of this bug though.
hope you have the same case.
What is happening is that when I reach the bottom of the page, it refreshes and loads the new data, however it doesn't show the data for the previous and current page.
For example it looks like this:
1
2
3
4
* end of page, refreshes page*
5
6
7
8
My function in my controller:
var i = 0;
$scope.result = [];
$scope.noMoreItemsAvailable = false;
$scope.loadMore = function() {
if (i < 4) {
$http.get(url.recommended + i).success(function(response) {
i++;
$scope.result = $scope.result.push(response);
console.log(response);
$timeout(function() {
$scope.result = response
});
$scope.$broadcast('scroll.infiniteScrollComplete');
});
} else {
$scope.noMoreItemsAvailable = true;
}
}
HTML:
<div class="item item-text-wrap" ng-click="post($event,res)" ng-repeat="res in result" ng-controller="recommendedJobsCtrl" ui-sref="tabs.jobDetails">
<ul>
<li id="jobTitle">{{res.title }}</li>
</ul>
</div>
<ion-infinite-scroll ng-if="!noMoreItemsAvailable" on-infinite="loadMore()" distance="1%"></ion-infinite-scroll>
Well, there are 2 main problems:
You're attributing the value of the push for your array. You shouldn't do this, you just have to do this:
$scope.result.push(response);
You should remove this timeout because it's overriding what you already have:
$timeout(function() {
$scope.result = response
});
By the way, I'd recommend you to create a factory to prevent problems with async data.
You could do something like this:
angular
.module('app', [])
.controller("MainCtrl", MainCtrl)
.factory("ItemsFactory", ItemsFactory);
ItemsFactory.$inject = ['$http'];
function ItemsFactory($http) {
var factory = {
getPages: getPages
};
return factory;
function getPages(url) {
return $http.get(url);
}
}
Then, in your controller:
MainCtrl.$inject = ['$scope', 'ItemsFactory'];
function MainCtrl($scope, ItemsFactory) {
var url = 'https://www.google.com';
function getResponse(response) {
$scope.result.push(response.data);
}
function getError(response) {
console.log(response);
}
ItemsFactory.getPages(url)
.then(getResponse);
.catch(getError);
}
Please, note: I also recommend you to change the way that you're retrieving your items from your back-end. It isn't a good way to retrieve the elements 1 by 1. The correct in your case is to retrieve all the four items at once and treat them in controller.
Your timeout is causing the $scope.result to be overwritten by the response.
Just remove this and it should append the response to the result
REMOVE THIS
$timeout(function ()
{
$scope.result=response
});
From what I've read, it seems using $rootScope.$broadcast is not advisable unless absolutely necessary. I'm using it in a service to notify a controller that a variable has changed. Is this incorrect? Is there a better way to do it? Should I be using watch instead (even though the variable only changes on user interaction) ?
the service:
function Buildservice($rootScope) {
var vm = this;
vm.box= [];
var service = {
addItem: addItem,
};
return service;
// Add item to the box
// Called from a directive controller
function addItem(item) {
vm.box.push(item);
broadcastUpdate();
}
function broadcastUpdate() {
$rootScope.$broadcast('updateMe');
}
// In the controller to be notified:
// Listener for box updates
$scope.$on('updateMe', function() {
// update variable binded to this controller
});
// and from a separate directive controller:
function directiveController($scope, buildservice) {
function addToBox(item){
buildservice.addItem(item);
}
So this works just fine for me, but I can't figure out if this is the way I should be doing it. Appreciate the help!
If you are in same module, why don't you use $scope instead of $rootScope?
You can use a callback function to notify the controller something has changed. You supply the service a function from the controller, and invoke that particular function whenever your variable has been changed. You could also notify multiple controllers if needed.
I have created a small example:
HMTL:
<div ng-controller="CtrlA as A">
{{A.label}}
<input type="text" ng-model="A.input" />
<button ng-click="A.set()">set</button>
</div>
<div ng-controller="CtrlB as B">
{{B.label}}
<input type="text" ng-model="B.input" />
<button ng-click="B.set()">set</button>
</div>
JS
var app = angular.module('plunker', []);
app.controller('CtrlA', function(AService) {
var vm = this;
vm.label = AService.get();
vm.notify = function() {
vm.label = AService.get();
}
vm.set = function() {
AService.set(vm.input)
}
AService.register(vm.notify);
});
app.controller('CtrlB', function(AService) {
var vm = this;
vm.label = AService.get();
vm.notify = function() {
vm.label = AService.get();
}
vm.set = function() {
AService.set(vm.input)
}
AService.register(vm.notify);
});
app.factory("AService", function() {
var myVar = "Observer";
var observers = [];
return {
get: function() {
return myVar;
},
set: function(name) {
console.log(name);
myVar = name;
this.notify();
},
register: function(fn) {
observers.push(fn);
},
notify: function() {
for( i = 0; i < observers.length; i++) {
observers[i]();
}
}
}
})
You will see upon executing this that the controllers get notified when the internal variable has been changed. (Notice: I haven't filtered the original sender from the list) (Plnkr)
I'm building a simple Pomodoro timer, and still in the early stages of learning Angular. I'm having trouble updating the view every second with the $scope.timeView variable. $scope.timeView logs to the console every second, but not the view. I have tried injecting $interval and using apply(), but their not working. I'm sure its something obvious to a trained eye, I'll keep searching. In the meantime any help would be greatly appreciated. Thanks.
pomodoro_timer.controller('app.controller', ['$scope', '$state', '$stateParams', function ($scope, $state, $stateParams) {
// (function() {
var intrvl;
var t = 1500;
var tDiv = $('#time');
$scope.startTimer = function() {
if (tDiv.hasClass("notWorking")) {
$scope.interval(t);
$scope.toggleClass();
}
};
$scope.interval = function() {
intrvl = setInterval(function(){
t -= 1;
$scope.displayTime(t)
},1000)
}
$scope.displayTime = function() {
var m = parseInt(t / 60);
var s = parseInt(t) % 60;
if (s < 10) {
s = "0" + s;
}
$scope.timeView = m+":"+s;
}
$scope.stopStart = function() {
if (tDiv.hasClass('working')) {
$scope.toggleClass();
clearInterval(intrvl);
$('#QwkBreak a').text('Continue Working'); //////////////////////Should I remove jQuery?/////////////////////////
} else if (t<1500) { // prevents timer from starting when '#QwkBreak' is clicked, unless timer has started counting down //
$('#QwkBreak a').text('Quick Break');
$scope.interval();
$scope.toggleClass();
}
}
$scope.toggleClass = function() {
tDiv.toggleClass('notWorking working');
}
$scope.resetTimer = function() {
if (!tDiv.hasClass('notWorking')) { //prevents reset button from toggling classes unless (class="working") //
clearInterval(intrvl);
t = 1500;
tDiv.text("25:00");
$scope.toggleClass();
}
}
// })();s
}]);
<body ng-controller="app.controller">
<h1>Pomodoro Timer</h1>
<div id="timeView">
<p id="time" class="notWorking">{{ timeView }}</p>
</div>
<div id="controls">
<button id="startWork"><a ng-click="startTimer()" href="#">Start Work</a></button>
<button id="QwkBreak"><a ng-click="stopStart()" href="#">Quick Break</a></button>
<button id="reset"><a ng-click="resetTimer()" href="#">Reset</a></button>
<button id="5_MInBreak">5-Min Break</button>
</div>
</div>
Angular has $interval service that internally will manage digests and also allows for easily getting rid of timers using cancel() method
$scope.interval = function() {
intrvl = $interval(function(){
t -= 1;
$scope.displayTime(t)
},1000)
}
Now you also want to remove that interval timer from the window when scope is destroyed
$scope.$on('$destroy', function(){
intrvl.cancel();
});
you will need to inject $interval in controller also
Also suggest that all of this timer related code should be placed in a directive. Controllers should not have any dom related code in them
Reference: $interval docs