Angular Material $mdDialog - Can't access 'this' items in confirm function - javascript

I'm trying to use the confirm function of an angular material $mdDialog to clear an array and then log this array to the console, but there seems to be an issue with accessing 'this' objects/arrays/expressions/functions within the $mdDialog function itself, with the console saying that whatever item references is undefined, even if used previously in other controller functions.
Does the $mdDialog directive have an issue with controllerAs syntax?
-
Controller:
app.controller('notificationsController', function($scope, $state, $http, $document, $mdDialog, $filter, $timeout) {
this.selectedNotification = null;
this.notifications = [
{
title: 'Notification One',
description: 'Description...',
time: '2017-10-27T16:39:32+00:00',
importance: 'Low',
read: false
},
etc...
$scope.clearNotifications = function(ev) {
var confirm = $mdDialog.confirm()
.parent(angular.element('body'))
.clickOutsideToClose(true)
.title('Are you sure you want to clear all notifications?')
.textContent('This action cannot be undone.')
.ariaLabel('Confirm notifications list clearance')
.ok('Yes')
.cancel('No')
.targetEvent(ev)
$mdDialog.show(confirm).then(function() {
$scope.status = 'All notifications deleted';
console.log($scope.status);
this.notifications.length = 0;
console.log(this.notifications);
}, function() {
$scope.status = 'Notifications list not cleared';
console.log($scope.status);
})
}

The this in:
$mdDialog.show(confirm).then(function() {
...
this.notifications.length = 0; // <---- here
...
}, function() {
...
})
refers to the promise resolve function of the promise returned by $mdDialog.show(), if you wanted to access the controller's notifications member you'd have to create a var that refers to the controller's this:
app.controller('notificationsController', function($scope, $state,
$http, $document, $mdDialog, $filter, $timeout) {
var _this = this; // <--- Now _this is the controller
this.notifications = [
{
title: 'Notification One',
description: 'Description...',
time: '2017-10-27T16:39:32+00:00',
importance: 'Low',
read: false
},
etc...
$scope.clearNotifications = function(ev) {
...
$mdDialog.show(confirm).then(function() {
...
_this.notifications.length = 0; //<--- using _this and not this
...
}, function() {
...
})
}

Related

ng storage of list at angular

i have a problem that i want to local storage a list and load it but
i found two problems that removing the item does not work well
and local storage is not working
.controller('tasksCtrl', [
'$scope',
'$stateParams',
'$localStorage',
function($scope, $stateParams) {
var dirlist = this;
var tasks = [
{
name: 'add task',
time: '12',
type: 'test'
}, {
name: 'do the home work',
time: '11',
type: 'study'
}
];
dirlist.list = tasks;
dirlist.toggle = false;
dirlist.addtask = function() {
dirlist.list.push({name: dirlist.name, time: dirlist.time, type: dirlist.type});
dirlist.name = '';
dirlist.time = '';
};
dirlist.remove = function(item) {
dirllist.splice(dirlist.list.indexOf(item), 1)
};
dirlist.saveData = function() {
$localStorage.list = tasks;
}
dirlist.loadData = function() {
dirlist.list = $localStorage.list;
}
}
])
local storage is not working
This is because you haven't passed the dependency in your controller.
You are passing only scope and stateParams.
Here's how you can fix it,
.controller('tasksCtrl', [
'$scope',
'$stateParams',
'$localStorage',
function($scope, $stateParams, $localStorage) {
Now, $localStorage can be used as localStorage service.
Hope it helps.
Cheers coding!

Angular promises

I am running into an asynchronous issue with my stats controller. I have a controller that queries the db and returns the objects. In this controller I use the filter to get the ones with the platform Facebook and I put this into $rootScope.facebookObjects.
First controller:
app.controller('statsCtrl', function ($scope, $log, $http, $timeout, $filter, Data, $rootScope) {
Data.get('stats').then(function(data){
$scope.stats = data.data;
$scope.currentPage = 1; //current page
$scope.filteredItems = $scope.stats.length; //Initially for no filter
$scope.totalItems = $scope.stats.length;
$scope.list_pages = [
{
id: '5',
name: '5'
}, {
id: '10',
name: '10'
}, {
id: '20',
name: '20'
}, {
id: '50',
name: '50'
}, {
id: '100',
name: '100'
}
];
$scope.maxSize = 5;
$rootScope.facebookObjects = $filter('filter')($scope.stats, { platform: "facebook" });
$rootScope.twitterObjects = $filter('filter')($scope.stats, { platform: "twitter" });
});
$scope.setPage = function(pageNo) {
$scope.currentPage = pageNo;
};
$scope.filter = function() {
$timeout(function() {
$scope.filteredItems = $scope.filtered.length;
}, 10);
};
$scope.sort_by = function(predicate) {
$scope.predicate = predicate;
$scope.reverse = !$scope.reverse;
};
});
I have a second controller that uses the $rootScope.facebookObjects to populate the chart. The problem is I need to wait until the $rootScope.facebookObjects has a value. Currently my console log shows undefined. I am looking into promises but I am a little unsure which controller to use it in and how to properly use it.
Second Controller:
app.controller("PieCtrl", function ($scope, $rootScope, $timeout, $log) {
$log.log('facebook - '+$rootScope.facebookObjects.length);
});
$rootScope.$watch('facebookObjects', function(newValue, oldValue) {
//do your job
});
while you could use $watch to watch it, but i'm not sure it's a good way to share data between the controllers, and even more data is acync.
I have created an example for you with angular factory:
HTML:
<div ng-app="jsfiddle">
<div ng-controller="MainCtrl">
Data: {{data}}<br>
</div>
<div ng-controller="SecondCtrl">
Data: {{data}}<br>
</div>
</div>
Angular:
var app = angular.module('jsfiddle', []);
app.factory('myService', function($http) {
return {
async: function() {
return $http.get('https://api.myjson.com/bins/1v21f');
}
};
});
app.controller('MainCtrl', function( myService,$rootScope, $scope, $timeout) {
$scope.data = "oron";
myService.async().then(function(d) {
$timeout(function() {
$rootScope.data = d;
}, 1000);
});
});
app.controller('SecondCtrl', function($rootScope, $scope, $timeout) {
$scope.test = $rootScope.data;
});
MainCtrl is calling myService and store the response on the $rootScope.
then the when the value is ready it will update the data object on the SecondCtrl.
Thank you everyone for your help. Here is what I came up with based off of your answers.
First Controller:
$scope.facebookObjects = $filter('filter')($scope.stats, { platform: "facebook" });
$scope.twitterObjects = $filter('filter')($scope.stats, { platform: "twitter" });
$scope.$broadcast('update_chart_controller', {
fb: $scope.facebookObjects,
tw: $scope.twitterObjects
});
Second Controller:
$scope.$on("update_chart_controller", function(event, args) {
$scope.data = [args.fb.length, args.tw.length];
});

How to load angular translation after some event

I have a TranslationService that is called after a login event, in this service I want to inizialize the $translateProvider.translation but this object seems not accessibile outside app.config(...). In the service I want to replace the previous translation.
Here some code:
.config(['$translateProvider', function ($translateProvider) {
$translateProvider.useStaticFilesLoader({
prefix: 'i18n/',
suffix: '.json'
});
$translateProvider.preferredLanguage('it');
}]);
While in my TranslateService I need something like
angular.module('myapp')
.factory('TranslateService', ['$translate', $translateProvider, function($translate, $translateProvider) {
$mydata = { "LABEL": "Label" };
$translateProvider.translations('it', mydata); // injection problem
$translate.somethingLike_getProvider().translations('it', mydata); // doesn't exist
}]);
The trick is to store $translateProvider in a variable that can be accessed later:
var app = angular.module('app', ['pascalprecht.translate']);
var provider = null;
app.config(function($translateProvider) {
provider = $translateProvider;
$translateProvider.translations('en', {
TITLE: 'Hello',
FOO: 'This is a paragraph.'
});
$translateProvider.preferredLanguage('en');
});
app.factory('inlineLoaderFactory', function($q) {
return function(options) {
var deferred = $q.defer();
deferred.resolve(options[options.key]);
return deferred.promise;
};
});
app.controller('MainCtrl', function($scope, $q, $translate) {
$scope.override = function() {
provider.useLoader('inlineLoaderFactory', {
en: {
TITLE: 'Hello My Friend',
FOO: 'TLDR',
CUSTOM: 'New Key'
}
});
$translate.refresh();
};
});
When a change to translations is required we tell $translateProvider to use inlineLoaderFactory translation loader service. The inlineLoaderFactory merely uses options as new translation data.

Angular-UI Modal Error: Expected response to contain an object but got an array

First of all, I know this error has been covered many times around here, and I read thoroughly many questions about this but no one seems to fit my problem exactly. Why? Well most of them are not related to the Angular UI modal and the way it asks for the resources to display.
I'll start showing you my controller:
'use strict';
// Customers controller
angular.module('customers').controller('CustomersController',
['$scope', '$stateParams', '$location', '$filter', 'Authentication', 'Customers', '$modal', '$log',
function($scope, $stateParams, $location, $filter, Authentication, Customers, $modal, $log ) {
// Find a list of Customers
$scope.find = function() {
Customers.query(function (data) {
$scope.customers = data;
$scope.buildPager();
});
};
// Find existing Customer
$scope.findOne = function() {
$scope.customer = Customers.get({
customerId: $stateParams.customerId
});
};
//List Pager
$scope.buildPager = function () {
$scope.pagedItems = [];
$scope.itemsPerPage = 15;
$scope.currentPage = 1;
$scope.figureOutItemsToDisplay();
};
/* Modal stuff */
$scope.animationsEnabled = true;
$scope.openUpdateModal = function (size, selectedCustomer) {
var modalInstance = $modal.open({
animation: $scope.animationsEnabled,
templateUrl: 'modules/customers/views/edit-customer.client.view.html',
controller: function ($scope, $modalInstance, upcustomer) {
$scope.upcustomer = upcustomer;
},
size: size,
resolve: {
upcustomer: function () {
return selectedCustomer;
}
}
});
modalInstance.result.then(function (selectedItem) {
$scope.selected = selectedItem;
}, function () {
$log.info('Modal dismissed at: ' + new Date());
});
};
$scope.toggleAnimation = function () {
$scope.animationsEnabled = !$scope.animationsEnabled;
};
//Controller Closing brackets
}
]);
In the view I have a list of customers, so if I click one of them I want the modal to open:
<a data-ng-repeat="customer in pagedItems" ng-click="openUpdateModal('lg', customer)" class="list-group-item"></a>
I did this thing based on a Bossable.com video tutorial called: MEAN Stack: 20 - Pass Customer Details to an Angular UI Modal
The only difference is that I got this error when clicking a customer:
[$resource:badcfg] Error in resource configuration. Expected response to contain an object but got an array
Thanks for your time.
Just remove the $scope.findOne function because it uses the get method and returns and array. If you look back at her tutorial, she kept it commented.
Your problem is to do with your Customer.query() or Customer.get() call. These are $resource calls and expect to be told what the response is.
Usually a get method expects an object while the query method expects an array. If you're not return one of those for those methods you need to configure it using the isArray: true/false option depending on your needs.
Documentation on this can be found:
https://docs.angularjs.org/api/ngResource/service/$resource
$resource( 'apiendpoint', {}, {
query: {
isArray: false
}
});
}

Advice on workflow for an 8 step application with ANGULAR.js

I'm creating an application with Angular.js and I'm getting a bit confused of how to use Angular to make it.
Below, you can see a preview of what I have for the moment, it's ugly but it works.
I just feel like there is much better ways of doing this, and would like to get other user inputs, knowing this :
The application will:
1) collect inputs over 8 steps
2) dependeing of those inputs, display specific results.
3) Being able to go to any state at any moment
// Create an application module
var app = angular.module('website', ['ngSanitize','ngAnimate','ui.router']);
app.config(function($stateProvider, $urlRouterProvider) {
$urlRouterProvider.otherwise("/home");
$stateProvider
.state('home', {
url: "/home",
templateUrl: "js/partials/home.html",
controller: HomeCtrl
})
.state('step1', {
url: "/step1",
templateUrl: "js/partials/step1.html",
controller: Step1Ctrl
})
.state('step2', {
url: "/step2",
templateUrl: "js/partials/step2.html",
controller: Step2Ctrl
})
.state('step3', {
url: "/step3",
templateUrl: "js/partials/step3.html",
controller: Step3Ctrl
})
.state('step4', {
url: "/step4",
templateUrl: "js/partials/step4.html",
controller: Step4Ctrl
})
.state('step5', {
url: "/step5",
templateUrl: "js/partials/step5.html",
controller: Step5Ctrl
})
.state('step6', {
url: "/step6",
templateUrl: "js/partials/step6.html",
controller: Step6Ctrl
});
});
function getNewPercentageValue(step,percent){
var NewPercentage = 0;
if(percent){
NewPercentage = percent * step;
}else{
$rootScope.values.ActualPercentage = (100/8);
NewPercentage = $rootScope.values.ActualPercentage * step;
}
return NewPercentage;
}
function HomeCtrl($scope, $http, $rootScope, $state) {
/* DEFAULT VARIABLES */
$rootScope.values = {
ActualPercentageSteps: (100/8),
ActualPercentage: 0
};
}
function Step1Ctrl($scope, $http, $rootScope, $state) {
$rootScope.values.ActualPercentage = getNewPercentageValue(1,$rootScope.values.ActualPercentageSteps);
$scope.services = [
{name: 'Service 1', id: 1},
{name: 'Service 2', id: 2},
{name: 'Service 3', id: 3},
{name: 'Service 4', id: 4},
];
$scope.FormCtrlAddService = function(service){
};
$scope.FormCtrlRemoveService = function(service){
};
}
function Step2Ctrl($scope, $http, $rootScope, $state) {
/*
STEP 2
*/
$rootScope.values.ActualPercentage = getNewPercentageValue(2,$rootScope.values.ActualPercentageSteps);
$scope.FormCtrlAddKeyword = function(keyword){
};
$scope.FormCtrlRemoveKeyword = function(keyword){
};
$scope.updateValue = function(value){
};
}
function Step3Ctrl($scope, $http, $rootScope, $state) {
/*
STEP 3
*/
$rootScope.values.ActualPercentage = getNewPercentageValue(3,$rootScope.values.ActualPercentageSteps);
}
function Step4Ctrl($scope, $http, $rootScope, $state) {
/*
STEP 4
*/
$rootScope.values.ActualPercentage = getNewPercentageValue(4,$rootScope.values.ActualPercentageSteps);
}
function Step5Ctrl($scope, $http, $rootScope, $state) {
}
function Step6Ctrl($scope, $http, $rootScope, $state) {
}
function Step7Ctrl($scope, $http, $rootScope, $state) {
}
You can define your controllers using app.controller("MyCtrl", function($scope){}) and then don't need to have all the globally defined functions (just reference them using a quoted string like controller:"MyCtrl").
Aside from that you can move your common data into a service or factory since both end up being singletons and will persist the data throughout the lifetime of the application, here's a plunk showing an example:
http://plnkr.co/edit/4OYWi35Ke2GGDB6wY2W9
main thing to note here is use of angular.copy when attempting to replace the entire object instead of just using = since both controllers are just pointing to the same referenced object so I don't ever want to create a new object and point the service at that or things would get disconnected.
var app = angular.module('plunker', []);
app.controller('MainCtrl', function($scope, Service) {
$scope.items = Service.items;
$scope.someModel = {};
$scope.addItem = function(item){
Service.addItem(item);
}
$scope.resetItems = function(){
Service.resetItems();
}
});
app.controller('AnotherCtrl', function($scope, Service) {
$scope.items = Service.items;
});
app.service('Service', function($timeout){
var someService = {
items:[],
id:0,
addItem:function(item){
someService.items.push({label:item, id:someService.id++});
},
resetItems:function(){
someService.id=0;
//simulated HTTP call
$timeout(function(){
angular.copy([], someService.items);
})
}
};
return someService;
})

Categories

Resources