Match inputs of two text fields - regex

Scenario: I have two input fields. One of them will accept an input in form which the user will decide. The other field should match the format defined in first field. For example, if the user enters format like anan-xxx in the first field..:
The user is allowed to enter b1c1-!*> in the other field.
User cannot enter 1b1c->!* because the first character is expected to be an alphabet not number.
So the first field will define a format definition for a (alphabets), n (numbers), a placeholder, and x (any characters).
What is the easy way to perform this in UI5? I read something related to mask input but I am not sure how to implement it.

As you already guessed, the control sap.m.MaskInput can be leveraged for this kind of use case.
Here is a demo:
globalThis.onUI5Init = () => sap.ui.require([
"sap/ui/core/mvc/XMLView",
"sap/ui/model/json/JSONModel",
"sap/ui/core/Core",
], async (XMLView, JSONModel, core) => {
"use strict";
const control = await XMLView.create({
definition: `<mvc:View
xmlns:mvc="sap.ui.core.mvc"
xmlns:form="sap.ui.layout.form"
xmlns="sap.m"
xmlns:core="sap.ui.core"
core:require="{ StringType: 'sap/ui/model/type/String' }"
height="100%"
>
<App>
<Page showHeader="false">
<form:SimpleForm
editable="true"
layout="ColumnLayout"
>
<Label text="Mask"/>
<Input
value="{
path: '/maskValue',
type: 'StringType',
constraints: {
search: '^$|^[-9ax]+$'
}
}"
placeholder="Example: a9a9-xxx (case sensitive)"
/>
<Label
text="Masked Input"
displayOnly="{= !%{/maskValue}}"
/>
<MaskInput
mask="{/maskValue}"
editable="{= !!%{/maskValue}}"
>
<rules>
<MaskInputRule
maskFormatSymbol="x"
regex="[^_]"
/>
</rules>
</MaskInput>
</form:SimpleForm>
</Page>
</App>
</mvc:View>`,
models: new JSONModel(),
});
core.getMessageManager().registerObject(control, true);
control.placeAt("content");
});
<script id="sap-ui-bootstrap"
src="https://sdk.openui5.org/nightly/resources/sap-ui-core.js"
data-sap-ui-libs="sap.ui.core,sap.m,sap.ui.unified,sap.ui.layout"
data-sap-ui-async="true"
data-sap-ui-oninit="onUI5Init"
data-sap-ui-theme="sap_horizon_dark"
data-sap-ui-compatversion="edge"
data-sap-ui-excludejquerycompat="true"
data-sap-ui-xx-waitfortheme="init"
></script>
<body id="content" class="sapUiBody sapUiSizeCompact"></body>
MaskInput has an aggregation named <rules> which awaits n-MaskInputRules.
sap.m.MaskInput contains already two default rules:
"9" for /[0-9]/
"a" for /[a-zA-Z]/
Additional rule added: "x" for any characters excluding the default placeholder symbol (_). The corresponding regex is /[^_]/.
For further references, take a look at "Writing a regular expression pattern".
Optionally, you could apply the mask in the second Input only when the first Input has passed its value to the model successfully. For this, you could validate the entry via String type with the search constraint regex ^$|^[-9ax]+$ which allows..:
^$: empty string
|: or
^[-9ax]+$: from the beginning (^) till the end (+$), only -, 9, a, or x.
And finally, let the framework handle UI Messages and ValueState in order to make any invalid inputs visible to the user.

Related

Angular2 - Why does my reactive form input with an html pattern attribute is not validating correctly?

I'm struggling with a problem that I can't understand:
I need to validate an input field with a pattern="[0-9]+([,.][0-9])?" attribute on an angular reactive form with Validators.pattern, but it seems my ? quantifier at the end is not working...
What I want
I want to validate numbers with zero or one decimal maximum. As you can see on https://regex101.com/r/2D2sww/1, the regex is working great.
The actual problem
In my app I can enter as many decimals as I want without the Validator.pattern to do anything. Any other character invalidate the form, so my Validator is working.
Here is my code (simplified):
component.html
<form [formGroup]="myForm">
<input type="number" formControlName="myInputField" id="myInputField" pattern="[0-9]+([,.][0-9])?" required />
</form>
component.ts (Every import and declarations are skipped for clarity)
ngOnInit() {
this.myForm = this.formBuilder.group({
myInputField: [
"",
[Validators.required, Validators.pattern],
]
});
}
I already tried to use Validators.pattern(/^[0-9]+([,.][0-9])?$/) and Validators.pattern("[0-9]+([,.][0-9])?") as pointed in the documentation, but it doesn't change anything, so I suspect my Regex to be incorrect...
Any ideas ? Thanks, have a nice day :)
I think there is nothing wrong with your validator pattern regex,
you can remove the pattern's attribute from the input, it is redundant because you are initiating it from inside the ts file: 'myInputField': new FormControl(null, [Validators.pattern('^[0-9]+([,.][0-9])?$')]).
StackBlitz

Regex not working in Angular Validators.pattern() while working in online regex testers

