Using keyboard input to login in Angular - javascript

I have a button, when clicked goes to the next route/page in Angular.
Is there a way we can use the same button but instead of clicking it sometimes give the user to enter a secret passphrase on the keyboard to navigate to the next page.
Example: if a user types "nextpage" he should go to the next page.
Here is the working stackblitz code for page routing
HTML:
<button (click)=goToNextPage()>Click me or type the passphrase</button>
TS:
goToNextPage() {
this.router.navigate(['/newPage'], { skipLocationChange: true });
}

constructor() {
document.addEventListener('keyup', this.addkey);
}
typed = '';
addkey = event => {
this.typed += String.fromCharCode(event.keyCode);
if (this.typed.endsWith('NEXTPAGE')) {
this.goToNextPage();
}
};
ngOnDestroy() {
document.removeEventListener('keyup', this.addkey);
}
https://stackblitz.com/edit/us-keyboard-to-go-7kmsl7?file=src/app/checkin/checkin.component.ts
You could put in a test for backspace to remove the last character if you want.

Related

Is there any way to catch keypress events in mobile browser keyboard?

I built a filter functionality for a list of banks. It works fine in desktop: When the user puts in any name, the keypress event occurs and later it call the filter() function.
However, it does not work on mobile, since no keypress event is triggered.
The goal is whenever user put any letter in input filed, it should call that filter() function on mobile. Is there any way to do this?
(this website is built on wix so it use its velo api)
let debounceTimer;
export function search_keyPress(event) { //enable onKeypress for input form , search is the id of input
$w("#clearSearch").show(); //show the cross mark to clear inputs
$w("#search").value; // value of input field
if (debounceTimer) {
clearTimeout(debounceTimer);
debounceTimer = undefined;
}
debounceTimer = setTimeout(() => {
filter($w("#search").value); //ID of input form
}, 200);
}
let searchWord;
function filter(search) {
if (searchWord !== search) {
$w("#bankTableDataset").setFilter(wixData.filter().contains('bankName', search)); // ID of the dataset
searchWord = search;
}
}

Submit form using on screen keyboard

I am trying to submit a form using an on screen keyboard but am not sure how to go about this. Essentially I need be able to see the characters that I click on in the on screen keyboard when I click the submit button on my form.
I have a directive that has the methods I use for listing the events like onFocus onBlur. I have a component that lists the different key and mouse events like keyPressed _enterPressed etc.
Here is my code and a stackblitz link below
service.ts
private _enterPressed: Subject<void>;
get enterPressed() {
return this._enterPressed;
}
fireEnterPressed() {
this._enterPressed.next();
}
directive
private onEnter() {
let element = this.el.nativeElement;
let inputEl = element.querySelector('input');
alert("Enter"+ inputEl.value);
}
app component.ts
submit() {
//submit forms
alert('submit');
}
Here is a stackblitz example of the code https://stackblitz.com/edit/onscreen-keyboard-5uxhyo?file=src%2Fapp%2Fapp.component.ts
When I use the on screen keyboard to input characters into the input fields, and then I click the submit button I do not see the characters that I have entered however if I type normally on my computers keyboard and click submit then i can see the values alerted.
Any idea how I can fix this?
Your keyboard only change the "element.value".
You can inject the "NgControl" in your osk-input.directive
constructor(#Optional()private control:NgControl,
private el: ElementRef, private keyboard: KeyboardService) {}
And in your functions onKey and onBackspace add this.control.control.setValue(...)
private onKey(key: string) {
let element = this.el.nativeElement,start = element.selectionStart,end = element.selectionEnd;
this.measure.textContent = element.value.substr(0, start) + key;
element.value =
element.value.substr(0, start) + key + element.value.substr(end);
//<--add this lines--//
if (this.control)
this.control.control.setValue(element.value)
...
}
private onBackspace() {
let element = this.el.nativeElement,start = element.selectionStart,end = element.selectionEnd;
...
this.measure.textContent = element.value.substr(0, start);
element.value = element.value.substr(0, start) + element.value.substr(end);
//<--add this lines--//
if (this.control)
this.control.control.setValue(element.value)
...
}
BTW. Your onEnterFunction should be some like
private onEnter() {
const ev = new KeyboardEvent('keydown',{code:"Enter",key: "Enter",
keyCode: 13})
this.el.nativeElement.dispatchEvent(ev)
}
So, you can use in your .html like
<form [formGroup]="setupForm">
<input appOskInput formControlName="email"
(keydown.enter)="mobile.focus()" />
<input #mobile appOskInput formControlName="mobile"
(keydown.enter)="button.focus()" />
<button #button type="button" (click)="submit()">Submit</button>
</form>
Your forked stackblitz

