Looking to create an enum for some regex to store in my application to allow for code reuse.
Eg:
export enum Regex {
ONE_DANK_REGEX = /^[dank]+$/g,
FIVE_OUT_OF_SEVEN = /^[meme]{5,7}$/g
}
But:
By not using string literals, I get the TS90010 error: Type RegExpis not assignable to type Regex.
By using string literals, I can't use these in a pattern attribute on my inputs
Eg.
<input ngModel="..." pattern="{{FIVE_OUT_OF_SEVEN}}" .../>
Is this the right way of going about doing this?
You cannot assign a RegExp to an enum, an enum can either be numeric or string-based.
So when it comes to storing the RegExp you have two options:
Option A - store the RegExp as string in an enum
enum RegExpEnum {
ONE_DANK_REGEX = "^[dank]+$",
FIVE_OUT_OF_SEVEN = "^[meme]{5,7}$"
}
Option B - store the RegExp in a class/variable
class RegexClass {
public static readonly ONE_DANK_REGEX = /^[dank]+$/g;
public static readonly FIVE_OUT_OF_SEVEN = /^[meme]{5,7}$/g;
}
In both ways you need to get a reference to the containing enum or class in your component. Which can be achieved by assigning it to a local variable.
#Component({ ... })
public class MyComponent {
availableRegex = RegExpEnum; // or RegexClass
}
Then you can access it in the html part of your component.
<input [(ngModel)]="name" [pattern]="availableRegex.ONE_DANK_REGEX"/>
DEMO
Enum will support only strings and Number.
If you wanted to store regular expressions, you need to use static class
export class RegularExpression
{
public static ALPHA_CHARACTERS: RegExp = /([^A-Za-z])+/g;
}
Usage
'Your_* Name'.replace(RegularExpression.ALPHA_CHARACTERS, '');
Prefer the option A mentioned on the currently accepted answer and use it as below the code:
export enum Regex {
ONE_DANK_REGEX = "^[dank]+$",
FIVE_OUT_OF_SEVEN = "^[meme]{5,7}$",
}
public readonly regOne = new RegExp(Regex.ONE_DANK_REGEX, "g");
This gives some flexibility when create the regular expression object.
Related
With an enum like say:
public enum Authors
{
KirkPatrick,
JasmineLliki,
NatashaKakuvi
}
Now using this helper method I can easily get the corresponding List<string> values:
public class EnumHelper<T> where T : Enum
{
public static List<string> ToList() => Enum.GetNames(typeof(T)).ToList();
}
My desired output would be something like:
new List<string>() {"Kirk Patrick", "Jasmine Lliki", "Natasha Kakuvi"};
instead of
new List<string>() {"KirkPatrick", "JasmineLliki", "NatashaKakuvi"};
that the method outputs.
It seems that you are trying to, effectively, assign string values to Enums.
If that is your intention, check out this StackOverflow question, may be one of the cases there will be helpful.
If you want to proceed with your current Enums instead, you can try using answers from this question to add spaces in a string with capital letters.
Regex-validated strings are not a thing in Typescript.
Still, the need is here: in my case, immutable strings that are validated against a Regex for UUIDv4, URIs, Email, etc.
I've got something close but I'm not happy with it, I have to rewrite the regex access and test function every time.
Here's what I have so far:
An abstract class "ValidatedString"
export interface Predicate<T> { (x: T): boolean }
export abstract class ValidatedString {
#str: string
constructor(str: string, predicate: Predicate<string>, className?: string) {
if (!predicate(str)) throw new Error(`Invalid ${className ? className : 'format'}: ${str}`)
this.#str = str
}
get length() { return this.#str.length }
toString = () => this.#str
}
And classes that implement it:
import { v4 } from 'uuid'
/** Regex-validated string class for UUIDv4 */
export class UUIDv4 extends ValidatedString {
constructor(str: string) { super(str, UUIDv4.test, 'UUID v4') }
static readonly regex = /^[0-9a-f]{8}-[0-9a-f]{4}-4[0-9a-f]{3}-[89ab][0-9a-f]{3}-[0-9a-f]{12}$/i
/** Test if a string matches the class predicate */
static test = (str: string) => UUIDv4.regex.test(str)
/** Generate a random string that matches the class predicate */
static generate = () => new UUIDv4(v4())
}
/** Regex-validated string class for UUIDv4 */
export class ApiVersion extends ValidatedString {
constructor(str: string) { super(str, ApiVersion.test, 'API version') }
static readonly regex = /^[0-9]+\.[0-9]+(\.[0-9]+)?[a-z]*$/
/** Test if a string matches the class predicate */
static test = (str: string) => ApiVersion.regex.test(str)
}
Despite my efforts to eliminate the obvious redundancies between the inheriting classes, I have failed: one cannot use a protected static field in the abstract class, so I'm left with rewriting the test function and the regex access every time.
I can't offer a generic signature for the generate function either.
I would like to basically build UUIDv4 as a ValidatedString with UUIDv4 regex and offer a regex access,test method and optional generate function signature.
Do you see how to implement this properly? Is there a way to build a type from a static parameter such as a Regex literal?
Say I define the following types:
type queueParams = {
durable: bool
};
class type amqpChannelT = [#bs] {
pub assertQueue: string => queueParams => Js.Promise.t(unit);
};
Then calling the following:
channel##assertQueue("exampleQueue", {"durable": bool});
Results in:
This has type:
{. "durable": bool}
But somewhere wanted:
queueParams (defined as
How can I pass the right type of thing? Why is the thing I'm passing not a record? And what is the meaning of that dot notation?
ReasonML interprets these two differently:
let jsObject = {"durable": true};
let reasonRecord = {durable: true};
Basically, wrapping keys with double-quotes is a short-hand notation for the special Javascript object type Js.t('a) - which is currently deprecated.
You can play around with an example here. Note how the two types are treated differently when converted to Javascript.
Read more about the deprecated syntax here:
https://bucklescript.github.io/docs/en/object-deprecated
I have a custom template ~/Views/Shared/EditorTemplate/String.cshtml and it seems to be causing the Exception:
The model item passed into the dictionary is of type 'Proj.Models.EnumType', but this dictionary requires a model item of type 'System.String'.
It seems to only happen to Enums. It also goes away if I remove the template. The template doesn't seem to cause it, I don't think it's even making it that far. I can put ANYTHING in there and the exception is the same.
So... can I not use an #Html.EditorFor with a model with an enum if I have a custom template?
Some context:
Model:
namespace Proj.Models
{
public enum EnumType
{
A = 0,
B = 1,
C = 2,
}
public class Mod
{
[Required]
public String Name;
[Required]
public EnumType Letter;
}
}
View:
#model Proj.Models.Mod
#Html.EditorFor(m=>m) // Exception happens here
Here is what I found to work for me.
In your template, make sure you declare your model as nullable enum type. Then, in code, check to see if it has a value and based on that do appropriate formatting.
#inherits System.Web.Mvc.WebViewPage<Proj.Models.EnumType?>
#{
Proj.Models.EnumType v = Model.HasValue ? Model.Value : {*some-default-value*};
#Html.{*Your-formatter-here*};
}
I've got a class that's meant to validate input fields to make sure the value is always a decimal. I've tested the regex here: http://livedocs.adobe.com/flex/3/html/help.html?content=validators_7.html, and it looks like it does the right thing, but in my app, I can't seem to get it to match to a number format.
Class Definition:
public class DecimalValidator {
//------------------------------- ATTRIBUTES
public var isDecimalValidator:RegExpValidator;
//------------------------------- CONSTRUCTORS
public function DecimalValidator() {
isDecimalValidator = new RegExpValidator();
isDecimalValidator.expression = "^-?(\d+\.\d*|\.\d+)$";
isDecimalValidator.flags = "g";
isDecimalValidator.required = true;
isDecimalValidator.property = "text";
isDecimalValidator.triggerEvent = FocusEvent.FOCUS_OUT;
isDecimalValidator.noMatchError = "Float Expected";
}
}
Setting the source here:
public function registerDecimalInputValidator(inputBox:TextInput, valArr:Array):void {
// Add Validators
var dValidator:DecimalValidator = new DecimalValidator();
dValidator.isDecimalValidator.source = inputBox;
dValidator.isDecimalValidator.trigger = inputBox;
inputBox.restrict = "[0-9].\\.\\-";
inputBox.maxChars = 10;
valArr.push(dValidator.isDecimalValidator);
}
And Calling it here:
registerDecimalInputValidator(textInput, validatorArr);
Where textInput is an input box created earlier.
Clearly I'm missing something simple yet important, but I'm not entirely sure what! Any help would be much appreciated.
I don't know ActionScript, but as far as I know it's an ECMAScript language, so I expect you need to escape the backslashes if you use a string to define a regex:
isDecimalValidator.expression = "^-?(\\d+\\.\\d*|\\.\\d+)$";
This strikes me as wrong; but I can't quite put my finger on it. For your DecimalValidator instead of composing a RegExpValidator; why not extend it?
public class DecimalValidator extend RegExpValidator{
//------------------------------- CONSTRUCTORS
public function DecimalValidator() {
super()
this.expression = "^-?(\d+\.\d*|\.\d+)$";
this.flags = "g";
this.required = true;
this.property = "text";
this.triggerEvent = FocusEvent.FOCUS_OUT;
this.noMatchError = "Float Expected";
}
}
How when is the registerdecimalInputValidator called? I have a slight worry about the Validator instance is a local variable to a method instead of 'global' property to the function.
protected var dValidator:DecimalValidator = new DecimalValidator();
public function registerDecimalInputValidator(inputBox:TextInput):void {
dValidator.isDecimalValidator.source = inputBox;
dValidator.isDecimalValidator.trigger = inputBox;
}
I'm not sure why you are setting restrictions on the TextInput in the registerDecimalInputValidator method; that should be done when you create the method (in createChildren() or possibly in response to public properties changing, in commitProperties . It is also not obvious to me what the validatorArr does. If you're expecting to access values inside the validatorArrray outside of the method; it would often be a common practice to return that value from the method. Without looking it up; I'm not sure if Arrays are passed by value or reference in Flex.