I am using Angular Bootstrap Modal to open a bunch of modals including video player inside
http://angular-ui.github.io/bootstrap/#/modal
I want to be able to keep where the video is at even if the modal is closed. It's just so next time I open the same modal again, I can see where I left off in the video.
In order to do that, I need to do:
Create each modal a separate instance
Instead of close(), I need to hide() the modal instead. Therefore the DOMs are still in there and the video player don't get re-created
What's the elegant way to do this as the Bootstrap modal has no hide feature. Should I just use jQuery to show/hide the .modal-backdrop and .modal classes?
From Don't destroy an Angular Bootstrap modal on close:
Why don't you abstract the modal state into its own service? That way, whenever the modal controller is created, it uses the service to setup the view state on initialisation.
Eg. create a service
.factory('ModalStateService', function(){
var state = {
someValue: 'something'
};
return {
getState: function() { return state; }
};
});
Then in your controller:
.controller('ModalCtrl', function($scope, ModalStateService){
$scope.viewState = ModalStateService.getState();
});
Then in your modal content view for example:
<span>{{viewState.someValue}}</span>
If you were then to set someValue inside your modal, say through an input, the service state would be updated. Then when you create and destroy your modal, the state will persist.
Related
I have a requirement that I am trying to implement as follows -
I have an audit log page which has a button to display the logs on a new browser window, while continuing to do other stuff on the application open in the main window.
We use ui-router and angularjs (1.6). Below is my code -
Route to the controller -
.state('auditlog', {
url: '/auditlog',
templateUrl: 'app/system/audit/audit-log.html',
controller: 'AuditLogController',
controllerAs: 'al'
})
On the click event of a button in a different controller, I have the following code -
unDockEventsPanel(event) {
let location = this.$state.href('auditlog');
this.$window.open(location, '', 'scrollbars=no,fullscreen=yes,toolbar=no');
}
and the HTML -
<i class="Icon-MoveOut Icon-Large icon-btn" ng-click="eventsPanelVM.unDockEventsPanel($event)">
Now, when I click on the "MoveOut" button the unDockEventsPanel() method gets called and a new window is opened with the contents of the controller/template in the route definition "auditlog".
The problem I'm facing however is, any operation I perform on the child window is randomly triggering something else on the parent window and vice versa. For eg. When I click on a select button in the child window, the select opens up on the child, but also, on the parent the a text box comes into focus like it would if I had clicked it. Likewise, when I click a select on the parent, a different control on the child gets highlighted.
I can see that a new instance of the application/controller is not created on the child and hence there is an overlap of the controls and events between the two. But I'm not able to figure out how to isolate the two.
Any help is greatly appreciated.
I believe the issue is related to the use of '$state'
let location = this.$state.href('auditlog');
this.$window.open(location, '', 'scrollbars=no,fullscreen=yes,toolbar=no');
from the angular-ui github wiki
When a state is activated, its templates are automatically inserted into the ui-view of its parent state's template.
I would suggest trying to avoid the use of $state by using plain old Javascript to do the new window navigation
window.open("{yourURL}/auditlog", 'scrollbars=no,fullscreen=yes,toolbar=no');
I have an Angular Component that I have downgraded so it can be used in AngularJs. It is used in a pop up modal dialog, The downgrade is successful and the component is functioning as it is supposed to but the only problem is when the modal dialog is closed, these changes are not reflected in the Angular component.
Every time the component runs and also when the model dialog is opened the ngOnInit life cycle is used for async data.
in the application view the component is in angular enviroment and used like so:
<interaction-component [interactionComponentData] = "data"></interaction-component>
in the pop up model dialog it is in angularJS enviroment and used like so:
<interaction-component [interaction-component-data] = "data"></interaction-component>
Say i have an interaction button that when clicked it displays a count in the component's view, when this action is performed and the component is running in Angular it updates the count and when the model dialog is launched - the component is running in AngularJs. Becuase of the ngOnInit - the count will be updated everytime the component runs/re-runs.
Before the model dialog is launched this component has a count of 3. Modal Dialog launches the count is still 3, now i click on the component's interaction button and increment the count to 4. In the dialog I see a count of 4 but when the dialog is closed the same component in Angular still has a like count of 3.
this is what's happening:
AngularJs count 3
Angular count 3
click and increment count in modal dialog to 4
AngularJs count 4
Angular count 3
close model dialog
Angular count 3 ( this count should be 4)
Is it possible for theses changes to keep in synch so when the changes are made in Angular are reflected in AngularJS (vice versa)?
From comments
changes are applied on depending on the toggleClick method which does many things, increments the count, toggles like: true || false. and then communicates with the server and makes a PUT. here is an extract from the method its self:
toggleClick(): void {
this.interactionComponentData.liked = !this.interactionComponentData.liked;
this.interactionComponentData.count = this.interactionComponentData.liked ? this.interactionComponentData.count + 1 : this.interactionComponentData.count - 1;
}
then the ngOnIt makes a request to get the changes applied using the toggleClick method.
ngOnInit(): void {
this.interactionComponentData = post.get({}, {}, endpoint);
//Other code for DOM use
}
what I am trying to achieve here is when the modal dialog is open, when the button in the interactionComponent is clicked, both of the component are updated. In the modal popup Dialog and outside the modal popup dialog. Please note in the modal dialog the component is downgraded, outside the modal popup dialog it is not.
I'm currently experiencing a problem with Bootstrap Modal, when changing views through the URL. ReloadOnSearch is disabled.
If I'm on a view such as:
blah.com/examples/1
and open up a Modal with a faded backdrop, then change the URL to change views such as:
blah.com/examples/2
the Modal window will close, but the faded backdrop will remain, and disable interaction to the web page.
I'm wondering if there is a way to define one function, which will programmatically remove the faded backdrop, which will execute on URL change, regardless of the controller in use.
Though the cause of the issue is due to AngularJS, the solution doesn't need to use AngularJS.
I had same issue, the solution is to remove that overlay class while your hashurl change
window.onhashchange = function() {
$(".lean-overlay").fadeOut(500); // whatever class name your overlay has
}
Use the event onhashchange to hide all modals on screen using the proper hide method:
window.onhashchange = function(event) {
$('.modal').modal('hide');
// You can even add some tests based on the new and old URL
console.log('new URL', event.newURL);
console.log('old URL', event.oldURL);
}
I am using Angular Bootstrap to display a Modal (the one presented here), which works perfectly. However, default behavior of this Angular extension is that the modal is reconstructed (and a new instance of its controller will be creatred) whenever it is closed and then opened again.
Since I have some pretty advanced stuff going on inside the Modal, I would like the modal to just be hidden when it is closed, so that its state remains. I have searched around a bit, but unfortunately could not find a simple and effective answer.
Just hiding it would be an option, but this then has to happen whenever the modal is closed, so also when it closes because the backdrop is clicked. And I want the same animation as when the modal is opened in the normal way.
Why don't you abstract the modal state into its own service? That way, whenever the modal controller is created, it uses the service to setup the view state on initialisation.
Eg. create a service
.factory('ModalStateService', function(){
var state = {
someValue: 'something'
};
return {
getState: function() { return state; }
};
});
Then in your controller:
.controller('ModalCtrl', function($scope, ModalStateService){
$scope.viewState = ModalStateService.getState();
});
Then in your modal content view for example:
<span>{{viewState.someValue}}</span>
If you were then to set someValue inside your modal, say through an input, the service state would be updated. Then when you create and destroy your modal, the state will persist.
As you might already know Angular initializes a controller when the associated view is added to the DOM. So the plugin author might have decided to add and remove the view element so that he does not have to worry about clearing the 'scope'each time user opens and closes the modal.
For example, we have a login box in the modal and if the scope is not cleared, it will keep the filled in details even the next time we show it.
An easy hack to solve your problem will be to wrap the originl modal in a custom directive, reneder it. And just change the display property of your custom modal to show and hide the modal ;)
Using Angular Bootstrap UI I am opening a modal to allow the user to make some selections... from that modal the user can click on a help icon that would in turn open another modal. The second modal opens and displays perfectly, but I cannot trigger any functions from the second modal. I am trying to use ng-click for both the first and second modals.
I figured out what I was doing wrong... when I initiated the 2nd modal I wasn't passing in scope.
$scope.rptHelp = function() {
$modalInstance2 = $modal.open({
templateUrl: 'rptHelpModal.html',
scope: $scope //this line was missing
});
}