How to block form submit with same trigger button but different function?

So, I have some problem. I have a search bar to search for a product, and can also redirect to another page if I type a word is match with pageKeywords array value. So in 1 searchbar there can be 2 triggers.
The first is when I click on search keywords and when it matches it will lead to another page:
$('#submitForm').on("click",function(e){
pageKeywords($("#searchKeywords").val(),e)
})
And will also direct to the result page if the word written does not contain pageKeyword:
$('#submitForm').on('click', function () {
console.log("another function submit")
$('#fform').submit()
return false;
});
The problem I'm having is, when I click Search, it will trigger the form submit. How to prevent form submission when the words typed in the searchbar match with pageKeywords? If it doesn't match ,the form submit can run. These two events cannot be contested, here I give an example of the code that I have made
you can try to input, after you type it and click enter, if the word matches with pageKeywords it won't reload, but when it doesn't match it will reload. How do I get my button to work like that too?
function pageKeywords(searchValue,evt){
const pageKeywords = {
"home": "/homepage",
"about": "/about-us"
}
const getInputVal = searchValue;
if(pageKeywords[getInputVal]) {
evt.preventDefault();
console.log(pageKeywords[getInputVal])
return false;
}else{
console.log('not found')
}
}
$(document).ready(function() {
$('#submitForm').on("click",function(e){
pageKeywords($("#searchKeywords").val(),e)
})
$('#submitForm').on('click', function () {
console.log("another function submit")
$('#fform').submit()
return false;
});
$("#searchKeywords").on("keypress", function(e) {
if (e.which === 13) {
pageKeywords($(this).val(),e)
}
});
})
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<form id="fform" action="#">
<input type="text" id="searchKeywords">
<button id="submitForm">Search</button>
</form>
If I understood your question correctly, you basically want to take different actions based on whether the search term matched something in your pageKeywords object.
You don't need to create two listeners for that. Just listen to the form submit event which is triggered on enter press as well. Then you can match the value and take action on the condition if the term matches or not.
const pageKeywords = {
"home": "/homepage",
"about": "/about-us"
}
$('#fform').on('submit', function(e){
const searchTerm = $('#searchKeywords').val();
if(searchTerm in pageKeywords){
e.preventDefault();
alert('term found');
} else {
alert('No match');
}
});
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<form id="fform" action="#">
<input type="text" id="searchKeywords">
<button id="submitForm">Search</button>
</form>
This is my opinion but if I had to do this, I wouldn't do it this way. I would keep all this logic on the server side.
You're overwriting one function call with another - JavaScript doesn't support function overloading. Combine their logic into a common function:
$('#submitForm').on("click",function(e) {
if (pageKeywords($("#searchKeywords").val(), e) !== false) {
console.log("another function submit");
$('#fform').submit();
} else {
e.preventDefault();
return false;
}
});

Effective onBlur for react-data-grid

