Vue Search Inputs fires Fetch-Method every single keypressed [duplicate] - javascript

background
I have a number of dropdowns on a page. If you change the first one, the rest of the dropdowns are updated according to what you've selected.
In our case, we deal with fund data. So the first dropdown is "All Fund Types". You select "Hedge Funds", and the next dropdown is filtered by options that only apply to Hedge Funds.
The client is now asking me to put a text field into the mix, which when the user starts typing, will effect those results.
So if they type "USD", the second dropdown will only contain options that have funds with "USD" in the name.
problem
The specific problem that I'm having is that with the code I'm using:
$('#Search').keypress(function () {
// trigger the updating process
});
It's triggering the search for each key press. So when I type "USD" I'm getting 3 requests immediately - one for "U", one for "US" and one for "USD".
I've tried setting a timeout with this:
$('#Search').keypress(function () {
// I figure 2 seconds is enough to type something meaningful
setTimeout(getFilteredResultCount(), 2000);
});
but all that does is wait 2 seconds before doing what I've described.
I'm sure this problem has been solved before. Could somebody suggest how to solve this issue?

The way I have done this before is to set a timeout, but clear the existing timeout each time a new key is pressed. That way you should only get the request being sent when the user has stopped typing.
var timeoutId = 0;
$('#Search').keypress(function () {
clearTimeout(timeoutId); // doesn't matter if it's 0
timeoutId = setTimeout(getFilteredResultCount, 500);
// Note: when passing a function to setTimeout, just pass the function name.
// If you call the function, like: getFilteredResultCount(), it will execute immediately.
});
(I'd go for about 500ms timeout.)

Related

In Angular 5 , How should group number of click events and emit once only when user stop clicking

I have a angular application (Angular5 + ngrx5).
In my app, users can click/select are number of options/items (just simple divs). such as option1, option2, option3 .... Multiple options can be selected.
Currently, users select one option, we trigger a service call to save a selected option. We do currency version number checks, so users have to wait the service call response (with latest version number) back before select the next option. It is not providing good UX.
Therefore, I prefer that users can keep clicking a number of options, once users stop clicking we make a single service call with multiple selections .
My question is that how to group number of click events and emit once only when user stop clicking? any examples or any suggestions?
I know rxjs debounce can drop emitted values.clicks, but I do not want to drop them I want to aggregate them in order to make a single service call.
thank you
The rxjs way of achieving this.
const ajax=Rx.Observable.timer(4000).mapTo('ajaxcall')
Rx.Observable
.fromEvent(click, 'click')
.scan((acc,curr)=> ([curr,...acc]) ,[])
.debounceTime(500)
.mergeMap(arrClick=>{
console.log(arrClick)
return ajax
}).subscribe()
https://jsfiddle.net/7kbg4q2e/453/
You can handle this with a setTimeout.
On each click, you can build an array with your values.
Then, set a timer to send to the API. If it receives another request while waiting for that timer, cancel it, and start a new one.
handleClick(value) {
this.values.push(value);
// If there's a timer going, cancel it
if (this.timer != null) {
clearTimeout(this.timer);
}
// Start a new one
this.timer = setTimeout(() => {
// Send to your API
// Make sure to clear your this.values array after the API call has returned
}, 5000);
}
In the example above, it will only send the request after 5 seconds without a click event

select drop downs and promises - briefly empty selects

I have two filters where the first influences the second before querying data to a remote server.
I have a select, which has its options in $scope.locationCodes. This select relies on another dropdown (customer). Once the customer is selected, I have the ID, and then pass that to the returned promise in the first function.
The issue 1:
As soon as I select a customer, if I really quickly go to select a location code (in codes dropdown), the options will be blank. If i blur and then try to select again, the options will show up, indicating there was a bit of a delay. What's the best way to handle this delay in the array being populated?
The code:
HTML:
<select data-ng-options="locationCode in locationCodes"></select>
JS:
$scope.getShipAbbleLocations = function (terminalId) {
var customerId = $scope.customer.id;
return Service.getShipAbbleLocations(customerId, terminalId).then(function (data) {
getLocationCodes(data);
_.defer(function () {
$scope.$apply();
})
});
};
function getLocationCodes(data) {
for (var i = 0; i < data.locationCodes.length; i++) {
$scope.locationCodes.push(["(" + data.locationCodes[i].shipThruLocationCode + ")", data.locationCodes[i].shipThruLocationId]);
}
$scope.$apply();
}
The issue 2:
The kicker is that the codes dropdown should be disabled until a customer is selected. I have been relying on a timeout in my controller to handle the disable by setting a delay for the 'enable' which allows time for the array to be populated. This works, but the issue re appears once you change customers and don't have to worry about the initial disable case.
I am wondering if there is a better way than timeouts (that hopefully shows a better understanding of angularjs/promises) to handle this delay/asynchronicity.
The best way is to show LOADER and disable the UI until your AJAX call is complete.
It is always a better practice to implement loader for async ajax calls.
You can implement the loader code in interceptors, so that for every request the loader will show up and you dont have to implement for every AJAX call, since its in the interceptor.

Alternatives to using a submit button with jQuery

Currently I am using a ajax post back to pass data to a my controllers, wherein I do my magic from there. The problem I am having right now is that we have removed a submit button and instead attached a handler using .keyup(), on a smaller database this works great! However when moving it to a larger database, as you might of guessed, it causes all sorts of issues, from delayed responses to crashes etc. So it won't work. My question to stack overflow would but this: What's a user-friendly version to submit a form?
Since the front end user could potentially be searching for single character values (e.g 6 as in userid 6) I can't limit it to a minimum character submission. We don't want a delay timer as that could back fire in a couple different ways. so basically I've ruled out .delay(), .blur(), and .keyup().
If your requirement is to not use a submit button but rather process the input as the user types then I have used solutions like this in the past.
First define a function to manage the delay, something like this:
var inputDelay = (function () {
var timer = 0;
return function (callback, ms) {
clearTimeout(timer);
timer = setTimeout(callback, ms);
};
})();
Then for your actual ajax-call do something like this in your onkeyup event:
inputDelay(function () {
//AJAX-call goes here
}, 400)
Please note that this is not a universal solution for handling the order of responses from the server though. You might very well get several AJAX requests sent to the server and this code does nothing to make sure you only handle the latest call.
The best way to handle your situation would be to use a form, complete with a submit button. You would then add your event listener to the submit event of the form, cancel the post-back, and then do your processing. This would handle both the user clicking the submit button as well as pressing the enter key from inside the form.
I had the same issue as you.. What I did is the following:
I used on keyup.. and I fire the search if the user stayed still for .. say 300 millisecond or 500 millisecond..
While the user is typing I clear and reset the setTimeout().. so if the user stayed still for the timeout time the search will fire.
Additionally you can take the reference of the xHR object and cancel it if another request was to take place..
Do I understand your question correctly? if you need a written example I can write you a fiddle.

Continually check for an Oracle record at page load

I basically have a page that when loads, reads an Oracle SQL table for a specific record id that may not currently exist at the point as it may take up to a minute to insert this specific record into the table.
Based on this, I need a means of showing a "Loading Image" while it waits for the record to exist, so has to wait. Once it does, I want to remove the loading image and present the user with the record details. I am using Oracle Application Express 4.2 for this.
My question is not so much the loading/hiding of the image but how to continually check for the record within the Oracle table, during page load.
Either I receive the record successfully and then hide the image or say after 1 minute, I dismiss the checking of the record and present the user with a message indicating that no record was found.
Sorry for my english. I will try help you.
Make your "Loading image" always visible on the page. There is no need to show it on load, you only need to hide it at proper moment.
Add Application Process to your application. Name it for example "GET_MY_ROW". Process must check your event, and return some flag, for example 1 or 0.
Example:
declare
l_cnt number;
begin
select count(*)
into l_cnt
from table1 t
where id = 12345;
if l_cnt > 0 then
htp.p(1);
else
htp.p(0);
end if;
end;
3.3 Add javascript code as page load event (for example by Dynamic Actions):
Javascript code:
var myInterval = setInteral(function {
var get = new htmldb_Get(null,$v('pFlowId'),'APPLICATION_PROCESS=GET_MY_ROW',$v('pFlowStepId'));
get.GetAsync(function(pRequest) {
if (pRequest.readyState == 4) {
if (pRequest.responseText == 1) {
alert('Record loaded successfully');
// add function call, hiding your "Loading image" here
clearInterval(myInterval);
}
};
});
get = null;
}, 5000); //check every 5 seconds
setTimeout(function() {
alert('Sorry, no record was found. Try again later.');
clearInterval(myInterval);
}, 60000); // fail after 1 minute
Since NoGotnu already answered, I'll put this here:
Is there any reason for the procedure to be called through a job? Is it the only way to create the required record? Is the job called anywhere else? Why not call the procedure directly when the required page has been submitted and show the loading icon there? When it finishes, the user knows it has finished. That would involve a lot less fiddling around as you can make apex show a processing graphic on page submit. You could then just inform the user on the other page that the process has not been ran yet and they'd have to do that first.
Secondly, while NoGotnu's answer will work, I'd like to point out that in apex 4.2 you should use the apex.server namespace instead of the never documented htmldb_Get construction. apex.server.process is a clean implementation of the jQuery ajax setup.
NoGotnu's code translated:
apex.server.process( "GET_MY_ROW"
, null
, { dataType: text
, success: function(pData){
if (pData == 1) {
clearInterval(myInterval);
alert('Record loaded successfully');
};
}
}
);
The call doesn't really need to be async though, but ok.
Another option would be to implement a "long poll" instead of firing the ajax event every 5 seconds. A long poll will just initiate a call to the server and wait for a response. As long as the server is busy, the client will wait. To achieve this you could use dbms_alert, as suggested in Waiting for a submitted job to finish in Oracle PL/SQL?
You'd signal an alert in the plsql code of the job, and in the ondemand process code register an interest in the alert and use waitone/any with a 60 second timeout. Presto long poll.

How do I set up a timer to prevent overlapping ajax calls?

I have a page where search resuts are shown both in a grid and on a map (using KML generated on the fly, overlaid on an embedded Google map). I've wired this up to work as the user types; here's the skeleton of my code, which works:
$(function() {
// Wire up search textbox
$('input.Search').bind("keyup", update);
});
update = function(e) {
// Get text from search box
// Pass to web method and bind to concessions grid
$.ajax({
...
success: function(msg) {
displayResults(msg, filterParams);
},
});
}
displayResults = function(msg, filterParams) {
// Databind results grid using jTemplates
// Show results on map: Pass parameters to KML generator and overlay on map
}
Depending on the search, there may be hundreds of results; and so the work that happens in displayResults is processor-intensive both on the server (querying the database, building and simplifying the KML on the fly) and on the client (databinding the results grid, overlaying big KML files on the map).
I like the immediacy of getting progressively narrower results as I type, but I'd like to minimize the number of times this refreshes. What's the simplest way to introduce an N-second delay after the user stops typing, before running the update function?
Instead of calling update() directly, call a wrapper that checks to see if there are any pending delayed updates:
$('input.Search').bind("keyup", delayedUpdate);
function delayedUpdate() {
if (updatePending) {
clearTimeout(updatePending);
}
updatePending = setTimeout(update, 250);
}
function update() {
updatePending = false;
//$.ajax(...
}
You should also probably add:
$('input.Search').bind("blur", update);
This will do an immediate update when the user leaves the field. But make sure you also add handling for the case where the user leaves the field while there's a pending delayed update (cancel the delayed update first).
As a first approach, what about something like :
$('input.Search').bind("keyup", function() { setTimeout(update, 5) } );
(not sure about the exact setTimeout syntax).
You can also keep a variable to track whether the timeout has already been scheduled or not.
You can use Window.SetTimeOut(YourRefreshMethod) , when the YourRefereshMethod gets called, it will check number of characters being typed so far , and compare it to the some counter, the counter will starts with 0 value, so the initial call will do nothing other than updating the counter with the current characters typed count, the second time your method get called , it will check the number of characters typed, if it matches the previous number recorded by the counter , then it means the user didn't type anything new and you can fire your Refresh method, otherwise you will update the counter value

Categories

Resources