I created a plunker to recreate the problem:
http://plnkr.co/edit/sPPB0Cq0PUg1jmzzZtXh
It contains a mini angular js app with angular-ui-bootsrap.
index.html - main html file with js includes and a ng-view div.
other.html, main.html - the views
app.js - main angular js file with declaration of app.
modal.js - some js stuff related to the modal.
I wrapped $modal with my own service that responds to a
broadcasted "show-modal" event by showing a modal and created a
directive that attaches to elements as an attribute and
emits/broadcasts this event.
The problem:
I'm trying to use $modal service to open a modal window.
It opens, then after I close it, i cannot open it again.
Actually, when trying to open again, it appears to not open. but when navigating to another location in the angular app the modal suddenly appear(or modals if you clicked many times) .
I'm kinda lost and the documentation didn't really help me.
Can anyone check it out and tell me what am i doing wrong?
After reviewing some cases in which the modal does work, i think i got a solution up at the same plunker i put before
http://plnkr.co/edit/sPPB0Cq0PUg1jmzzZtXh
You have to use $modalInstance to .close() and .dismiss() the modal.
the docs suggest one could use the injected $close $dismiss functions but using these caused the problem for me...
I left the problem as is and implemented the solution in new files so you can review both (at your pleasure).
--- EDIT ---
if all fails $scope.apply() (or $rootScope.apply())
i tried to scope.apply after issuing the signal to open the modal and it successfully showed the modal immidietaly instead of on the next cycle (which was triggered for example by going to another page)
Related
Problem:
Anyone know why in my cb.register function below, my Modal window closes OK, but the $location.url('/dashboard') does not properly run?
I don't get any console errors, and the page does not redirect. However, console.log('TRANSITION DONE') still prints out in the code below after the modal window closes, so I know the event is being recognized:
Code:
app.controller('userController', ['$scope', 'userFactory', '$location', function($scope, userFactory, $location) {
var cb = {
register: function(createdUser) {
// Closes Modal window:
$('#myModal').modal('hide');
// Runs after close with completed transition effects:
$('#myModal').on('hidden.bs.modal', function (e) {
console.log('TRANSITION DONE');
$location.url('/dashboard');
})
},
};
}]);
Questions:
Why does the $location service not behave properly when nested inside of my .on() function?
Should I be using angular-ui instead? (Of which I was not familiar until researching solutions to this issue, and instead started my project by framing out all the views first using bootstrap3 and including the JS files, etc).
What I've Tried:
I've tried passing the $location parameter into the .on()'s callback function, along with e, but that made no real change and the function should still have access to $location in the larger scope.
Console logging $location or $location.url works properly, so I know the methods are accessible in the scope.
Moving the $location function outside of the on() function does load the dashboard page, however the fade-out modal close does not complete. A light-grey transparent BG is overlaying my dashboard page, which is why I chose to utilize the hidden.bs.modal event per the documentation: http://getbootstrap.com/javascript/#modals
// Closes window:
$('#myModal').modal('hide');
// Redirects to page but fade-out on Modal not completed:
$location.url('/dashboard');
Desired Behavior/Pseudo-Code:
Modal window closes (when callback runs)
After Modal fade out:
$location.url('/dashboard') runs, loading dashboard page
Thank you to any angular/bootstrap ninjas whom can help!
Why does the $location service not behave properly when nested inside of my .on() function?
You're directly using Bootstrap modals in your application -- which is OK. But, this requires you to manipulate the modal with jQuery. It is not advisable to use jQuery in an AngularJS application as AngularJS has its own methods of DOM manipulation and therefore you shouldn't manually manipulate the DOM via jQuery.
To answer your question, since you're using jQuery to directly manipulate the DOM, it is likely that AngularJS' digest cycle has not picked up on the modal closing. You could get around this by telling AngularJS to activate a digest cycle via $scope.$apply(). However, this will easily dirty up your code and just doesn't make sense according to best AngularJS principles.
Should I be using angular-ui instead? (Of which I was not familiar until researching solutions to this issue, and instead started my project by framing out all the views first using bootstrap3 and including the JS files, etc).
Yes. I would highly suggest using angular-ui. As per the documentation:
This repository contains a set of native AngularJS directives based on Bootstrap's markup and CSS. As a result no dependency on jQuery or Bootstrap's JavaScript is required.
As you can see, all of the Bootstrap functionality has been wrapped up into AngularJS directives that can easily be dropped into your application without worrying about jQuery.
What's the best way to have my views appear in a popup modal?
I have the main dashboard of my app, and then whenever the user wants to add or edit an item on the dashboard I want this to be done via a form in a popup modal.
I know I can use jquery to handle the showing and hiding of the popup. But is there an angular way to do this, or is jquery acceptable in this scenario?
Check this out and go down to the modal section. This looks nice and clean. There is an example of the html and javascript there for you. Your view is a template and can be a html file or inline html inside the javascript.
http://angular-ui.github.io/bootstrap/
Much like everything in Angular, there are a number of ways you could do this. Perhaps the most simple way would be to have the HTML of the modal be hidden by either ng-show or ng-hidein conjunction with ng-mouseover.
I'm actually doing this right now and decided to use jquery ui for the modal. Dragging and resizing is hard to do and my modal requires that. I wrap the modal call in a directive so modal pops up onclick. The mistake I made was using jquery append to add new html. Don't do this. Use template or templateUrl and then put that in your modal. This will ensure all scope vars in your modal will communicate with your controllers.
I am using Angularjs UI bootstrap to render Modal windows in my project. But In some situation I want to call a function after the modal loads. I have tried with $timeout and $viewContentLoaded but no use. can any one help me to resolve this issue.
Thank you all.
I go through the documentation of angular ui bootstrap and finally I found the solution.
The open method returns a modal instance, an object with the opened propertie:
opened - a promise that is resolved when a modal gets opened after downloading content's template and resolving all variables
to call function after model opens.
$modalInstance.opened.then(function(){
alert('hi');
});
Alternatively, you can use:
$modalInstance.rendered.then(function(){
alert('hi');
});
PS: this was originally pointed by #esqew user. I put it here just to be easier to find.
I am using $modal for opening modals.
I have a modal that contains a ui-view. States using the ui-view need to wait until the modal has been added into the DOM, otherwise the states will not find the ui-view to load templates into.
Anyone have a good way for delaying the loading of a template? I have considered a promise that resolves once the modal's controller has been initialized, but I fear it is overcomplicating things.
Thanks
So if anyone is going down the same road, I ended up using Jquery-based foundation for my modal control, rather than the angular-foundation $modal service. With the jquery foundation modals, I can add a hidden modal div to my main template, containing the ui-view. So there is never any waiting for the modal to be appended to the DOM. Activating the modal is just unhiding the modal's div. This solved all timing issues and works as intended.
I'm trying to implement the http-auth-interceptor for angularjs, but anywhere I put the event listener $on, the page stops loading.
Here is the plunker of the problem: http://plnkr.co/edit/gQvBW2?p=preview
Now, if the directive-auth.js is commented out, then the page will load fine.
I've even tried to put the event listener in the module.run area, but the same result occurs.
The app.js file needs to be the last script file loaded. app.js runs the angular app, so any directives, services, etc would not get included, and may throw an error. In your plunkr, moving the script tag to the bottom fixes the issue.