I'm jumping in on a pretty big React JS project which is using react-data-grid to display a bunch of editable data. Right now, you have to click an Update button to send changes to the server. My task at hand is to create auto-save functionality like so:
User selects cell to edit text
User changes text
User either moves to another cell or clicks away from data-grid
Changes are persisted to the server
Here's what I've tried:
onBlur event on each column. The event will fire, but it seems like the event was attached to a div and not the underlying input control. Therefore, I don't have access to the cell's values at the time this event is fired.
onCellDeselected on the <ReactDataGrid> component itself. It seems like this method is fired immediately upon render, and it only gets fired subsequent times when moving to another cell. If I'm editing the last cell and click away from the data-grid, this callback isn't fired.
Using react-data-grid, how can I effectively gain access to an editable cell's content when the user finishes editing?
The commits on react-data-grid are handled by the EditorContainer. The commit logic is simple. An editor commits a value when:
The editor unmounts
Enter is pressed
Tab is pressed
In some cases when the arrows are pressed (will skip this part is it may not be necessary for you, you can look at the logic for this on the EditorContainer)
Based on that the way I would recommend to do the autosave is:
Create an an EditorWrapper (HOC) the editors where you want auto save to be turned on
const editorWrapper(WrappedEditor) => {
return class EditorWrapper extends Component {
constructor(props) {
base(props);
this._changeCommitted = false;
this.handleKeyDown.bind(this);
}
handleKeyDown({ key, stopPropagation }) {
if (key === 'Tab' || key === 'Enter') {
stopPropagation();
this.save();
this.props.onCommit({ key });
this._changeCommitted = true;
}
// If you need the logic for the arrows too, check the editorContainer
}
save() {
// Save logic.
}
hasEscapeBeenPressed() {
let pressed = false;
let escapeKey = 27;
if (window.event) {
if (window.event.keyCode === escapeKey) {
pressed = true;
} else if (window.event.which === escapeKey) {
pressed = true;
}
}
return pressed;
}
componentWillUnmount() {
if (!this._changeCommitted && !this.hasEscapeBeenPressed()) {
this.save();
}
}
render() {
return (
<div onKeyDown={this.handleKeyDown}>
<WrappedComponent {...this.props} />
</div>);
}
}
}
When exporting you editor just wrap them with the EditorWrapper
const Editor = ({ name }) => <div>{ name }</div>
export default EditorWrapper(Editor);
Use one of the start or stop event callback handlers at the DataGrid level like onCellEditCommit
<DataGrid
onCellEditCommit={({ id, field, value }, event) => {
...
}
/>
or a valueSetter for a single the column definition:
const columns: GridColDef[] = [
{
valueSetter: (params: GridValueSetterParams) => {
// params.row contains the current row model
// params.value contains the entered value
},
},
];
<DataGrid columns={columns} />

Phonegap - Determine exact element active

I need to change the back button functionality of my phonegap project, which I've succeeded in doing without any problem. The only issue now, is that I need to further change the functionality based on if the user has a certain field selected.
Basically, if the user has clicked in a field with the id of "date-selector1", I need to completely disable the back button.
I was attempting to use document.activeElement, but it only returns the type of the element (input in this case), but I still want the functionality to work when they are in a general input, but not when they are in an input of a specific id.
EDIT
I tried all of the suggestions below, and have ended up with the following code, but still no success.
function pluginDeviceReady() {
document.addEventListener("backbutton", onBackKeyDown, false);
}
function onBackKeyDown() {
var sElement = document.activeElement;
var isBadElement = false;
var eList = ['procedure-date', 'immunization-date', 'lab-test-done', 'condition-onset', 'condition-resolution', 'medication-start-date', 'medication-stop-date', 'reaction-date'];
console.log("[[ACTIVE ELEMENT: --> " + document.activeElement + "]]");
for (var i = 0;i < eList.length - 1;i++) {
if (sElement == $(eList[i])[0]) {
isBadElement = true;
}
}
if (isBadElement) {
console.log('Back button not allowed here');
} else if ($.mobile.activePage.is('#main') || $.mobile.activePage.is('#family') || $.mobile.activePage.is('#login')) {
navigator.app.exitApp();
} else {
navigator.app.backHistory();
}
}
if you're listening for the back button you can add this if statement:
if (document.activeElement == $("#date-selector1")[0]) {
/*disable button here, return false etc...*/
}
or even better (Thanks to Jonathan Sampson)
if (document.activeElement.id === "date-selector1") {
/*disable button here, return false etc...*/
}
You can have a flag set when a user clicks on a field or you can have a click event (or any other type of event) when a user clicks on the field that should disable the back button.
From the documentation it looks like for the specific page that the backbuton is conditional on you can drop back-btn=true removing that back button.
http://jquerymobile.com/test/docs/toolbars/docs-headers.html
If you need complex conditional functionality you can just create your own button in the header or footer, style it using jquery-mobile widgets and implement your own click functionality.

Categories

Resources