I have a $scope.$on function which works fine when I'm leaving an unfinished operation on a tab to another:
$scope.$on("$stateChangeStart", function(event, toState) {
if (some conditions) {
event.preventDefault();
$modal.open({
templateUrl: 'prompt modal template',
controller: 'prompt modal controller',
backdrop: 'static',
size: 'sm'
})
.result.then(function (result) {
if (result === 'confirm') {
myService.doSomething(arg).then(function(result) {
$scope.doAnotherThing();
});
$state.go(toState.name);
}
else {
//stay where you were
}
});
}
});
Now I'd like to add ui-select2 change event to this function, so when user is trying to change the ui-select2 option while they have not finished the operation, the prompt modal would pop up and prevent any changes unless user confirms.
My ui-select2 ng-change="selectCity()" which it looks like:
$scope.selectCity = function() {
//some stuff
}
I tried adding $scope.selectCity/selectCity as an event after $stateChangeStart, but didn't work.
I would appreciate if someone could help me with this! Thanks
Related
I've want to display a popup, but with a bit of delay. The problem is that when I'm not delaying the popup the buttons aren't working and when I'm adding the delay the buttons don't show up! I've read online that the $timeout is an async function, but that isn't the issue, or is it?
The popup:
var myPopup = $ionicPopup.show({
templateUrl: 'templates/components/welcomePopup.html',
scope: $scope,
buttons: [{
text: 'Hejdå!',
type: 'custom-save-button',
onTap: function (e) {
$scope.showSpinner = true
}
}]
})
How I delay it:
$timeout(function (){
// Popup here
}, 3000)
But when adding a delay my buttons aren’t showing and without they delay nothing is working.
buttons: [{
text: 'Hejdå!',
type: 'custom-save-button',
Does anyone know a quick fix?
This is the code at the moment:
$timeout(function() {
var myPopup = $ionicPopup.show({
templateUrl: 'templates/components/welcomePopup.html',
scope: $scope,
buttons: [{
text: 'Hejdå!',
type: 'custom-save-button',
onTap: function (e) {
$scope.showSpinner = true
}
}]
})
}, 3000)
Thanks for reading! :)
Well I managed to solve half of the problem. I suspected that the problem had something to do with the $scope and apparently I was correct.
So I added another $scope to:
var myPopup = $ionicPopup.show({
templateUrl: 'templates/components/welcomePopup.html',
scope: $scope.$scope, // added $scope
buttons: [{
text: 'Hejdå!',
type: 'custom-save-button',
onTap: function (e) {
$scope.showSpinner = true
}
}]
})
However, the buttons aren't working yet!
Your button is not working because when you do something on your $scope in the timeout context, you're not anymore in your controller context.
The variable showSpinner should be actually set to true when you tap on the button, the problem is that Angular isn't aware that the value has changed, and therefore does not refresh the view.
To solve this, you can force a refresh by adding that piece of code after you change the value in your scope:
if ($scope.$root.$$phase !== '$apply' && $scope.$root.$$phase !== '$digest') {
$scope.$apply();
}
The condition is to prevent a refresh request while there is already one in progress.
Therefore, I don't think you need to pass a $scope inside your main $scope.
Hope this helps!
I'm using the following code for some validation stuff using both $ionicPopup and Firebase:
onTap: function(e) {
firebase.auth().applyActionCode($scope.data.emailcnfrm)
.then(function() {
return $scope.data.emailcnfrm;
},
function(error) {
alert("wrong code");
e.preventDefault();
});
}
But In the case of error, and after I get the "wrong code" alert, the popup gets closed, as e.preventDefault(); has been ignored.
So what's exactly wrong in my code? and how can I fix this problem?
Your call to firebase.auth().applyActionCode is asynchronous, and e.preventDefault will be called asynchronously in the error callback. This happens after the user has already invoked onTap, thus e.preventDefault won't have any effect.
Edit (a proposed fix)
To fix it, you could separate the async logic from the onTap method:
var myPopup = $ionicPopup.show({
onTap: function(e) {
// always keep the popup open, because we'll decide when to close it later
e.preventDefault();
}
});
myPopup.then(function(res) {
firebase.auth().applyActionCode($scope.data.emailcnfrm)
.then(function() {
// if successful, imperatively close the popup
myPopup.close();
}, function(err) {
// log the error, or something
});
});
Finally I solved the problem by using my own trick:
-outside Async:
$scope.myPopup = $ionicPopup.show({
scope: $scope, buttons: [
{ text: 'Cancel' },
{
text: '<b>Done</b>',
type: 'button-positive',
onTap: function(e)
{
// always keep the popup open, because we'll decide when to close it later
e.preventDefault();
$AsyncCallback();
}
}
]
});
$scope.myPopup.then(function(){},
function(error)
{
$ionicPopup.alert({
title: 'Internal error!',
template: error
});
});
-inside async:
$scope.myPopup.close();
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
I'm using the Angular module based on fullcalendar: https://github.com/angular-ui/ui-calendar along with the dialog module from ng-bootstrap. I configured the calendar to show a dialog for editing an event on eventClick action. It works fine only once. After closing first dialog and clicking again on any event new dialog doesn't show. But when I click on any other link on page, all desired dialogs shows one by one like they're queued somewhere some way.
Here's snippet from my controller:
$scope.showEditVisitDialog = function (event) {
var editVisitDialogOpts = {
backdropClick: false,
templateUrl: 'views/addEditVisitDialog.html',
controller: 'AddEditVisitDialogController',
resolve: {
patientId: function () {
return event.patientId;
},
visitId: function () {
return event.id;
}
}
};
var editVisitDialog = $dialog.dialog(editVisitDialogOpts);
editVisitDialog.open().then(function (updatedVisit) {
//some action
});
};
$scope.calendar = {
height: 450,
editable: true,
header: {
left: 'month agendaWeek ',
center: 'title',
right: 'today prev,next'
},
eventClick: $scope.showEditVisitDialog
};
$scope.events = [];
$scope.eventSources = [$scope.events]
Events are fetched from REST later in the controller.
In html:
<div ui-calendar="calendar" config="calendar" ng-model="eventSources"/>
No errors in console, what am I doing wrong?
Code on plunker: http://plnkr.co/edit/89sQfsU85zN4uxauFI2Y?p=preview
As always, things are simpler and more obvious when there's a fiddle/plnkr available. You need to place your call to showEditVisitDialog inside the $apply function:
...
$scope.calendar = {
editable: true,
eventClick: function(){
$scope.$apply(function(){
$scope.showEditVisitDialog()
});
}
};
...
Working plnkr.
you need to declare you fnction before uiConfig for the calendar ;)
I have a requireJS setup where I have an 'imageGallery' module which listens for and handles
click events on '.gallery' elements. This in turn uses a plugin 'magnificPopup' to open a
gallery of images based on the clicked element.
I want to test this using Jasmine; that is I want to test that the click event is called and that
the html for the magnificPopup is in the dom - proving that the click event is successful.
My current click test uses 'waitsFor' but this is always failing. Any ideas on how I can acheive this?
Image Gallery Module
define(
['jquery', 'magnificPopup'],
function($, magnificPopup) {
return {
init: function() {
$('body').on('click', '.gallery', function(e) {
e.preventDefault();
//code to generate items...
$.magnificPopup.open({
items: items,
gallery: { enabled: true }
});
});
}
}
})
Image Gallery Jasmine Test
define(['imageGallery'],
function(imageGallery) {
jasmine.getFixtures().fixturesPath = '/';
describe('Image Galleries', function() {
beforeEach(function(){
loadFixtures('/path-to-my-fixture');
spyOn(imageGallery, 'init');
imageGallery.init();
});
it('Should be defined', function() {
expect(imageGallery).not.toBe(null);
});
it('Should be initialised via imageGallery.init()', function() {
expect(imageGallery.init).toHaveBeenCalled();
});
//fails
it('Should open a modal after a .gallery element is clicked', function() {
$('.gallery').click();
waitsFor(function() {
return ($('body').find('.mfp-ready').length > 0)
}, '.gallery to be clicked', 500);
});
});
}
);