unable to use timeout in angular js bootstrap in mvc - javascript

index.cshtml
<!doctype html>
<html data-ng-app="ui.bootstrap.demo">
<head>
<script src="~/Scripts/angular.js"></script>
<script src="//angular-ui.github.io/bootstrap/ui-bootstrap-tpls-0.13.0.js"></script>
<script src="~/Scripts/example.js"></script>
<link href="~/Content/bootstrap.min.css" rel="stylesheet" />
</head>
<body>
<div data-ng-controller="AlertDemoCtrl">
<alert ng-repeat="alert in alerts" type="{{alert.type}}" close="closeAlert($index)">{{alert.msg}}</alert>
<button class='btn btn-default' ng-click="addAlert()">Add Alert</button>
</div>
</body>
</html>
example.js
angular.module('ui.bootstrap.demo', ['ui.bootstrap']);
angular.module('ui.bootstrap.demo').controller('AlertDemoCtrl', function ($scope) {
$scope.alerts = [
{ type: 'danger', msg: 'Oh snap! Change a few things up and try submitting again.' },
{ type: 'success', msg: 'Well done! You successfully read this important alert message.' }
];
$scope.addAlert = function() {
$scope.alerts.push({msg: 'Another alert!'});
};
$scope.closeAlert = function(index) {
$scope.alerts.splice(index, 1);
};
$timeout(function () {
$scope.alerts.splice($scope.alerts.indexOf(alert), 1);
}, 3000); // maybe '}, 3000, false);' to avoid calling apply
unable to close the alert after 3 sec interval, anything wrong ?

angular.module('ui.bootstrap.demo', ['ui.bootstrap']);
angular.module('ui.bootstrap.demo')
.controller('AlertDemoCtrl', function ($scope, $timeout) { //here I've just injected the $timeout service to your controller. if your other codes are ok then this $timeout will work
$scope.alerts = [
{ type: 'danger', msg: 'Oh snap! Change a few things up and try submitting again.' },
{ type: 'success', msg: 'Well done! You successfully read this important alert message.' }
];
$scope.addAlert = function() {
$scope.alerts.push({msg: 'Another alert!'});
};
$scope.closeAlert = function(index) {
$scope.alerts.splice(index, 1);
};
$timeout(function () {
$scope.alerts.splice($scope.alerts.indexOf(alert), 1); // you are using 'alert' to get the specific alert in alerts array of object, but you haven't passed/defined 'alert' anywhere. so how can you get this alert? and how can it be removed. Please pass/define 'alert', which is the portion you would know better. Then your code will work.
}, 3000); // maybe '}, 3000, false);' to avoid calling apply

You need to include "$timeout" dependency in your controller.
As mentioned by #Mahbubul Haque, "alert" is undefined inside your timeout.
Your $timeout instance should be destroyed on $destroy of scope
If you requirement is to close one alert after every 3 secs, you can do something like this:
angular.module('ui.bootstrap.demo', ['ui.bootstrap']);
angular.module('ui.bootstrap.demo').controller('AlertDemoCtrl', function ($scope, $timeout) {       
var timeoutInstance;
$scope.alerts = [
{ type: 'danger', msg: 'Oh snap! Change a few things up and try submitting again.' },
{ type: 'success', msg: 'Well done! You successfully read this important alert message.' }
];
$scope.addAlert = function() {
$scope.alerts.push({msg: 'Another alert!'});
};
$scope.closeAlert = function(index) {
$scope.alerts.splice(index, 1);
};
$scope.index = 0;
timeoutIntance = $timeout(function () {
$scope.alerts.splice(index, 1);
++$scope.index;
}, 3000);
$scope.$on("$destroy", function(){
if(angular.isDefined(timeoutInstance)){
$timeout.cancel(timeoutInstance);
timeoutInstance = null;
}
});

Related

Cannot read property 'data' of undefined on a not-even started $http.get request

I have a web application, started by a previous company, written in Angular.JS.
The application exposes a request towards the back-end (written in Node.JS+Express) to gather some data required to fill a table.
Specifically, this is the request that the application sends everytime the user enters in the page that holds the table (The config variable holds the access token).
define(['app'], function (app) {
app.factory('AdvService', AdvService);
AdvService.$inject = ['BasicService'];
function AdvService(BasicService) {
var service = angular.extend(BasicService, {});
var $http = service.$http;
var API = service.API
var handleSuccess = service.handleSuccess;
var handleError = service.handleError;
var config = {
params: {
'token': JSON.parse(window.sessionStorage.getItem('session')).token
}
};
service.searchByCriteria = function (criteria) {
debugger;
config.params.pageNumber = criteria.pageNumber;
config.params.pageSize = criteria.pageSize;
return $http.get(API + '/api/v2/admin/ads/getAdsByCriteria', config).then(handleSuccess, handleError);
};
service.createAd = function (ad) {
debugger;
return $http.post(API + '/api/v2/admin/ads/insertNewAd', ad, config).then(handleSuccess, handleError);
};
return service;
}
});
handleSuccess and handleError are so defined
define(['app'], function (app) {
app.factory('BasicService', BasicService);
BasicService.$inject = ['CONF', '$http', '$window', '$q'];
function BasicService(CONF, $http, $window, $q) {
$http.defaults.headers.common['x-access-token'] = JSON.parse($window.sessionStorage.getItem('session')).token;
return {
$http: $http,
API: CONF.API_URL,
handleSuccess: function (res) {
debugger;
var deferred = $q.defer();
res.data.success ? deferred.resolve(res.data) : deferred.reject(res.data.message);
return res.data;
},
handleError: function (error) {
debugger;
return {
success: false,
message: error
};
}
}
}
})
and this is the only point of the application that calls that service
($scope.search = function () {
debugger;
AdvService.searchByCriteria($scope.searchCriteria).then(function (res) {
debugger;
$scope.searchRes = res.data.docs;
//$scope.gridOptions.totalItems = res.data.total;
}, function (err) {
console.log(err);
});
})();
Being a CORS request (the front-end is at port 8010 and the back-end in another one), I see from Chrome's Network Monitoring System that the $http.get part gets executed twice, but here's my problem: even before starting handling on the back-end the first call, the front-end generates the error
angular.js:14961 TypeError: Cannot read property 'data' of undefined
at Object.<anonymous> (ui-grid.js:3291)
at Object.invoke (angular.js:5117)
at $controllerInit (angular.js:11139)
at nodeLinkFn (angular.js:10002)
at angular.js:10410
at processQueue (angular.js:17330)
at angular.js:17378
at Scope.$digest (angular.js:18515)
at Scope.scopePrototype.$digest (hint.js:1495)
at Scope.$apply (angular.js:18903)
and even tough the request does return data, having crashed, Angular cannot correctly render everything.
The only thing I tried was to use the Await/Async mechanism to try to wait and see what could have happened but this always resolves in the above error.
Does anybody have any clue of what's going on? I'm 100% positive that the code that I've posted here is the only one that gets called during this process and I can't honestly understand why should the process fail if both requests return data
So, as correctly pointed out by Alon Eitan in the comments, the error was somehow related with ui-grid and that, probably, it might have been that the gridOptions were not correctly called like the HTML was excepting.
IN FACT ...
HTML
<div class="alerts container-fluid" ng-controller="AdsController">
<div class="row">
WORK IN PROGRESS!
<!-- <span>Pubblicità attive: <b>{{activeAdsCounter}}</b> - </span>-->
<!-- <span>Pubblicità totali: <b>{{totalAdsCounter}}</b> - </span>-->
</div>
<button ng-click="openCreateNewAdModal()"><i class="material-icons">library_add</i></button>
<div class="row">
<div class="col-md-12">
<h3>Pubblicità Nel Sistema</h3>
<div class="grid" ui-grid="adsGridOptions" ui-grid-pagination
ui-grid-auto-resize></div>
</div>
</div>
</div>
Controller
define(['app', 'moment'], function (app, moment) {
app.controller('AdsController', AdsController);
AdsController.$inject = ['$scope', '$mdDialog', 'AdvService'];
function AdsController($scope, $mdDialog, AdvService) {
debugger;
$scope.rowHeight = 30;
$scope.gridOptions = {
data: 'searchRes',
paginationPageSizes: [25, 50, 75],
paginationPageSize: 25,
enableSorting: true,
enablePaginationControls: true,
enableColumnMenus: false,
useExternalPagination: true,
rowHeight: $scope.rowHeight,
columnDefs: [
{
name: 'Cliente',
field: 'customerName',
}, {
name: 'Durata',
field: 'duration',
}, {
name: 'Euro Spesi',
field: 'spentEuros',
}, {
name: 'Data inserimento',
field: 'createdAt',
type: 'date',
width: '130',
cellFilter: "date:'dd-MM-yyyy'",
}, {
name: 'Email Referente',
field: 'referralEmail',
}, {
name: 'Nome Referente',
field: 'referralPerson',
}, {
name: 'Numero Referente',
field: 'referralNumber',
},
],
onRegisterApi: function (gridApi) {
$scope.gridApi = gridApi;
$scope.gridApi.core.on.sortChanged($scope, function (grid, sortColumns) {
if (sortColumns[0]) {
console.log(sortColumns[0].sort);
$scope.searchCriteria.sort = {};
$scope.searchCriteria.sort[sortColumns[0].field] = sortColumns[0].sort.direction;
}
});
$scope.gridApi.pagination.on.paginationChanged($scope, function (pageNum, pageSize) {
$scope.searchCriteria.pageNumber = pageNum;
$scope.searchCriteria.pageSize = pageSize;
$scope.search();
});
}
};
The controller had the options called as "gridOptions", while the HTML had them called "adsGridOptions". Changing the name to "gridOptions" to both sides solved the issue.
Thank you, Alon Eitan!

Calling onload function in $ionicPopup without the use of "onTap" for inserting Bar Chart

Below is my code snippet and I wish to call a function "insertBarchart()" on loading the ionic popup. However I am not able to call without the use of "onTap" (which requires clicking the 'Show' button).
Note: The barchart is shown at the place of "container" which is defined inside popup so function call must be made within the scope.
$ionicPopup = Apperyio.get("$ionicPopup");
var alertPopup = $ionicPopup.show({
scope: $scope,
template: '<div id="container" style="min-width: 200px; height: 200px; margin: 0 auto" ></div>',
buttons: [{
text : 'OK',
type: 'button-positive'
},
{
text : 'Show',
type: 'button-positive',
onTap : function(e) {
$scope.insertBarchart();
e.preventDefault();
}
}]
});
In the same situation I tried in other way please check this code once
angular.module('ionic.example', ['ionic'])
.controller('PopupCtrl', function($scope, $timeout, $q, $ionicPopup) {
$scope.cmnt={};
$scope.showToast=function (message) {
if (window.plugins && window.plugins.toast) {
window.plugins.toast.showLongCenter(message);
}
else $ionicLoading.show({ template: message, noBackdrop: true, duration: 2000 });
}
$scope.showPopup = function () {
$scope.data = {};
var pop=$ionicPopup.show({
template: '<div class="list" dir="rtl"><label class="item item-input"><input ng-model="cmnt.name" type="text" placeholder="name"></label><label class="item item-input"><textarea ng-model="cmnt.body" rows="4" placeholder=" comment..."></textarea></label></div>',
title: 'write your comment',
subTitle: '',
scope: $scope,
buttons: [
{
text: 'cancel',
type: 'button-small'
},
{
text: '<b>save</b>',
type: 'button-energized',
onTap: function (e) {
return $scope.cmnt;
}
}
]
}).then(function (res) {
$scope.showToast(res.name);
});
}
});
Instead of $ionicPopup you can create a modal page in Appery that will have its own init() function and can be customized more easily

Building Hybrid Mobile Apps for YouTube Channel with ionic: Array return value 0

I'm new to this forum and also ionic. I was getting started with ionic following this tutorial but I got stuck at the step where they say I should have at least 5 returned object.
In my console, I see this:
Object {kind: "youtube#searchListResponse", etag: ""5g01s4-wS2b4VpScndqCYc5Y-8k/laShVU5DlHERrc8rfTBVxO0BH0k"", regionCode: "MY", pageInfo: Object, items: Array[0]}
As you can see, items array is Array[0]. What have i done wrong?
Here are my codes :
index.html and below is app.js
(function(){
var app = angular.module('BooWoow', ['ionic'])
app.run(function($ionicPlatform) {
$ionicPlatform.ready(function() {
if(window.cordova && window.cordova.plugins.Keyboard) {
cordova.plugins.Keyboard.hideKeyboardAccessoryBar(true);
}
if(window.StatusBar) {
StatusBar.styleDefault();
}
});
});
app.controller('bcontrol', function ($scope, $http){
// $scope.videos = [
// {
// title: "My first video",
// date: "1-1-2015",
// thumbnails: "http://i.ytimg.com/vi/bJp1ptX4F3M/maxresdefault.jpg",
// },
// {
// title: "My second video",
// date: "5-7-2015",
// thumbnails: "http://i.ytimg.com/vi/NA2VerbOyt0/maxresdefault.jpg",
// }
// ];
$scope.videos = [];
$scope.youtubeParams = {
key:'AIzaSyDUbabBoC8eqrsp7OZiIJ9_5RmnbVl08A0',
type: 'video',
maxResults: '5',
part: 'id,snippet',
q: 'youtube#searchListResponse',
order: 'date',
channelId:'UCosQ8Pm_9hU3Ck878svpKeQ',
}
$http.get('https://www.googleapis.com/youtube/v3/search', {params:$scope.youtubeParams}).success(function(response){
console.log (response);
// angular.forEach(response.items, function(child){
// });
});
});
}());
You have done everything right but the problem is about what to search for (value of q) and which channel to search (value of channelId).
As you see bellow I've changed the q and also removed channelId (which is not necessary) and result array is not empty any more.
(function() {
console.clear()
var app = angular.module('BooWoow', ['ionic'])
app.run(function($ionicPlatform) {
$ionicPlatform.ready(function() {
if (window.cordova && window.cordova.plugins.Keyboard) {
cordova.plugins.Keyboard.hideKeyboardAccessoryBar(true);
}
if (window.StatusBar) {
StatusBar.styleDefault();
}
});
});
app.controller('bcontrol', function($scope, $http) {
$scope.videos = [];
$scope.youtubeParams = {
key: 'AIzaSyDUbabBoC8eqrsp7OZiIJ9_5RmnbVl08A0',
type: 'video',
maxResults: '5',
part: 'id,snippet',
q: 'youtube',
order: 'date',
//channelId: 'UCosQ8Pm_9hU3Ck878svpKeQ',
};
$http
.get('https://www.googleapis.com/youtube/v3/search', {
params: $scope.youtubeParams
}).then(function(response) {
console.log(response.data.items.length);
});
});
}());
<script src="https://cdnjs.cloudflare.com/ajax/libs/angular.js/1.5.7/angular.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/ionic/1.3.1/js/angular-ui/angular-ui-router.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/ionic/1.3.1/js/angular/angular-resource.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/ionic/1.3.1/js/angular/angular-animate.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/ionic/1.3.1/js/angular/angular-sanitize.js"></script>
<link href="https://cdnjs.cloudflare.com/ajax/libs/ionic/1.3.1/css/ionic.css" rel="stylesheet" />
<script src="https://cdnjs.cloudflare.com/ajax/libs/ionic/1.3.1/js/ionic.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/ionic/1.3.1/js/ionic-angular.js"></script>
<div ng-app="BooWoow" ng-controller="bcontrol"></div>

Fire ionicModal on ionicPopup close

I want to open ionic modal whenever the user presses the Yes button, but close ionic popup whenever the user presses the No button. How can I do this?
At the moment, ionic popup opens up in each case. Here is my code so far:
services.js
function PopupService($ionicPopup) {
function acceptAppointmentPopup(scope) {
return $ionicPopup.show({
title: 'Are you sure you want to accept this appointment?',
scope: scope,
buttons: [{
text: '<b>Yes</b>',
type: 'button-positive',
onTap: function(e) {}
}, {
text: 'No',
onTap: function(e) {}
}, ]
})
}
return {
acceptAppointmentPopup: acceptAppointmentPopup
};
}
controller.js
function BusinessPendingAcceptanceCtrl($scope, PopupService, ModalService) {
$scope.newMessageModal = function() {
ModalService.show('templates/modals/new-message.html', 'ConsumerNotificationsCtrl as vm');
}
$scope.showAcceptAppointmentPopup = function() {
$scope.data = {}
var myPopup = PopupService.acceptAppointmentPopup($scope);
myPopup.then(function(res) {
$scope.newMessageModal();
});
};
}
$ionicPopup supports confirm (a YES, NO dialog) which returns a promise and as an argument passes the result. You can use it like this:
$ionicPopup.confirm({ // example taken from official documentation
title: 'Consume Ice Cream',
template: 'Are you sure you want to eat this ice cream?'
}).then(function (result) {
if (result) {
// At this point user confirmed that they want to eat the ice cream,
// so lets open a modal to visually show the user how the ice cream is being consumed
$ionicModal.fromTemplateUrl('my-modal.html', {
scope: $scope,
animation: 'slide-in-up'
}).then(function(modal) {
$scope.modal = modal;
$scope.modal.show();
// This is where the user starts drooling :P
});
} else {
// This user apparently hates ice cream, which is ridiculous...
}
});
You can get more info on the official documentation page.
Integrating my example into your code:
services.js
function PopupService($ionicPopup) {
function acceptAppointmentPopup(scope) {
return $ionicPopup.show({
title: 'Are you sure you want to accept this appointment?',
scope: scope,
buttons: [{
text: '<b>Yes</b>',
type: 'button-positive',
onTap: function(e) {
return true;
}
}, {
text: 'No',
onTap: function(e) {
return false;
}
}]
})
}
return {
acceptAppointmentPopup: acceptAppointmentPopup
};
}
controller.js
function BusinessPendingAcceptanceCtrl($scope, PopupService, ModalService) {
$scope.newMessageModal = function() {
ModalService.show('templates/modals/new-message.html', 'ConsumerNotificationsCtrl as vm');
}
$scope.showAcceptAppointmentPopup = function() {
$scope.data = {}
var myPopup = PopupService.acceptAppointmentPopup($scope);
myPopup.then(function(res) {
if (res) { // Here we check if user pressed Yes - Yes button returns true
$scope.newMessageModal();
}
});
};
}

Angular Grid in an Angular widget returns Error: [$injector:unpr] Unknown provider:

In the following code I have created an angular widget which uses an angular grid to pass data. However, I am getting the following error Error: [$injector:unpr] Unknown provider: alphadataProvider <- alphadata
The widget code:
'use strict';
angular.module('alphabeta.table.widgets', ['adf.provider', 'btford.markdown', 'ngGrid'])
.value('githubApiUrl', 'https://api.github.com/repos/')
.config(function(dashboardProvider){
dashboardProvider
.widget('reservationTotals', {
title: 'Reservation Totals',
description: 'Reservation Totals widget',
controller: 'reservationTotalsCtrl',
templateUrl: 'scripts/widgets/alphabeta/alphabeta.html',
resolve: {
alphadata: function(alphatradingService){
return alphatradingService.get();
}
},
edit: {
templateUrl: 'scripts/widgets/alphabeta/edit.html',
reload: false
}
});
})
The service
.service('alphatradingService', function($q, $http, githubApiUrl){
return {
get: function(){
var deferred = $q.defer();
$http.get('9_Response.json')
.success(function(data){
deferred.resolve(data);
})
.error(function(){
deferred.reject();
});
return deferred.promise;
}
};
})
The controller
.controller('reservationTotalsCtrl', function($scope, alphadata){
var tabledata = [];
var i, n;
var ycount=0, yexist=0;
var numf;
for(i=0;i<alphadata.length;i++){
yexist=0;
for(n=0;n<ycount;n++){
if (alphadata[i].stYear == tabledata[n].Year && alphadata[i].market == tabledata[n].Market) {
tabledata[n].Sales += alphadata[i].totSale;
tabledata[n].Sales = parseFloat(Math.round(tabledata[n].Sales * 100) / 100);
yexist++;
break;
}
}
if (!yexist) {
numf = alphadata[i].totSale;
tabledata.push({
Market: alphadata[i].market,
Year: alphadata[i].stYear,
Sales: parseFloat(Math.round(numf * 100) / 100),
CustomerName: alphadata[i].custName
});
ycount++;
}
}
$scope.data = tabledata;
$scope.gridOptions = {
data: 'data',
enablePinning: true,
columnDefs: [{ field: "Market", width: 60, pinned: true },
{ field: "Year", width: 60 },
{ field: "Sales", width: 60 },
{ field: "CustomerName", width: 60 }]
};
console.log($scope.data);
});
The alphabeta.html code:
<div>
<div ng-controller="reservationTotalsCtrl">
<div class="gridStyle" ng-grid="gridOptions"></div>
</div>
</div>
Can you please help me?
Try defining your resolve like this:
resolve: {
'alphadata': ['alphatradingService', function(alphatradingService){
return alphatradingService.get();
}]
}
I am sorry as I am seeing your question very late after it was asked. But my answer might help others who are stuck on similar problem. See get to the basic of the error which says,
Error: [$injector:unpr] Unknown provider:
Which means you have not resolved the dependency correctly for your injector which seems to be a service in your case as mentioned in angularjs document.
You could have tried:
resolve: {
alphadata: function(alphatradingService){
return alphatradingService.get;
}
In your service
$scope.get = get (get is your function defined in services)

Categories