I've written and rigorously tested a regex on Regex101.com, but when implemented into my FormControl Validators.pattern method, it's displaying unexpected behaviour.
This is for the Width input for a package to be mailed. Only positive values, with a maximum of 2-decimal places, a minimum value being (0.01), and a maximum being tested later against an API response (irrelevant).
package_validation_messages = {
'maxWidth': [
{type: 'required', message: 'Width is required.'},
{type: 'pattern', message: 'Invalid Width.'}
]
};
this.packageSizeForm = this.formBuilder.group({
maxWidth: new FormControl('', Validators.compose([
Validators.pattern('^([+]?(([1-9]\d*(\.\d{1,2})?)|0\.(([1-9]\d?)|(\d[1-9]))))$'),
Validators.required
]))
});
<div>
<input formControlName='maxWidth' type='text' required />
<span *ngFor="let validation of package_validation_messages.maxWidth">
<span *ngIf="packageSizeForm.get('maxWidth').hasError(validation.type) && (packageSizeForm.get('maxWidth').dirty || packageSizeForm.get('maxWidth').touched)">{{validation.message}}</span>
</span>
</div>
The following screenshot illustrates my tests from Regex101.com; you can see all the scenarios that should PASS and FAIL.
But, as you can see here, any multi-digit value fails the pattern, contrary to the expected behaviour above.
Use the following fix:
Validators.pattern(/^\+?(?:[1-9]\d*(?:\.\d{1,2})?|0\.(?:[1-9]\d?|\d[1-9]))$/)
The regex demo is here.
Make sure:
You define the regex as a regex literal (not a string, /.../ should not be wrapped with any quotes
If you use a string pattern, make sure you double escape the backslashes and then, you do not need to use ^ and $ at both ends as they will be added automatically.
The code above is equal to
Validators.pattern("\\+?(?:[1-9]\\d*(?:\\.\\d{1,2})?|0\\.(?:[1-9]\\d?|\\d[1-9]))")

HTML - Using pattern attribute

In html form, I need textarea which allows any type of text: numbers, symbols, newline or letters, including Hebrew letters. The only two rules:
The input must include the string: "{ser}"
The input should prohibit any use of "{" or "}" except for the above string
I tried this:
<form action="#">
...
<textarea pattern="[^\{\}]*\{ser\}[^\{\}]*" required>
האם אתה נמצא בשבת הקרובה? אם כן נא השב {ser} + שם מלא
</textarea>
...
<input type="submit" />
...
</form>
But for some reason it also allows sending texts that do not meet the rules. I would appreciate your help.
You cannot use pattern attribute on textareas, see the documentation.
maxlength specifies a maximum number of characters that the
is allowed to contain. You can also set a minimum length that is
considered valid using the minlength attribute, and specify that the
will not submit (and is invalid) if it is empty, using the
required attribute. This provides the with simple
validation, which is more basic than the other form elements (for
example, you can't provide specific regexs to validate the value
against using the pattern attribute, like you can with the input
element).
Perhaps implement a regex match with javascript?
function validateTextarea(text) {
var re = /ser/g;
var result = text.match(re);
if(result != null && result.length > 0)
// Do something
}
Then probably the best way is to check the function in onsubmit form attribute.

How do I use a custom Tooltip Text for Invalid Input Pattern instead of "You must use this format: [blank]"

When the input does not match the pattern specified by the pattern attribute, Firefox simply says, "Please match the requested format", which is okay; however, when this validation fails Internet Explorer 10 displays "You must use this format:" in a tooltip with nothing else. This may be simple, but searching has not yielded me a clue as to how to supply text to the tooltip telling it the pattern that should be used.
Example below for a one to four digit number:
<input id="institution_threshold_days" type="text" placeholder="0-9999" pattern="^[0-9]{1,4}$" />
Try using the title attribute to describe what you want it to say:
<input id="institution_threshold_days" type="text" placeholder="0-9999" pattern="^[0-9]{1,4}$" title="Please enter a number less than 10000." />
Should work for all major browsers...
From Microsoft
the content of the title attribute is both shown as tooltip text for
the field and appended to the generic pattern mismatch error message.
From Mozilla
Use the title attribute to describe the pattern to help the
user.
And although I cannot find official documentation, it appears to work in Chrome as well.

How can I display extra details in the autosuggest, but only ID in the input field?

I'm using a ColdFusion autosuggest for my UserID field. When a user starts to type in a UserID, a list of user ids and the user names associated with it pop up (populated by a cfc function). Sample code:
<cfinput name="userID" type="text" value="#userID#" autoSuggest="cfc:Utilities.suggestUser({cfautosuggestvalue})" matchcontains="true" />
The suggestions are listed in the format "User Name <userID>". So if the user would start typing 123, a sample suggestion that would pop up would be "Harvey Mann <1234>".
The problem is that if the user chooses that suggestion, I don't want to insert the whole suggested text into the input field - I just want to insert the user id ("1234" in this case). I would also like to be able to insert the user name ("Harvey Mann") into an adjacent field/area if possible. Is there any way to accomplish this?
Since you are using CF's built-in implementation of autosuggest, you are stuck with only having access to one returned value. Thus if the value consists of mutliple 'parts' and you want to insert different 'parts' of the value into different columns, you will have to parse the value and extract appropriate parts from the string. In your example case you could treat the value as a list delimited by <. In this case you can get the name 'part' with
trim(listfirst(form.userID, "<"))
and the id 'part' with
replace(listlast(form.userID, "<"), ">", "")
Alternatively, you can always use jQuery UI Autocomplete implementation - you'll have to write your own javascript for it, but it gives you far more control than the built-in cf's implementation. Check jQuery UI docs for more info: http://jqueryui.com/demos/autocomplete/
UPDATE:
On second thought, if you just want to display selected value's 'name' part in another area on the same page, you may be able to do it using just CF's built-in autosuggest and a bit of javascript. Try adding this code to the HEAD section of your page:
<cfajaxproxy bind="javaScript:showName({userID})">
<script type="text/javascript">
showName = function(strUserId) {
document.getElementById("someID").innerHTML = strUserId.split('<')[0];
}
</script>