I need to add a space after every 4th digit I enter, I am getting this in the console, how can I can achieve this to change in the input in Angular 5.
Code I used given below .ts
mychange(val) {
const self = this;
let chIbn = val.split(' ').join('');
if (chIbn.length > 0) {
chIbn = chIbn.match(new RegExp('.{1,4}', 'g')).join(' ');
}
console.log(chIbn);
this.id = chIbn;
}
HTML
<input class="customerno" (ngModelChange)="mychange($event)" [formControl]="inputFormControl" (keydown.backspace)="onKeydown($event)" maxlength="{{digit}}" (keyup)="RestrictNumber($event)" type="tel" matInput [(ngModel)]="id" placeholder="Customer No. ">
Console:
1
11
111
1111
1111 1
1111 11
1111 111
1111 1111
1111 1111 1
1111 1111 11
1111 1111 111
1111 1111 1111
I adapted it from Angular 2 : add hyphen after every 4 digit in input , card number input. but I changed the hypen to a space.
I would recommend to check out this Directive
import { Directive, HostListener, ElementRef } from '#angular/core';
#Directive({
selector: '[credit-card]'
})
export class CreditCardDirective {
#HostListener('input', ['$event'])
onKeyDown(event: KeyboardEvent) {
const input = event.target as HTMLInputElement;
let trimmed = input.value.replace(/\s+/g, '');
if (trimmed.length > 16) {
trimmed = trimmed.substr(0, 16);
}
let numbers = [];
for (let i = 0; i < trimmed.length; i += 4) {
numbers.push(trimmed.substr(i, 4));
}
input.value = numbers.join(' ');
}
}
and use in your html template as
<input type="text" credit-card>
Here is the
source code
UPDATE: (10/10/2019)
Input type should be only text (default type)
Don't forget to handle Backspace, Cursor Position, and American Express
I had to handle some extra complexity, but it's likely what many people will confront when developing this. We need to consider use of the Backspace key and arrow keys when rewriting the input value. There is also American Express numbers to consider, which are not simply 4-4-4-4 numbers.
Here's how I did it in a component using a template reference variable and cursor position detection. (No need for a custom directive if you only have one component that is taking credit card numbers, which is often the case.)
To handle Backspace and cursor arrow keys, we have to store the original cursor position and restore it after editing from a spot anywhere other than the end of the string.
To enable handling of American Express, I use a variable called partitions to store the 4-6-5 spacing format for Amex and the 4-4-4-4 spacing format for all other cards. We loop partitions as we add spaces.
/* Insert spaces to make CC number more legible */
cardNumberSpacing() {
const input = this.ccNumberField.nativeElement;
const { selectionStart } = input;
const { cardNumber } = this.paymentForm.controls;
let trimmedCardNum = cardNumber.value.replace(/\s+/g, '');
if (trimmedCardNum.length > 16) {
trimmedCardNum = trimmedCardNum.substr(0, 16);
}
/* Handle American Express 4-6-5 spacing format */
const partitions = trimmedCardNum.startsWith('34') || trimmedCardNum.startsWith('37')
? [4,6,5]
: [4,4,4,4];
const numbers = [];
let position = 0;
partitions.forEach(partition => {
const part = trimmedCardNum.substr(position, partition);
if (part) numbers.push(part);
position += partition;
})
cardNumber.setValue(numbers.join(' '));
/* Handle caret position if user edits the number later */
if (selectionStart < cardNumber.value.length - 1) {
input.setSelectionRange(selectionStart, selectionStart, 'none');
}
}
If you have a routine of your own to detect American Express numbers, use it. What I'm using here simply examines the first two digits and compares them to PAN/IIN standards.
Higher in your component, ensure you have the right imports:
import { ViewChild, ElementRef } from '#angular/core';
And:
#ViewChild('ccNumber') ccNumberField: ElementRef;
And when you set up your form controls, do something like this so that spaces can be included in your regex pattern:
this.paymentForm = this.fb.group({
cardNumber: ['', [Validators.required, Validators.pattern('^[ 0-9]*$';), Validators.minLength(17)]]
})
And finally, in your template, configure your element like this:
<input maxlength="20"
formControlName="cardNumber"
type="tel"
#ccNumber
(keyup)="cardNumberSpacing()">
You should be good to go!
Related
I feel that this is a dumb question, sorry.
I have an input with the number type and I want to add some validation to it. It is not required, so an empty string should be valid, negative numbers too, but not the - sign.
Consider now I've entered -102 into that field and removing symbols one by one, watching for changes.
Here's the basic codepen for it. As you can see, when there's just a - sign left the value (event.target.value) is an smpty string, which should be valid.
So, how can I check if there is only a minus sign left and mark this field as invalid?
const el = document.getElementById('input');
el.addEventListener('keyup', (e) => {
const value = e.target.value;
console.log(value)
})
<input type="number" id="input">
you can use pattern to only accept positive or negative number
in JS you can call method checkValidity() or use {yourinput}.validity.valid to check if value entered in input is valid or not
in css you can use the pseudo class :invalid to design your input when value entered don't match the pattern/field expectation
const el = document.getElementById('input');
el.addEventListener('keyup', (e) => {
console.log(el.checkValidity());
if (!el.checkValidity()) {
//treat case input invalid
}
})
input:invalid {
color: red;
}
<input type="number" id="input" pattern="\d+">
I have a requirement to display a hyphen after 5 characters in a text box for zip code. On entering more than 5 characters, a hyphen is displayed, as expected. However, when a user enters a hyphen symbol manually, the code should automatically remove the hyphen added manually. That is not working as expected. The hyphens added manually are not getting removed. When I debugged the typescript code in browser developer tools, I could see that the extra hyphen was removed from the property 'zipCode', but that change is not getting reflected in the UI.
Here is the code for the typescript file:
export class AppComponent {
zipCode: string = '';
public setValue(val: any) {
if(val.indexOf('-') >= 0)
val = val.replaceAll('-', '');
if(val.length > 5)
val = val.substr(0,5) + '-' + val.substr(5, val.length - 5);
this.zipCode = val;
}
}
Here is the code for html file:
<input type="text" name="zipField" [(value)] = "zipCode" (input)="setValue($event.target.value)">
Can someone please let me know why this code is not working. Also, please suggest any alternate way of achieving the removal of extra hyphen added manually. Thanks in advance.
Instead of passing the value of the input alone you should pass the element itself.
That way you will be able to change the text in the input tag too
<input type="text" name="zipField" [(value)] = "zipCode" (input)="setValue($event.target)">
Then in your typescript file
export class AppComponent {
...
public setValue(element: any) {
let val = element.value;
if(val.contains('-'))
val = val.replaceAll('-', '');
if(val.length > 5)
val = val.substr(0,5) + '-' + val.substr(5, val.length - 5);
this.zipCode = val;
element.value = val;
}
}
I'm creating a form to seed a varying number of teams to a tournament, by first mapping them to a form group with labels and number input. How can I make it so each field has to be unique before the form is considered valid?
By unique, I mean each field with take a certain number in a range, say if a tournament has 14 teams, then each field should be a number between 1 and 14, but two fields shouldn't be able to take the same number.
renderButton() {
return (
<Form onSubmit={this.handleSeedingSubmit}>
{this.state.teams.map((team)=>
<FormGroup key={team.name}>
<Form.Label >{team.name}</Form.Label>
<Form.Control type = "number" name={team.name} min={1} max={this.state.tournament.noTeams} onChange={this.onChangeHandler} required />
</FormGroup>
)}
<Button type="submit" >
Submit
</Button>
</Form>
);
}
On submit each team is being mapped with {name, seeding}. I want every team to have a unique seeding as they will be sorted into pools based on seeding later.
Well what you can do is make the number inputs controlled by storing their values in the store:
state = {
// other state,
inputs: {}
}
then in onChangeHandler set the value of each input in the state:
function onChangeHandler(e) {
const { name, value } = e.target;
this.setState({
inputs: {
...this.state.inputs,
[name]: value
}
})
}
then when your form is submitted you can add a check to see if the values are unique or not, there are many ways to do that, what I'm doing here is remove the duplicates from the array and then check the length of the array against the values in the state like this:
function handleSeedingSubmit(e) {
e.preventDefault();
const { inputs } = this.state;
const valuesInState = Object.values(input);
const uniqueValuesArr = [...new Set(valuesInState)];
const areInputsValid = valuesInState.length === uniqueValuesArr.length;
if (!areInputsValid) {
// set Error here
return;
}
// Hurray!! Inputs are valid
// Handle Success case here
}
Hope it helps :)
I have an input field where the user can input a numeric value. I need to automatically insert commas after every 3rd digit. When the user deletes numbers, the commas need to be in the correct places (after every 3rd digit, starting from the first number) as well as stay in place instead of relocating to the end of the input value. I cannot use ngModel, this is a reactive form.
I have tried this method in my TS file, to mask the user input
maskInputAmount(e) {
const t = e.target.value.replace(/\D/g, '').match(/(\d{0,3})(\d{0,3})
(\d{0,3})/);
e.target.value = t[2] ? t[1] + ',' + t[2] + (t[3] ? ',' + t[3] : '') :
t[1];
}
And in my HTML input field
<input (input)="maskInputAmount($event)" maxlength=11
formControlName="businessNetWorth" id="businessNetWorth"
type="text" class="form-control col-3 col-lg-12" data-hint="yes">
I am having commas come after every 3rd number. However, when deleting numbers from the end of the input, the commas at the front of the number should update correctly. For example, I enter '123,456,789'. When I delete the last two numbers I get '123,456,7' when it should be '1,234,567'.
One other issue, when a user deletes one of the first numbers, the comma in the input box automatically repositions itself to the end of the input value, I need it to stay in place. For example: '123,456,789'. I delete '3' and have '124,567,89' and the cursor is now behind the '9' when it should stay in front of the '2'.
How can I change my maskInputAmount(e) method to make this behave correctly?
Following code worked for me. (Assume present currency is in Indian rupees. If you want to have your own currency then you need to mention your country's code in code).
app.component.html
<input type="text" [formControl]="currency" (input)="changeToCurrency(currencyTextRef)" #currencyTextRef>
//sending reference of input element #currencyTextRef to function
{{ currency.value }}
app.component.ts
currency = new FormControl();
temp;
currncyLength=0;
changeToCurrency(currencyTextRef) {
this.currncyLength = this.currency.value.length;
console.log("currency len is "+this.currncyLength);
let index:number;
// if(currencyTextRef.selectionStart || currencyTextRef.selectionStart == '0') {
// console.log("index isss "+currencyTextRef.selectionStart);
index = currencyTextRef.selectionStart; //getting caret(cursor) position
// }
console.log("index is "+index);
// console.log("value is "+this.currency.value);
let a = this.currency.value;
a = a.replace(/,/g,'');
let num:number = + a;
let temp = new Intl.NumberFormat('en-IN').format(num); //inplace of en-IN you can mention your country's code
// console.log("temp is "+temp);
this.currency.setValue(temp.toString());
console.log("pressent len iss "+this.currency.value.length)
if(this.currncyLength<this.currency.value.length) {
console.log("incoming to < ")
index+=1;
currencyTextRef.setSelectionRange(index,index);
}
else if(this.currncyLength >=this.currency.value.length) {
console.log("incoming to > ");
// index-=1;
currencyTextRef.setSelectionRange(index,index);
}
// else {
// currencyTextRef.setSelectionRange(index,index);
// }
}
Following link might help.
Intl number MDN
I'd like users to enter a code and to assist them in transcribing it I'd hope to increase the spacing between every 3rd character they type. I've seen this nicely done for credit cards having 4 character spacing. This will be for an Ionic app so the simple input box coud be replaced with a customised Ionic control.
What methods have you used for this and what works best?
Open to Angular/Ionic code samples or a related web site tutorial.
Pure CSS would be nice.
Here is an other version, without jquery, works with alphanumerical and takes a configurable separator:
Typescript:
GROUP_SEPARATOR=" ";
......
format(valString) {
if (!valString) {
return '';
}
let val = valString.toString();
const parts = val.replace(/ /g, '');
return parts.replace(/\B(?=(?:\w{3})+(?!\w))/g, this.GROUP_SEPARATOR)
};
HTML
<input [(ngModel)]="input"
style="border:1px solid black" #myBudget="ngModel" (input)="input = format(input)">
DEMO
You can add space on keyup event.
Example
$('#input').on('keyup', function(e){
var val = $(this).val();
var newval = '';
val = val.replace(/\s/g, '');
for(var i=0; i < val.length; i++) {
if(i%3 == 0 && i > 0) newval = newval.concat(' ');
newval = newval.concat(val[i]);
}
$(this).val(newval);
})
I found a simpler method based on Vija's method ... Basically we match 3 non-space chars and we remove any previously added space chars. This is needed to allow the user to update or erase any chars in the text box.
A final solution may also need to adjust the position of the cursor based on where it was prior to performing the replace.
$('#input').on('keyup', function(e){
var val = $(this).val();
var newval = val.replace(/([^ ][^ ][^ ]) */g, "\$1 ").trim();
$(this).val(newval);
})