Okay folks,
I apologize if this has been asked before, I searched all of yesterday for a solution and came up empty handed. Perhaps I am searching the incorrect terms... but I digress. My issue is I have a PDF document that is actually ten documents in one, a series of letters and forms that require about a dozen redundant fields over all 10 documents.
TopmostSubform.ControlSheetPG1.RCN::initialize - (JavaScript, client)
RCN.rawValue = app.response("Enter the Report Control Number (RCN)");
if (RCN.rawValue < "" || RCN.rawValue == RCN.rawValue) {
TopmostSubform.ControlSheetPG1.RCN::exit - (JavaScript, client)
RCN.rawValue = RCN.rawValue;
As you can see, I have the user enter the information upon initialization, and upon exit I have it update the global data for RCN. My issue is the "if" statement. I need to have the javascript check to see if the field is occupied before it creates the popup box asking for the info. So if the field is occupied with data it skips it and leaves the data alone and goes onto the next field and repeats until all fields have been updated, or checked. I hope all of this makes sense.
Related
I am trying to prevent duplicate items from being entered in an Interactive Grid in Oracle Apex 20.2. I do get a unique constraint error when this happens, but this is for a barcode scanning stock control app and the unique constraint error only happens when saving after scanning a room with lots of objects. It is then very difficult to find the duplicate field. You also cannot use sort, since that wants to refresh the page and looses all your scanned items. I cannot presort because I want the last scanned item on top.
I was able to add Javascript on page load that creates an array with all the barcodes. I then check this array when scanning and do not add new Interactive Grid rows when a duplicate barcode is going to be added to the array.
In addition to this I need to add the same for when an Interactive Grid row is manually entered. For this I wanted to add a Javascript dynamic action on the barcode column in the Interactive Grid, in order to once again check the global array for uniqueness. However I have several issues: I cannot figure out how the get the entered barcode value in the change dynamic action Javascript, sometimes it shows the previous changed value (might be this bug although I am in 20.2) and the Change event also seems to fire twice when hitting enter after entering a value (once for the new row (this time my code works unlike when hitting Tab) and once for the next row below). The last one seems bad, since then it will try to check existing values (the next row) and give errors that should not happen; however I do not see a more appropriate event like On Row Submit. Not sure if there is a way to check whether the value changed on the Change event.
The code I currently have I got from here. I am assuming this means Oracle Apex does not have a standard way of getting an Interactive Grid column value in a Javascript dynamic action. Not sure if this has changed in 20.2 or 21. The code I have is:
console.log($(this.triggeringElement));
var grid = apex.region('LINES').widget().interactiveGrid('getViews', 'grid');
var model = grid.model;
var selectedRow = grid.view$.grid('getSelection');
var id = $(selectedRow[0][0]).data('id');
var record = model.getRecord(id);
let bcode = model.getValue(record, 'BARCODE');
console.log(id);
console.log(record);
console.log($(selectedRow[0][0]));
console.log(bcode);
if(barcodes.includes(bcode)) {
apex.message.showErrors([{
type: "error",
location: "page",
message: "The entered barcode is already in the list.",
unsafe: false
}]);
}
When I console.log(record) I can see values that I enter into the barcode column, but I do not know how to walk the object tree in order to retrieve the value out of the record. I do not understand the object it shows me in the console log. It does not seem to correlate with the dot access traversals that others are doing in the above code. I can see the record array at the top, but for that the barcode column shows the previous value; below that it does however show the newly entered value as the third (2) index, but I do not know how to write Javascript to access that.
If I can access the previous and new value from the record object I could check for changes and also compare the new value against the global array. How do I access these values in the record object or is there a better way of achieving my goal? bcode prints the previous value, so I guess I already have that if that is not a bug.
I've recently upgraded the ngx-bootstrap from 1.8.1 to 3.0.1 . After the upgrade type ahead doesn't seem to work as expected. I'm using this example :
https://valor-software.com/ngx-bootstrap/#/typeahead#async-data
with [typeaheadMinLength]="3"
Now , if I search, lets say "abcdef" then it starts searching after 3 characters have been typed that is abc and then abcd, abcde, abcdef and so on which is fine.
But now if I delete everything in input textbox using backspace in one go, that is if I make abcdef to empty by pressing backspace in one go, then once input is empty, it shows drop down values again which correspond to min length which is abc.
Ideally it should clear drop down values but looks like when you delete it very fast using backspace, it retains the values corresponding to min length token string.
It is more visible when data is fetched from a service and the data is huge, so it takes some time to load and clear.
Delay in service response can be emulated using typeaheadWaitMs and this issue can be replicated using this example : https://valor-software.com/ngx-bootstrap/#/typeahead#delay
https://github.com/valor-software/ngx-bootstrap/issues/4412
Could someone please help on this?
You have to put a check if search field is empty then clear the list holding values. When pressing backspace what happens is that when search length reaches threshold value i.e abc it fetches the result and stores it after that no operation is performed hence the search results for abc are persisted. Add (keyup)="onKey($event.target.value)" if value is empty clear the list holding your dropdown data.
As a workaround, I removed [typeaheadMinLength]="3" and instead checked the length on server. If length of prefix token is less than 3 , server doesn't do anything and instead returns empty array. This isn't the optimal solution ofcourse because even for length less than 3, requests will go to the server.
Although, I didn't feel any visible performance impact but still it could be better if done on UI rather than server.
EDIT This question is almost a duplicate of this question from 2010, except that I'm not using transactions, so none of the answers make sense.
EDIT I am not asking how to reset the primary key. I am asking why the primary key is not auto-incrementing by consecutive numbers.
I'm using xmlhttprequest to capture as-you-type information and store it in my Mysql database.
HTML
<input type="text" name="example" onKeyUp="saveData(this)">
JAVASCRIPT
function saveData(a){
var z;
var d=new FormData();
d.append('data',a.value);
if(window.XMLHttpRequest){z=new XMLHttpRequest();}else{z=new ActiveXObject("Microsoft.XMLHTTP");}
z.onreadystatechange=function(){if(z.readyState==4&&z.status==200){if(z.responseText=='false'){alert(z.responseText);}}}
z.open("POST", '/scripts/save_data.php');
z.send(d);
}
PHP
For testing purposes I'm hard-coding the uid user id.
<?php
$stmt=$pdo->prepare("INSERT INTO `user_data` (`uid`, `data`) VALUES (:myuid,:mydata) ON DUPLICATE KEY UPDATE `data`=values(`data`)");
$stmt->bindValue('myuid',1,PDO::PARAM_INT);
$stmt->bindParam('mydata',$_POST['data'],PDO::PARAM_STR);
$stmt->execute();
My MySQL table has...
id, primary INT(10) unsigned auto-increment
uid, INT(10) unsigned
data, VARCHAR(24)
Everything works as expected, but I'm not seeing the values of id increment sequentially as I would expect (1, 2, 3, etc.). It's jumping (1, 20, etc.) as if lines have been created, then dropped, to form the final line. Can anyone explain this behavior? Need I worry about it?
Since you clarified, that your INSERT is creating duplicate entries with the uid, this is the issue:
MySQL reserves the next auto increment value and issues an end table lock before even trying to insert. The insert then fails and the UPDATE part happens. But since the auto increment already was moved up and another process could have picked the next number, it will not be decreased again. So you get a hole.
This of course, creates only one "hole" at a time, but since you are doing this on keyup it happens very often. And because of the hard coded uid it happens also for every concurrent request.
Ok, so I have a kind of weird problem that I need ideas on how to solve.
I have a vb.net web application that points to a sql database. There's a table with a primary key that is an auto-incremented integer.
When a user adds an object to this table, it doesn't currently check to see if the "First Name" and "Last Name" already exist in one of the datarows. The desired addition to the functionality is as follows:
1)When the user submits the form, check the table to see if such a record already exists.
1.1)If the record doesn't exist proceed with the insert.
2)If that record does exist, display a warning to the user that such a record exists
2.1)The warning should have two buttons, "Continue" and "Cancel"
2.1.1)If the user clicks "Continue" go ahead and add the duplicate record
2.1.2)If the user clicks "Cancel" stop the insert.
I'm still relatively new to web development (a little over a year of experience). I am looking for the "correct" way to do this. The aspect of this task that is making it hard for me is that I have to run the query, and then possibly display and alert (javascript probably). I'm not sure how to display an alert in the middle of the server side validation.
Any ideas or comments are appreciated!
Thanks!
If you wouldn't allow insertion of duplicates, you could just create unique index in your database. However, what you can do now is to get the count of records in the database, where firstname and lastname equals to inserted.
In case of normal SQL it would look like
SELECT COUNT(recordID) WHERE firstName = #firstName AND lastName = #lastName;
Or it could look even easier with Entity Framework. Anyway, your question was about "displaying alert in the middle of server side validation". Think about it differently. Think about it as about two checks.
Add another control to your input form, an invisible checkbox near the Submit button. It should contain the expression about user's agreement to insert duplicate record.
Once you detect, that record is duplicate, interrupt the validation, and make checkbox visible, but Submit button - disabled. When user checks the checkbox, Submit button should become visible again.
Now, since you are going through the same validation again, you have to take your checkbox into equation - if it is visible and checked, you don't have to check for record duplication anymore, and just submit the record. If you need to re-use that input form, don't forget to uncheck the checkbox and make it invisible once again.
What you want to do here is add a confirm parameter or something like that to your method, like this:
' This is just pseudocode; I'm guessing you can translate it to
' whatever web framework you're using
Sub InsertRecord(ByVal name() As String, Optional ByVal confirm As Boolean = False)
If DuplicateRecord(name) And Not confirm
' Here's where you would render the page with a confirmation dialog
RenderViewToRequestConfirmation()
Return
End
DoInsertRecord(name)
RenderViewAfterRecordInserted()
End
Then under normal circumstances, from your front end you would submit a request that would call this method without the confirm parameter. In the case of duplicate records, the server would render a response with a dialog requesting confirmation. If the user clicked 'Yes' (or whatever), then the front end would send the same request but this time with the necessary request params to set confirm to True.
In terms of web requests, this process might look like:
| Request Data | Response |
|------------------------------------------|------------------------|
| { "name": "M Webster" } | Page w/ confirm dialog |
| { "name": "M Webster", "confirm": true } | Success page |
The route that I went is a little confusing... even now that I have it working, but i'll explain it here in case it makes sense to someone else who can better explain it later.
I wrote a function in the code behind that calls the function that checks the database for a duplicate record, but I added these two lines of code above the function declaration:
<System.Web.Services.WebMethod()>
<System.Web.Script.Services.ScriptMethod()>
Then, I wrote a JavaScript function that grabs the value from the Textbox and passes the value to that function in the code behind. This is made possible by those two lines above the function declaration in the code behind and by using the PageMethods object. The actual call from the JavaScript would look like this:
PageMethods.FunctionName(parameter, function(returnValueFromOtherFunction){
....function stuff
});
Then I assigned the JavaScript function to the onBlur event in the Textbox.
Thanks for the help guys, but I think this is the best way to solve my problem.
I'm new here so please go easy on me. This is somewhat of a confusing situation. :)
I'm working on a search input in which a user enters a name of another user (or part of a name) in a search text box and then a list of users matching that search string is returned. The problem is that it is a bit slow when there are tens of thousands of users involved. Due to this slowness, when the user quickly enters a name into the search input, the screen will begin to flash search results for each key stroke (well after the user has already entered the search string in). It's like a severely delayed reaction.
For instance, if I enter in the name 'Wendy', the search results for the search string 'W' (the first character I entered) will not even be displayed yet. The search results for the letter 'W' will then be displayed, followed by 'We' and so on and so forth even though i've already typed the full name and just want to see the results for 'Wendy'.
What I want to do is only perform the search when the user has not entered anything for a certain period of time (i'm thinking two seconds). Otherwise, the word 'Searching' will be displayed. The code of the Javascript method is below. Just as a note, that code currently works for searching through the users, I just need to implement the delayed execution.
function updateSearchResults() {
if($F('searchString').length > 0){
Element.update($('searchResultsScrollBox'), '<h3>Searching...</h3>');
$('searching').style.display = 'block';
var url = '<c:url value='ajaxFrontGetUsers.html'/>';
var ajax = new Ajax.Updater({success: 'searchResults'}, url,
{method: 'post', parameters: $('searchForm').serialize(true)});
$('searching').style.display = 'none';
}
}
I hope this all makes sense. Thanks in advance for anyone that can help.
Try the following steps:
Every few milliseconds, check to see if the textbox has new data in it.
If the textbox has new text, execute your Ajax, and copy the text to a variable (for comparison in step 1).
If you want to improve performance from there, activate the timer whenever the user types something, and deactivate it when the Ajax call is made.
Hey, thanks for your answer.
I ended up setting 500 millisecond intervals in which a javascript function would continuously check to see if new characters were entered in the search string within that 500 millisecond time period. If they were, the search function would be called to search on the string the user had entered. Otherwise, it would wait another 500 milliseconds until the user had stopped typing. In the end, it's very similar to what you proposed.
Thanks again!
Or you could put an "onkeypress"event handler on the item that clears some global variable or cancels a timer to keep the AJAX event from firing. I know Prototype implements this for you via it's in-place editor and the "frequency" option. (I believe it sets a timeout timer that it cancels after every key press.)
I know this is an old question, but for others taking a look, I think your going about this the wrong way. I think you should date/time stamp each ajax call, and keep track of the data time stamps in your javascript. Then, when an ajax call is returned you can check the date/time stamp and make sure it is the result set for the most resent ajax call. This way you do make the ajax call for each keystroke immediately, but only display results if the ajax results catches up to the typing.
Also, are you sending over ALL matching results? Like thousands for just the letter W? To speed up the javascript side maybe you should rank the results on the database and return only the top 10-20. The doesn't want to see more than 10-20 results anyways.
Additionally, is your SQL query optimal? Seems like the query is taking too long. If your doing a one sided like search (ie. like input+'%') not a two sided like search (ie. like '%' + input + '%') then there are some really good indexes you can put on the table to help you out.