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
Related
i have edit and close button in same row, if there is any edit made to the input field then it must show an alert message, if no change is made it must retain its old value. My issue here is, i click on edit and do some change to input, when i click on close, i am able to retain new value, but when i click on close, it must revert to old value
TS:
public onEditEvent(event) {
this.editCommitment = event;
}
public onCloseEvent(event){
if(event.policyCT == this.editCommitment.policyCT && event.quotes == this.editCommitment.quotes && event.writtenPremium == this.editCommitment.writtenPremium) {
event.writtenPremium = this.editCommitment.writtenPremium;
event.policyCT = this.editCommitment.policyCT;
event.quotes = this.editCommitment.quotes
this.editableRow = 0;
} else {
alert('change')
}
}
Demo
By default ng-model will update the model.
You need to maintain old value manually when user clicks on edit button. Like below:-
selectedRow: any;
public onEditEvent(event) {
this.selectedRow = { ...event };
this.editCommitment = event;
}
Apply that when user click on close button.
public onCloseEvent(event) {
event.writtenPremium = this.selectedRow.writtenPremium;
event.policyCT = this.selectedRow.policyCT;
event.quotes = this.selectedRow.quotes;
this.editableRow = 0;
}
And on Save click you dont have to do anything as model is already updated.
Working Demo:- https://stackblitz.com/edit/angular-turxyo?file=src%2Fapp%2Fapp.component.ts
I need to enable the submit button as soon as all input fields has value enterred. I have two input fields type text and type password and a button which is disabled (I set its class as "disabled" than use CSS to change color etc..), I would like to remove that class whenever the above condition is met. I added 'change' and 'input' event listeners to all field like below:
const inputs = [...document.querySelectorAll('input[type="text"], input[type="password"]')];
const continueBtn = document.querySelector('continuebtn');
const signinForm = document.querySelector('#sign-in-form');
inputs.forEach((input) => {
input.addEventListener('input', function(e){
if (input.value !== '') {
continueBtn.classList.remove('disabled');
}else{
continueBtn.classList.add('disabled');
}
}
});
Tried with e.target.value.trim() === '' as well
I guess the above would be applied to all inputs and check if they're empty when the user is typing, but I'm not able to make it work: the button is being activated no matter what I do.
I would need some help in plain Javascript as this is what I'm currently learning. no jQuery. Thanks
Use the every() method to check all the inputs, not just the one that the user is currently editing.
const inputs = [...document.querySelectorAll('input[type="text"], input[type="password"]')];
const continueBtn = document.querySelector('#continuebtn');
const signinForm = document.querySelector('#sign-in-form');
inputs.forEach((input) => {
input.addEventListener('input', function(e) {
if (inputs.every(input => input.value.trim())) {
continueBtn.classList.remove('disabled');
} else {
continueBtn.classList.add('disabled');
}
});
});
#continuebtn.disabled {
background-color: grey;
}
<input type="text">
<input type="password">
<button id="continuebtn" class="disabled">Continue</button>
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.
I am trying to make a citizenNumber component to use in forms. It implements ControlValueAccessor for ngModel.
export class CitizenNumberComponent implements ControlValueAccessor {
private _value: string;
#Input() placeholder = '';
#Input() required = true;
get value(): string {
return this._value;
}
set value(value: string) {
this._value = value;
this.propagateChange(value);
}
// registers 'fn' that will be fired when changes are made
// this is how we emit the changes back to the form
registerOnChange(fn: any): void {
this.propagateChange = fn;
}
// not used, used for touch input
registerOnTouched(fn: any): void { }
// this is the initial value set to the component
writeValue(value: string): void {
if (value) {
this._value = value;
}
}
// the method set in registerOnChange to emit changes back to the form
propagateChange = (_: any) => { };
}
I make a NumberDirective to restrict input except 0-9 digits.
In numberDirective I used 'input' event because keypress, keydown and keyup not working android chrome.
#Directive({
selector: 'input[jhiNumbersOnly]'
})
export class NumberDirective {
private specialKeys: Array<string> = ['Backspace', 'Delete', 'Insert', 'Tab', 'End', 'Home', 'ArrowRight', 'ArrowLeft'];
#HostListener('input', ['$event']) onInput(event) {
const key = event['data'];
// Allow Backspace, tab, end, and home keys
if (this.specialKeys.indexOf(key) !== -1) {
return;
}
const initalValue = event.target['value'];
event.target['value'] = initalValue.replace(/[^0-9]*/g, '');
if (initalValue !== event.target['value']) {
event.stopPropagation();
}
}
}
Finally, everything works but altough event has stopped, the model takes the value.
As an example, my input maxlength is 11. after 10 number enter, if some key entered (except 0-9) form will be validate.
Look component in stackblitz;
Can you help me with my problem?
You should replace your input handler by a keydown handler. Then if the key is good, do nothing, otherwise, prevent the event from happening.
The problem is that if you listen to the input event, it will be too late, the ngModel will have been updated, so you have to listen to the keydown event and filter it appropriately.
#HostListener('keydown', ['$event']) onKeyDown(e: KeyboardEvent) {
if (this.specialKeys.indexOf(e.key) !== -1 || new RegExp(/[0-9]/g).test(e.key)) {
return;
}
e.preventDefault();
}
I tested this code in your stackblitz demo and it works.
EDIT: You mentionned you cannot use the keydown handler, sorry.
I managed to get it to work with the oninput handler on the the <input> element and I removed your directive on the input:
<div class = "form-group">
<label class = "form-control-label label-color" for = "citizenNumber">Citizen Number
</label>
<input type = "text"
class = "form-control input-css"
name = "citizenNumber"
id = "citizenNumber"
#citizenNumber="ngModel"
oninput="this.value = this.value.replace(/[^0-9]/g, '');"
[(ngModel)] = "value"
[placeholder] = "placeholder"
minlength = "11"
maxlength = "11"
[required] = "required">
<div *ngIf = "citizenNumber.invalid && (citizenNumber.dirty || citizenNumber.touched)"
class = "form-text text-danger">
<small *ngIf = "citizenNumber.errors.required">This field is required.</small>
<small *ngIf = "citizenNumber.errors.minlength">This field must be 11 characters.</small>
<small *ngIf = "citizenNumber.errors.invalidTc">This is not a citizen number</small>
</div>
</div>
Here is an updated Stackblitz.
Hope that helps!
I'm developing a web application with Angular2, with one component needing to listen to the keyboard to check if the 'D' key is pressed. This works fine, except that it's preventing me from typing into a HTML <input> which resides in another component. I'm guessing it's caused by some piece of code in the keyboard listener class, but I'm not sure where.
Here is the listener class in it's entirety:
export class Keyboard {
private keyboard_d;
constructor(){
this.keyboard_d = Keyboard.keyboard(68);
}
static keyboard(keyCode){
var key = {
code: keyCode,
isDown: false,
isUp: true,
press: undefined,
release: undefined,
downHandler: function(event){
if (event.keyCode === key.code) {
if (key.isUp && key.press) key.press();
key.isDown = true;
key.isUp = false;
}
event.preventDefault();
},
upHandler: function(event) {
if (event.keyCode === key.code) {
if (key.isDown && key.release) key.release();
key.isDown = false;
key.isUp = true;
}
event.preventDefault();
}
}
//Attach event listeners...
window.addEventListener(
"keydown", key.downHandler.bind(key), false
);
window.addEventListener(
"keyup", key.upHandler.bind(key), false
);
return key;
}
//Returns true if the D key is pressed down, false if it is not.
public isDpressed(){
return this.keyboard_d.isDown;
}
}
This class is used in the Angular2 component like this:
var keyboard_listener = new Keyboard(); //create
var dPressed : boolean = keyboard_listener.isDPressed();
Where in this code is it preventing me from typing into HTML input forms?
Note I've purposely left out the angular code of the two relevant components because I don't want to add the angular2 tag if I don't need to, my intuition says the code above is the problem. But if it's deemed necessary I'll edit the post and add the angular code and tag.
The call of event.preventDefault stops the default behaviour of that event and as a result the character is not shown in the input field.