Browse Source

Add x-mask:dynamic instead of :function

Caleb Porzio 3 years ago
parent
commit
c12a63b33f

+ 24 - 10
packages/docs/src/en/plugins/mask.md

@@ -87,57 +87,71 @@ The following wildcard characters are supported in masks:
 | `9` | Only numeric characters (0-9) |
 
 <a name="mask-functions"></a>
-## Custom Mask Functions
+## Dynamic Masks
 
-Sometimes simple mask literals (i.e. `(999) 999-9999`) are not sufficient. In these cases, `x-mask:function` allows you to dynamically generate masks on the fly based on user input.
+Sometimes simple mask literals (i.e. `(999) 999-9999`) are not sufficient. In these cases, `x-mask:dynamic` allows you to dynamically generate masks on the fly based on user input.
 
 Here's an example of a credit card input that needs to change it's mask based on if the number starts with the numbers "34" or "37" (which means it's an Amex card and therefore has a different format).
 
 ```alpine
-<input x-mask:function="
+<input x-mask:dynamic="
     $input.startsWith('34') || $input.startsWith('37')
         ? '9999 999999 99999' : '9999 9999 9999 9999'
 ">
 ```
 
-As you can see in the above example, every time a user types in the input, that value is passed to the function as `$input`. Based on the `$input`, a different mask is utilized in the field.
+As you can see in the above example, every time a user types in the input, that value is passed to the expression as `$input`. Based on the `$input`, a different mask is utilized in the field.
 
 Try it for yourself by typing a number that starts with "34" and one that doesn't.
 
 <!-- START_VERBATIM -->
 <div class="demo">
-    <input x-data x-mask:function="
+    <input x-data x-mask:dynamic="
         $input.startsWith('34') || $input.startsWith('37')
             ? '9999 999999 99999' : '9999 9999 9999 9999'
     ">
 </div>
 <!-- END_VERBATIM -->
 
+`x-mask:dynamic` also accepts a function as a result of the expression and will automatically pass it the `$input` as the the first paramter. For example:
+
+```alpine
+<input x-mask:dynamic="creditCardMask">
+
+<script>
+function creditCardMask(input) {
+    return input.startsWith('34') || input.startsWith('37')
+        ? '9999 999999 99999'
+        : '9999 9999 9999 9999'
+}
+</script>
+```
+
 <a name="money-inputs"></a>
 ## Money Inputs
 
-Because writing your own custom mask function for money inputs is fairly complex, Alpine offers a prebuilt one and makes it available as `$money()`.
+Because writing your own dynamic mask expression for money inputs is fairly complex, Alpine offers a prebuilt one and makes it available as `$money()`.
 
 Here is a fully functioning money input mask:
 
 ```alpine
-<input x-mask:function="$money($input)">
+<input x-mask:dynamic="$money($input)">
 ```
 
 <!-- START_VERBATIM -->
 <div class="demo" x-data>
-    <input type="text" x-mask:function="$money($input)" placeholder="0.00">
+    <input type="text" x-mask:dynamic="$money($input)" placeholder="0.00">
 </div>
 <!-- END_VERBATIM -->
 
 If you wish to swap the periods for commas and vice versa (as is required in certain currencies), you can do so using the second optional parameter:
 
 ```alpine
-<input x-mask:function="$money($input, ',')">
+<input x-mask:dynamic="$money($input, ',')">
 ```
 
 <!-- START_VERBATIM -->
 <div class="demo" x-data>
-    <input type="text" x-mask:function="$money($input, ',')"  placeholder="0.00">
+    <input type="text" x-mask:dynamic="$money($input, ',')"  placeholder="0,00">
 </div>
 <!-- END_VERBATIM -->

+ 1 - 1
packages/mask/src/index.js

@@ -4,7 +4,7 @@ export default function (Alpine) {
         let templateFn = () => expression
         let lastInputValue = ''
 
-        if (['function'].includes(value)) {
+        if (['function', 'dynamic'].includes(value)) {
             // This is an x-mask:function directive.
 
             let evaluator = evaluateLater(expression)

+ 35 - 0
tests/cypress/integration/plugins/mask.spec.js

@@ -32,6 +32,34 @@ test('x-mask',
     },
 )
 
+test('x-mask with x-model',
+    [html`
+        <div x-data="{ value: '' }">
+            <input x-mask="(999) 999-9999" x-model="value" id="1">
+            <input id="2" x-model="value">
+        </div>
+    `],
+    ({ get }) => {
+        // Type a phone number:
+        get('#1').type('12').should(haveValue('(12'))
+        get('#2').should(haveValue('(12'))
+        get('#1').type('3').should(haveValue('(123) '))
+        get('#2').should(haveValue('(123) '))
+        get('#1').type('4567890').should(haveValue('(123) 456-7890'))
+        get('#2').should(haveValue('(123) 456-7890'))
+        // Clear it & paste formatted version in:
+        get('#1').type('{selectAll}{backspace}')
+        get('#1').invoke('val', '(123) 456-7890').trigger('input')
+        get('#1').should(haveValue('(123) 456-7890'))
+        get('#2').should(haveValue('(123) 456-7890'))
+        // Clear it & paste un-formatted version in:
+        get('#1').type('{selectAll}{backspace}')
+        get('#1').invoke('val', '1234567890').trigger('input')
+        get('#1').should(haveValue('(123) 456-7890'))
+        get('#2').should(haveValue('(123) 456-7890'))
+    },
+)
+
 test('x-mask with non wildcard alpha-numeric characters (b)',
     [html`<input x-data x-mask="ba9*b">`],
     ({ get }) => {
@@ -43,6 +71,13 @@ test('x-mask with non wildcard alpha-numeric characters (b)',
     },
 )
 
+test('x-mask:dynamic',
+    [html`<input x-data x-mask:dynamic="'(999)'">`],
+    ({ get }) => {
+        get('input').type('123').should(haveValue('(123)'))
+    }
+)
+
 test('$money',
     [html`<input x-data x-mask:function="$money">`],
     ({ get }) => {