I'm developing a web application using Angular 6. I have a question:
I'm creating a custom input component (for text input) such as:
#Component({
selector: 'input-text',
templateUrl: './input-text.component.html'
]
})
export class InputTextComponent {
#Input() pattern?: string;
}
I would like a user can insert a regular expression for the validation of the input field, in this way:
<input-text pattern="^[a-z0-9_-]{8,15}$"></input-text>
The template of my component is defined like this:
<input type="text" [attr.pattern]="pattern"/>
Unfortunately I know absolutely nothing about regular expressions.
I would like to do two things:
1 - Create a method that checks the validity of the regular expression and changes the visual style.
2 - Make sure that if the input (with a pattern field) is inserted into a form, the attribute form.valid remains false until the expression is valid.
Thanks for your help!
Check regex validity
You can simply catch exceptions thrown by the RegExp constructor when instanciating it.
try {
const regex = new RegExp(pattern);
} catch (error) {
// If it goes here, then the regex model is not correct
console.error(error.message)
}
Change the visual style
You can simply use the ngClass attribute to change your input style.
If you enter the catch statement, set a style variable to change the class like so
private hasBadInput: boolean;
// [...]
catch (error) {
hasBadInput= true;
}
Then apply a specific class in that case:
<input-text [ngClass]="{'yourErrorClass': hasBadInput}"><input-text>
Form validity
You did well using [attr.pattern], the form should automatically consider the entered pattern. You should try your form with a hard written regex before, and then use the input one.
Follow this official guideline to create Angular 2+ forms.
Related
I have a textfield controller which matches a RegExp whenever the user type it in. For example the typed in string may be "#jack and #jill went up the hill". The following code will match the taghandles and list them.
Firstly the TextField:
TextField(
controller: myController,
)
Which listens for each input into the text field and passes it to a function:
myController.addListener(_matchTextToRegexp);
The function then matches taghandles ie. '#jack' '#jill'
_matchTextToRegexp() {
String value = myController.text;
RegExp regExpTaghandle = RegExp(r"\B#+([\w]+)\b");
Iterable matches = regExpTaghandle.allMatches(value);
matches.forEach((match) {
tagHandle = value.substring(match.start, match.end);
_callToAction(tagHandle);
}
}
The issue is that i want to call a function _callToAction() and pass it the taghandle (for example it could pass the substring/taghandle to a typeahead suggestion dropdown menu as the user types it in - similar functionality to a tweet mention). This code works for one taghandle, but if the users continues inputting text (or adds multiple taghandles) into the form it will keep matching the first taghandle even though the user has typed passed the first taghandle.
So how do you distinguish between multiple taghandles as they are dynamically typed in?
I need a custom validator to ban a specific list of banned words from a textarea field.
I need exactly this type of implementation, I know that it's not logically correct to let the user type part of a query but it's exactly what I need.
I tried with a regExp but it has a strange behaviour.
My RegExp
/(drop|update|truncate|delete|;|alter|insert)+./gi
my Validator
export function forbiddenWordsValidator(sqlRe: RegExp): ValidatorFn {
return (control: AbstractControl): { [key: string]: any } | null => {
const forbidden = sqlRe.test(control.value);
return forbidden ? { forbiddenSql: { value: control.value } } : null;
};
}
my formControl:
whereCondition: new FormControl("", [
Validators.required,
forbiddenWordsValidator(this.BAN_SQL_KEYWORDS)...
It works only in certain cases and I don't understand why does the same string works one time and doesn't work if i delete a char and rewrite it or sometimes if i type a whitespace the validator returns ok.
There are several issues here:
The global g modifier leads to unexpected alternated results when used in RegExp#test and similar methods that move the regex index after a valid match, it must be removed
. at the end requires any 1 char other than line break char, hence it must be removed.
Use
/drop|update|truncate|delete|;|alter|insert/i
Or, to match the words as whole words use
/\b(?:drop|update|truncate|delete|alter|insert)\b|;/i
This way, insert in insertion and drop in dropout won't get "caught" (=matched).
See the regex demo.
it's not a great idea to give such power to the user
I want to make a custom validator that should check the input Url is valid or not.
I want to use the following regex that I tested in expresso, but comes off invalid when used in typescript (the compiler fails to parse it):
(((ht|f)tp(s?))\://)?((([a-zA-Z0-9_\-]{2,}\.)+[a-zA-Z]{2,})|((?:(?:25[0-5]|2[0-4]\d|[01]\d\d|\d?\d)(?(\.?\d)\.)){4}))(:[a-zA-Z0-9]+)?(/[a-zA-Z0-9\-\._\?\,\'/\\\+&%\$#\=~]*)?
The above url checks for optional http:\\\ and also will validate an Ip address
The following url's should be valid :
192.1.1.1
http://abcd.xyz.in
https://192.1.1.126
abcd.jhjhj.lo
The following url's should be invalid:
192.1
http://hjdhfjfh
168.18.5
Kindly assist
The forward slashes / are not escaped in the regex.
What is valid or invalid in Javascript is valid or invalid in Typescript and vice-versa.
There may be another option for you, that relies on the URL class. The idea is to try converting the string into a URL object. If that fails, the string does not contain a valid URL.
public isAValidUrl(value: string): boolean {
try {
const url = new URL(value);
return isValid(url.pathname);
} catch (TypeError) {
return false;
}
}
isValid(value: URL): boolean {
// you may do further tests here, e.g. by checking url.pathname
// for certain patterns
}
Alternatively to returning a boolean you may return the created URL or null instead of a boolean or - if that exists in JavaScript or TypeScript: something like an Optional<URL>. You should adapt the method's name then, of course.
Is it possible to use the flowVariable inside wildcard or expression filter directly.
I need to stop the flow based on the flow Variable value.
Example: My flow Variable name keyValue have the value like customer/feed/h26/h56 in this 'h26/h56' should set dynamically but customer/feed is constant always. I need to set my filter only after '/feed/' if it contain any characters.
<flow name="testFlow1" doc:name="testFlow1">
<file:inbound-endpoint responseTimeout="10000" doc:name="File" path="c:/in"/>
.......( Many component)
<set-variable variableName="keyValue" value="#[customer/feed/h26/h56]" doc:name="Variable"/>
.......( Many component)
<message-filter doc:name="Message">
<wildcard-filter pattern="customer/feed/+*" caseSensitive="true"/>
</message-filter>
</flow>
Used + in pattern to check whether it contain one or more characters.
Also I used expression filter, not sure how to use flow Variable inside the filter expression. Could you please help me on this.
I don't want to use property filter.
Use expression filter instead, and since your expression is simple just use the startsWith method of String.
for example
<expression-filter expression="flowVars.keyValue.startsWith('customer/feed/')" doc:name="Expression"/>
this will allow messages
First of all, you can't use wildcard-filter on flowVars directly because it applies a wildcard pattern to the message payload. Here is the implementation excerpt from the org.mule.routing.filters.WildcardFilter class
public boolean accept(MuleMessage message) {
try {
return accept(message.getPayloadAsString());
} catch (Exception e) {
logger.warn("An exception occurred while filtering", e);
return false;
}
}
So it is clear that the WildcardFilter converts the payload to a String and applies the filter.
Also, in the case of regex-filter, it applies a regex pattern to the message payload. Here is an implementation excerpt from the org.mule.routing.filters.RegExFilter
public boolean accept(MuleMessage message) {
try {
return accept(message.getPayloadAsString());
} catch (Exception e) {
throw new IllegalArgumentException(e);
}
}
Now coming to your question, you can very well use expression-filter as suggested by Tyrone Villaluna. But you may want to include the expression in start and end signs like ^customer/feed/.+$
And so
<expression-filter expression="flowVars.keyValue.matches('^customer/feed/.+$')" />
How do i write a regular expression which accepts only value "1" in the textbox
and it should not accept zero or greter than "1"
if (theTextBoxValue == "1") {
// accept
} else {
// reject
}
You don't need regex for this simple task. And, if you only accept "1" in a user input, why provide such an input to the user at all?
/^1$/
… but for a "Must be this value, exactly this value, and nothing but this value" test, you would be much better off with a simple string comparison.
/^1$/ but a simple == "1" will be enough in most languages (or .equals("1")).
I saw your previous question (using the jquery validationEngine), and I was intrigued by it so I started looking.
The problem with using a funcCall (as you were trying in the old post) is that the function is called without any context (has no arguments, and has this == window), so you can't tell which input field is being validated.(I solved this with a trick - see example & comments linked below).
Another solution I found was using regex(as you are trying now).
This is the entry you have to add to the languages file:
"isOne":{
"regex":"/^1$/",
"alertText":"* Only '1' is valid [regex]"
}
This is how you use it on the input field:
<input type="text" class="validate[custom[isOne]]">
And this is how you start the validation engine:
$('#form').validationEngine({
validationEventTriggers:"change"
});
You can view a working example using both function and regex here
Don't think you want to use regex for this.
Pattern: ^1$