Vue-js I have been trying to use a simple javascript onload event that moves the page down to a particular row in a table. Those rows are separate components, each with its own id. Something like this:
mounted: function () {
this.getExcList(); // load data for exceptions from server
this.$nextTick(() => {
location.hash = "exc_"+this.excn0;
});
},
It works fine if you run it once the page is loaded, but apparently the mounted event is just too early. In this case, the data for loading (this.getExcList) only arrives then.
Is there a simple answer to this question: How do you run an onload event in Vue-js, that only happens after the render is complete?
There are so many questions online about things like this. Surely there is a standard answer? Thanks!
Update, based on comments:
Trying this
async created () { // backend to get data on exceptions
await this.getExcList(this.archiveyear); // load data for exceptions
},
mounted: function () {
this.$nextTick(() => {
location.hash = "exc_"+this.excn0;
});
},
It still doesn't jump to the location.
Related
I came across the following code:
let timeoutHandler;
clearTimeout(timeoutHandler);
timeoutHandler = setTimeout(() => {...});
This is an overly simplification since the original code is contained in a Vue application as follow:
public handleMultiSelectInput(value): void {
if (value === "") {
return;
}
clearTimeout(this.inputTimeoutHandler);
this.inputTimeoutHandler = setTimeout(() => {
axios.get(`${this.endpoint}?filter[${this.filterName}]=${value}`)
.then(response => {
console.log(response);
})
}, 400);
}
Does this mean this is some kind of cheap-ass debounce function?
Could someone explain what this exactly means.
Yes, it is a debounce function, which is when we wait for some amount of time to pass after the last event before we actually run some function.
There are actually many different scenarios where we might want to debounce some event inside of a web application.
The one you posted above seems to handle a text input. So it's debouncing the input, meaning that instead of fetching that endpoint as soon as the user starts to enter some character into the input, it's going to wait until the user stops entering anything in that input. It appears it's going to wait 400 milliseconds and then execute the network request.
The code you posted is kind of hard to read and understand, but yes, that is the idea of it.
I would have extracted out the network request like so:
const fetchData = async searchTerm => {
const response = await axios.get(`${this.endpoint}?filter[${this.filterName}]=${value}`);
console.log(response.data);
}
let timeoutHandler;
const onInput = event => {
if (timeoutHandler) {
clearTimeout(timeoutHandler);
}
timeoutHandler = setTimeout(() => {
fetchData(event.target.value);
}, 400);
}
Granted I am just using vanilla JS and the above is inside a Vuejs application and I am not familiar with the API the user is reaching out to. Also, even what I offer above could be made a lot clearer by hiding some of its logic.
Fullcalendar version 3 used to have a callback function that would fire once all events have rendered. I would use this:
eventAfterAllRender: function( view ) {
load_call_list();
}
load_call_list is a function I made to count certain events based on their status. It also queries my database for other information.
Using fullcalendar 4, once the calendar has fully loaded and all the events have rendered, I want to call that function. Here's how my calendar is initialized now...
<script>
document.addEventListener('DOMContentLoaded', function() {
var calendar_full = document.getElementById('calendar_full');
var calendar = new FullCalendar.Calendar(calendar_full, {
height: 700,
selectMirror: true,
events: {
url: 'ajax_get_json.php?what=location_appointments'
},
....
I suppose my lack of understanding about javascript is limiting me in understanding where I can catch when the calendar events have all fully loaded.
I thought about using eventrender, but I don't want the load_call_list to be fired every time as my database is queried with that function too.
I tried using jquery $(document).ready(function(){}) but that fires before the events have been rendered.
Any advice on how to accomplish this?
Ok, so how about this? I can use the loading function. When the calendar is done loading, I can call my load_call_list function. I am using a bool variable to stop it from firing everytime the calendar loads without a page refresh (like when cycling through months or weeks, for instance).
When the page first loads, I have a var called initial_load = true. When the calendar has finished 'loading', if this is true, then I'll call my function and set my initial_load to false so it won't just fire off as I explained before.
<script>
//set initial_load so when the calendar is done loading, it'll get call list info
var initial_load = true;
document.addEventListener('DOMContentLoaded', function() {
var calendar1 = document.getElementById('calendar_mini');
var calendar_mini = new FullCalendar.Calendar(calendar1, {
....
....
loading: function(bool) {
if (bool) {
$('.loader').show();
$('#show_cancelled_appts').hide();
$('#show_rescheduled_appts').hide();
$('#print_calendar').hide();
} else {
$('.loader').hide();
$('#show_cancelled_appts').show();
$('#show_rescheduled_appts').show();
$('#print_calendar').show();
//once it's done loading, load call list with current date stuff; set
initial_load = false so it doesn't keep loading call list when calendar changes while cycling months/weeks/etc
var today = moment().format('YYYY-MM-DD');
if (initial_load) {
load_call_list(today);
initial_load = false;
}
}
},
It does actually work! Thoughts on that? Is this okay programming? I don't see any downside as of now.
Earlier I ran into the issue of Alexa not changing the state back to the blank state, and found out that there is a bug in doing that. To avoid this issue altogether, I decided that I wanted to force my skill to always begin with START_MODE.
I used this as my reference, where they set the state of the skill by doing alexa.state = constants.states.START before alexa.execute() at Line 55. However, when I do the same in my code, it does not work.
Below is what my skill currently looks like:
exports.newSessionHandler = {
LaunchRequest () {
this.hander.state = states.START;
// Do something
}
};
exports.stateHandler = Alexa.CreateStateHandler(states.START, {
LaunchRequest () {
this.emit("LaunchRequest");
},
IntentA () {
// Do something
},
Unhandled () {
// Do something
}
});
I'm using Bespoken-tools to test this skill with Mocha, and when I directly feed IntentA like so:
alexa.intended("IntentA", {}, function (err, p) { /*...*/ })
The test complains, Error: No 'Unhandled' function defined for event: Unhandled. From what I gather, this can only mean that the skill, at launch, is in the blank state (because I have not defined any Unhandled for that state), which must mean that alexa.state isn't really a thing. But then that makes me wonder how they made it work in the example code above.
I guess a workaround to this would be to create an alias for every intent that I expect to have in the START_MODE, by doing:
IntentA () {
this.handler.state = states.START;
this.emitWithState("IntentA");
}
But I want to know if there is a way to force my skill to start in a specific state because that looks like a much, much better solution in my eyes.
The problem is that when you get a LaunchRequest, there is no state, as you discovered. If you look at the official Alexa examples, you will see that they solve this by doing what you said, making an 'alias' intent for all of their intents and just using them to change the state and then call themselves using 'emitWithState'.
This is likely the best way to handle it, as it gives you the most control over what state and intent is called.
Another option, assuming you want EVERY new session to start with the same state, is to leverage the 'NewSession' event. this event is triggered before a launch request, and all new sessions are funneled through it. your code will look somewhat like this:
NewSession () {
if(this.event.request.type === Events.LAUNCH_REQUEST) {
this.emit('LaunchRequest');
} else if (this.event.request.type === "IntentRequest") {
this.handler.state = states.START;
this.emitWithState(this.event.request.intent.name);
}
};
A full example of this can be seen here (check out the Handlers.js file): https://github.com/alexa/skill-sample-node-device-address-api/tree/master/src
I would also recommend reading through this section on the Alexa GitHub: https://github.com/alexa/alexa-skills-kit-sdk-for-nodejs#making-skill-state-management-simpler
EDIT:
I took a second look at the reference you provided, and it looks like they are setting the state outside of an alexa handler. So, assuming you wanted to mimic what they are doing, you would not set the state in your Intent handler, but rather the Lambda handler itself (where you create the alexa object).
exports.handler = function (event, context, callback) {
var alexa = Alexa.handler(event, context);
alexa.appId = appId;
alexa.registerHandlers(
handlers,
stateHandlers,
);
alexa.state = START_MODE;
alexa.execute();
};
I'm attempting to create a modular sign in script for some webpages I'm developing. In short, I load the script on the main page, fire the main signIn function from a button press, and an overlay div is created on the main page which is managed by the external signIn.js. The external js sets some sessionStorage variables that will be utilized in the main page.
The hope for modularity would be to have signIn.js handle the authentication from the database and have the main page do with the process of signing in as needed (in this specific instance, it gives users access to their projects). Ideally, the sign in will not force a refresh of the main page due to other project goals.
The problem I'm encountering, is how do I notify the main page that the user has signed in without destroying any sense of modularity?
On top of other efforts, the most hopeful was attempting to create a custom event on the main page's document using $(document).on('userSignedIn', function() {...}); but signIn.js apparently cannot trigger this event.
Any suggestions for how to accomplish this or am I just going about this entirely wrong?
EDIT:
So, this was definitely a scope related issue I was experiencing. To flesh out the process, if anyone finds it relevant, signIn.js adds an overlay div to mainPage.html. $("#signInContainerDiv").load("signIn.html") is used to load the sign in form into the page. It turns out, when I was trying to reference $(document), it was using signIn.html's document, and not mainPage.html's. Upon that realization, I just created a div (signInNotify) on the mainPage that I bind the event to ($("#signInNotify").on("userSignedIn", function() {...});) and trigger it in signIn.js.
My own inexperience has conquered me, yet again.
jQuery can help you out when it comes to this. Here's an example from the main page for trigger
$( "#foo" ).on( "custom", function( event, param1, param2 ) {
alert( param1 + "\n" + param2 );
});
$( "#foo").trigger( "custom", [ "Custom", "Event" ] );
jQuery Page Reference
Another solution is to use some library like amplify.js, it has publish/subscribe functionality which can be useful for implementing the "observer pattern". You could also implement your own library for that, the code could be something like this:
// the implementation
function Notify () {
this.listeners = {};
}
Notify.prototype.subscribe = function (event, callback, context) {
this.listeners[event] = this.listeners[event] || [];
this.listeners[event].push({ callback: callback, context: context || null});
};
Notify.prototype.publish = function (event/*, args...*/) {
var args = Array.prototype.slice.call(arguments, 1);
(this.listeners[event] || []).forEach(function (x) {
x.callback.apply(x.callback.context, args);
});
};
// usage:
// an instance, or can be implemented as a singleton
var global_events = new Notify();
// wherever you want to be notified of login events
global_events.subscribe('login_success', function () {
// do something with the arguments
}, myContext/*optional*/);
// after success login
global_events.publish('login_success', user_credentials, other_data);
// and all subscribers (listeners) will be called after this
I have used that code for similar purposes and also used amplifyjs a couple times, you can read more about Amplify Pub/Sub.
i am trying to get the first ready state of the DOM. the second, third, etc is not interesting me, but the first one. is there any trick to get the first ready state of DOM?
$(document).ready(function() {
// is it the first ready state?
});
There are 4 readyState possible values:
uninitialized - Has not started loading yet
loading - Is loading
interactive - Has loaded enough and the user can interact with it
complete - Fully loaded
To see it's value use this code:
document.onreadystatechange = function () {
if (document.readyState === YourChoice) {
// ...
}
}
I could not catch the uninitialized readyState. (but why should I need it?)
If you need a listener for complete load of the DOM, use:
document.addEventListener('DOMContentLoaded', YourListener);
or
document.addEventListener('load', YourListener);
or even
window.onload = YourListener;
for jquery:
$(document).on("DOMContentLoaded", function() { });
or
$(document).on("load", function() { });
or
$(window).on("load", function() { });
Ah, you're using jQuery. Have a look at the docs: There is only one ready event! I will never fire multiple times. Internally, this is even handled with a Promise, so it cannot fire multiple times.