I'm looking for a way to cancel the resolve of a Angular-UI Bootstrap modal and stop it from opening. The dismissAll method is not working because the modal instance is added to the modal stack only after the resolve has completed.
I have a website where modals open and close on route change. If dismissAll is called during route change to close any old modals it won't affect modals that are still resolving. So you come to the new route but the old modal still pops up after its resolve has completed.
As things stand right now, there is no way to cancel ES6 and $q promises. you can refer to this question for more info.
tl;dr Bluebird allows promise cancellation
If you really need it you can add bluebird to angular.
If you still want to use plain ol' $q, here's what I would have done
Pass the modal the current state (if using ui-router) or route (if using angular router).
When you need to render the modal template compare the current state to the provided state.
If they are not equal discard the modal
The modalInstance object exposes a rendered promise that will run when the modal finished rendering, you can place $uibModalStack.dismissAll(); inside.
Example:
modalInstance.rendered.then(function (currentState) {
if (currentState !== $state.current) {
$uibModalStack.dismissAll();
}
}, function () {
$log.info('Modal dismissed at: ' + new Date());
});
Of course you can defer your loading after rendering the modal and avoid this mess altogether.
This is by far the simplest way to make sure modals never stick around, and it works for apps with simple modal use. I’ve seen this working for years at several places and reliably. Essentially, you register a state change listener in your router and whenever there’s a state change you make sure to dismiss all open modals, whatever those might be. Again, this might seem harsh, but in some apps this works like a charm, and is better than nothing.
A simple example, using UI Router’s $transition service and Angular UI Bootstrap’s $uibModalStack, this can be as simple as:
$transitions.onFinish({}, function(transition) {
$uibModalStack.dismissAll();
});
And of course, if needed, you can only perform this for transitions that match a specific criteria.
Source: https://www.codelord.net/2017/12/11/reliably-managing-modals-in-angularjs/
Related
I have a JS component (SigPlot) that I need to read click values from. I have instantiated SigPlot inside of a VerticalLayout, where I also instantiate a DIV to pass to the SigPlot constructor. I am not sure if this is a valid way, but it works.
Now I need to read CLICKS but I am having troubles finding correct way to do this. Can someone pass some words of wisdom?
In my constructor for my VIEW, it use addAttachListener to start my JS code using.
div.addAttachListener(e->{
e.getUI().getPage().executeJs("myInit($0)",div);
});
How can I register a click listener to this?
Regards
As long as it's just a regular DOM event listener, then something like this should work:
div.getElement().addEventListener("click", event -> Notification.show("Clicked"));
If you need to do something on a more granular level, then your might want to expose callbacks as #ClientCallable and then use executeJs to run some short JavaScript snippets to set up listeners that delegate to those methods.
I have build a plugin (pluginA) based on zeptojs and inside this plugin I fetch data using ajax and attach a list of
How do I bind an event to these anchors? I was going for something globally like and then use $('[data-key]').pluginB() and then inside pluginB() have something like
$(this).on('click', function (e) { e.preventDefault(); ... }); but I am not able to bind the click event to anchors created dynamically.
I tried adding $('a').on('click', ...) before I call pluginA() but it's not firing.
What I really would like would be to use the bind() trigger() approach in order to decouple the two plugins, but I am having trouble finding a good example.
Use the delegating form of on to bind all desired links in a particular area (in this example, the entire body):
$(body).on('click', 'a[data-key]', function(e) {e.preventDefault();...});
Now all links with data-key will trigger your function, regardless of whether or not they were present at the time you called on; subsequently-added links will automatically get the behavior, and removed links won't leak memory by holding dangling handler references.
I added a ParameterHandler to my application's main window so I can catch and process custom get parameters in my url. However, the presence of one parameter reloads the first page of my application, for some reason building this page triggers the handleParameters method again, this time with no parameters passed. If left unchecked (e.g. no ifs) the page's elements will just replicate themselves on top of themselves over and over again.
I suspect it has something to do with my main windows's addComponent method.
How can I stop it from doing that?
I completely forgot I still had this question open. I found that the problem was that the method got triggered for both get and post type parameters, and this is what caused the unexpected output.
I already implemented an HttpServletRequestListener because I used Vaadin's ThreadLocal pattern, so I just filtered all GET parameters out of the request object in one of the implemented methods and went from there.
debug your application and have a view at the call stack of the handleParameters method
The view part of my code using Backbone.js is something like this:
var myView = Backbone.View.extend({
events: {
'focus .cell input' : "updateCurrentCell"
},
updateCurrentCell: function(event) {
console.log('updateCurrentCell called');
// Update the current cell.
}
}
Whenever the input element gets focus, the function is called twice. I tried printing the stack trace using console.trace(). It shows that once the function call originated from focus event while the next time from focusin.
My attempts to find out how to prevent one of these events getting fired lead me nowhere.
How can I fix this?
Backbone.View uses delegateEvents to bind the events listed in your events object. If you take a look at the source, you'll see that delegateEvents uses jQuery.delegate to do so.
There's a note in the jquery docs for .focus() that's probably relevant:
The focus event does not bubble in Internet Explorer. Therefore,
scripts that rely on event delegation with the focus event will
not work consistently across browsers. As of version 1.4.2, however,
jQuery works around this limitation by mapping focus to the focusin
event in its event delegation methods, .live() and .delegate().
In theory, this should just work fine, but since you're getting both, perhaps you could try to just listen for the .focusin() event, as it supports the kind of event bubbling .delegate() listens for and is what jQuery is trying to map 'focus' to anyway.
In Nitrogen, the Erlang web framework, you wire actions like this:
wf:wire(send_message, #event { type=click, postback=send_message })
but if after that you run
wf:wire(send_message, #event { type=click, postback=send_message2 }),
then you get the action wired twice.
How do you unwire the previous action or all actions of an element?
Since events in nitrogen are bound using jquery's bind method. You can use unbind to unbind them. There isn't currently a nitrogen api to unbind an event but you could output the javascript code to unbind it yourself if you so wished.
see action_event.erl for an example of how the binding javascript is output. You can create a similar action/event that removes the binding.
I too was looking for an "unwire" and didn't find it. My work-around was to wf:replace() the element to which the event was wired, and wire the replacement element; I hope that javascript will eventually notice the former bind can never be called and then garbage collect it. I don't know how expensive such abandoned bindings are. My context was a lazy loading of the page, such that a button would initially show a stub, but when clicked would download arbitrarily large content, and henceforth toggle hide/show.
Beyond being nervous about the sophistication of the javascript garbage collection, I'm worried that this may be a bad pattern, and would love to hear others' experience. The only alternative that occurs to me would be to keep state (e.g. data) in the original element and pass that state back with the event message so that the same event handler would act on the "unloaded->loaded_show->loaded_hide->loaded_show" transitions. But I'd prefer not to be calling back to the server for a simple hide/show transition.