简体   繁体   中英

Control value of input in Aurelia

I need to create an input in Aurelia that only accepts a phone number. If the user types 1234567890 into this input it should display (123) 456-7890 and the bound variable would be set to 1234567890 . The result should be the same if the user types (123) 456-7890 into the input as well. If the user types a letter into the input, the input should not display the letter, nor should the bound javascript variable get updated.

I'm able to partially achieve this using a ValueConverter:

phone.ts

export class PhoneValueConverter {
    private removeNonDigits(input) {
        let digits = '';

        // Remove non-digits. i.e. '(', ')', ' ' and '-'
        for (let i = 0; i < input.length; i++) {
            let char = input.charAt(i);

            if ('0' <= char && char <= '9')
                digits += char;
        }

        return digits;
    }

    toView(value) {
        if (!value)
            return value;

        value = this.removeNonDigits(value);

        let formatted = '(' + value.substring(0, 3);

        if (value.length >= 3)
            formatted += ') ' + value.substring(3, 6);
        if (value.length >= 6) {
            // Don't place an upper limit, otherwise the user would not
            // see the entire value
            formatted += '-' + value.substring(6);
        }

        return formatted;
    }

    fromView(value) {
        let digits = this.removeNonDigits(value);

        // Only accept a 9-digit phone number
        return digits.substring(0, 10);
    }
}

app.html

<template>
  ${PhoneNumber} <br>
  <require from="phone"></require>
  <input value.bind="PhoneNumber | phone">
</template>

This works perfectly in forcing PhoneNumber to always be 0-9 numerical digits. If the user types a letter, or a 10th digit, into the input, it will not be added to PhoneNumber - just as expected. But unfortunately, the value of the input ( $('input').value() , not value.bind ) will still contain the extra, incorrect character.

Is there an Aurelia convention in controlling what characters get added to the value of the input?

You can subscribe to the input's keydown event and prevent the default action when it's a character you don't want to appear in the input.

Here's an example of using this approach to build a very simple numeric input: https://gist.run?id=3101e8f73cf4da32445505d0e4258f01

app.html

<template>
  <require from="./numeric-input"></require>

  <numeric-input value.bind="value"></numeric-input>

  ${value}
</template>

app.js

export class App {
  value = '';
}

numeric-input.html

<template>
  <input type="text" value.bind="value" placeholder.bind="placeholder">
</template>

numeric-input.js

import {
  inject,
  bindable,
  bindingMode
} from 'aurelia-framework';

// http://stackoverflow.com/a/995193/725866
function isNavigationOrSelectionKey(e) {
  // Allow: backspace, delete, tab, escape, enter and .
  if ([46, 8, 9, 27, 13, 110, 190].indexOf(e.keyCode) !== -1 ||
    // Allow: Ctrl+A/X/C/V, Command+A/X/C/V
    ([65, 67, 86, 88].indexOf(e.keyCode) !== -1 && (e.ctrlKey === true || e.metaKey === true)) ||
    // Allow: home, end, left, right, down, up
    (e.keyCode >= 35 && e.keyCode <= 40)) {
     // let it happen, don't do anything
     return true;
  }
  return false;
}

// http://stackoverflow.com/a/995193/725866
function keydown (e) {
  if (isNavigationOrSelectionKey(e)) {
    return;
  }
  // If it's not a number, prevent the keypress...
  if ((e.shiftKey || (e.keyCode < 48 || e.keyCode > 57)) && (e.keyCode < 96 || e.keyCode > 105)) {
    e.preventDefault();
  }
}

@inject(Element)
export class NumericInput {
  @bindable({ defaultBindingMode: bindingMode.twoWay }) value;
  @bindable placeholder = '';

  constructor(element) {
    this.element = element;
  }

  attached() {
    this.element.addEventListener('keydown', keydown);
  }

  detached() {
    this.element.removeEventListener('keydown', keydown);
  }
}

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM