the problem is this, I have a little jquery code to handle a menu with dropdowns lists inside of it, at first I have a login component when the user logs-In I call that code from the mounted hook of the main component (there is window onClick inside the code and I put a console.log to make tests), and everything works fine, now when the user logs-out and then another user (or the same user) logs-in again the code its been called again (because of the mounted hook) and when he/she clicks something I get two console.logs.
if the page is reloaded everything works great and the function is called once but as soon as the user logs-in, logs-out, logs-in, etc..... then I get multiple console.logs.
What is the proper way to load this jquery code (I know that everything jquery does, vue do it as well).
How to destroy/re-call that code without having it twice.
a dirty solution that comes to me is to load the code in the main .html file and then reload the page when the user is in the main page.
thanks in advance.
UPDATE:
Hi, thanks for your replies, Im using vue-router so in the loggin component there is no need of the jquery code, I need it in the dashboard component where the menu lives thats why I load the code in the mounted hook, a piece of code is just a window.addEventListener('click', ......) and this code shows a console.log just for testing, so when the user logs-in the jquery its been loaded, when the user logs-out and then log-in the jquery code its been loaded again so I will have 2 console.logs when the user clicks the window, I'll try your solutions.
FINAL:
Well, thanks to everyone, what I ended up doing was to use jquery's bind function $(window).bind('click' .....) and then in the beforeDestroy hook just $(window).unbind() and eveything works great.
First I would recommend to not use jQuery together with Vue! As you already said, Vue is a framework which can manipulate the DOM without needing jQuery's help.
But anyways, a quick 'vue way' solution is to use the beforeDestory hook on your login component, and clear your jQuery events.
beforeDestroy() {
// Clean the listeners.
}
P.S. For next time, would be better to show some code :)
If I understand your problem correctly, you need to check to see if your handler exists already before setting it. That way if it already exists you won't add it again.
In mounted() check if typeof window.onclick == 'object' if it does, then you haven't set it yet and you can set your handler window.onclick = function() {}
If it is set then typeof window.onclick would equal 'function'
Related
When a page is routed to another page or when a user presses the Back, Forward, or Refresh buttons, the alert window is displayed and the user selects Move, and the user wants to proceed with the initialization process.
For unload events, this does not occur in page routing. Attempted to use canDeactivate, but failed to execute a specific function after closing the alert window.
I want to know the detailed method and example.
(I'm not familiar with the anglular)
Yes. I can think of two potential solutions to your problem:
-1- If you are using Angular Material Dialog combined with canDeactivate guard logic there is a built-in method just called like that. It is named beforeClosed. It returns an Observable that you can subscribe to which will notify you when the dialog started closing. Inside this method you can execute your function.
-2- Angular router has an API called events. It essentially helps you track the status of the router. It can detect when the router starts the navigation, ends the navigation, cancels the navigation, resolved the navigation, etc...
For a complete list of API advanced events. Check this documentation link
Cool, with this API you can choose the right event that suits you and put you function inside the condition such as :
checkRouterEventToFireCustomFunctionLogic(){
this.router.events.subscribe((routerEvent) => {
if(routerEvent instanceof NavigationStart) {
// execute my custom function OR
// just console.log("Hello World")
}
});
}
PS: beforeunload event is not really good especially when it comes to Web Vitals bfcache
I am trying to reset the 'selected' item after the user makes a selection. This is calling to the Vue function below, tS(). The first call $('#sel1').prop('selectedIndex',0); only works if I execute it in the console however the second one $('#current-schedule-holder').text('Current : '+scheduleToTime(msg)); works fine, meaning that jquery is working. Also my console.log($('#sel1')) shows that the element from the first call, the one that is not working, is already in the DOM when the function executes.
tS: function(msg){
$('#sel1').prop('selectedIndex',0);
console.log($('#sel1'))
$('#current-schedule-holder').text('Current : '+scheduleToTime(msg));
toggleScheduler(this.query, msg);
},
I wouldn't recommend mixing jQuery and Vue. Vue uses a virtual DOM while jQuery does not. What's probably happening is that when the tS function runs, it updates the DOM correctly, but then Vue overrides those changes based on the info it has in its virtual DOM.
See https://vuejsdevelopers.com/2017/05/20/vue-js-safely-jquery-plugin/ for instructions on how to get jQuery to work with Vue. You're going to have to wrap your jQuery functions in a Vue component which is fine if your needing some complicated functionality in a jQuery plugin, but for basic DOM manipulation like this, it's much easier to stick to doing this inside of Vue.
I've found a tool for table management and I love it. The only problem is that it needs initializing as shown below, which means that it only gets called once - when the page's been loaded.
mounted: () => {
$(document).ready(function () {
$("table").DataTable();
}
}
I've put the code in the mounted section and I also tried to use created. For some reason (probably rendering order), I have to keep it in ready method - otherwise it doesn't come up.
This poses two problems for me. Firstly, I'm reusing the same component as a matrix view in multiple components (it's dynamically set up based on the store). Secondly, when I navigate from the page and then go back, it doesn't reinitialize.
How should I make the code inside ready method to run each time the component gets in the view?
I've googled a bit but it's a not so common issue and I'm out of ammo. The best hit I got was the life cycle of the component where I couldn't see anything ground breaking. I also found that the data table instance needs to be destroyed but that only helps if I get to invoke the stuff, which seems not to happen.
I believe you just need to do following:
mounted () {
$("table").DataTable();
}
as $(document).ready detects that the document is ready, but in vue case, mounted is called after the instance has just been mounted where el is replaced by the newly created vm.$el, which should be equivalent of document.ready.
I have also checked in vue 2.x.x that mounted gets called if you navigate from the page and then go back.
If this code is dependent on data being loaded and re-rendering of component, you can use updated instead of mounted which is called after a data change causes the virtual DOM to be re-rendered and patched.
updated () {
$("table").DataTable();
}
Ok so i have a component i made up with a form. I would like to alert the user that he has unsaved data (if he has) when the user clicks on another link.
Now if i would not be tied to ember i would put a flag on a change event and add a window unload listener to show the actual message, However,
Since im not really leaving the window this is not getting called.
Is there any Ember event i can attach a handler to? like a change route intent event of some kind
Im interesting in knowing which is the correct event for the leaving route action, not in the something change logic.
ive tried this so far on the didInsertElement( ) method
Ember.$("body").on('unload',()=> alert('it works'));
Ember.$("window").on('unload',()=> alert('it works'));
Ember.$("body").on('unload','body'()=> alert('it works'));
any ideas?
Have you had a look at the willTransition method on your route? That will be the place to do it. Have a read of this guide to preventing and retrying transitions, as well as the willTransition method's documentation. Hope that helps!
You can catch transition event on route. It's meant to be used for this use case.
There is also action when component is being destroyed but that is meant for teardown.
In a very common scenario, I have an HTML page with an "Add" button that opens a modal dialog (through Facebox) and asks the user to select an item from the list that appears in it.
The modal dialog gets its HTML snippet from the server asynchronously. I want this snippet to be reusable in many parts of my application so it shouldn't assume that I am using Facebox to load it. The only thing it should do is to trigger the item-selected event whenever the user selects an item in it. But since the snippet is loaded asynchronously, I cannot use $(document).ready. That is, I cannot trigger the event like this:
$(document).ready(function() {
$(".item").click(function() {
$(".items-modal-dialog").trigger("item-selected", this);
});
});
Also, I don't really like using the items-modal-dialog class to identify the enclosing DOM element.
I came up with some solutions to this, and I would like to know if there is some superior pattern that I am missing, because I think this is a very common problem.
Put the script after all the HTML so I am sure that the snippet DOM is loaded (I think this is a bad practice)
Creating a JavaScript function that loads the snippet with Facebox and then binds the events. This way I assume that I am using Facebox and also have to create a function for every type of modal dialog that I create. The only positive side I see in this is that I can create the items-modal-dialog DIV programmatically so I don't have to use a class to identify it.
Using jQuery live to bind the events.
Using an iframe and $(document).ready.
Any suggestions would be greatly appreciated.
Using jQuery's live or delegate function would be the best solution in my opinion.