Other frameworks
React-Native
import * as React from "react";
import { View, StyleSheet, Image, Text } from "react-native";
import { useState } from "react";
const arabicToEnglish = (string) => {
// removing non numeric characters
const number = string.replace(/[^0-9Ù -Ù©.,]+/g, "");
// replacing arabic numbers with english numbers
return number.replace(/[\u0660-\u0669]/g, (digit) =>
"٠١٢٣٤٥٦٧٨٩".indexOf(digit)
);
};
export default function MyComponent(props) {
const [number, setNumber] = useState(() => "");
return (
<>
<View>
<Text>This input changes arabic numbers to english numbers! </Text>
</View>
<View />
<View
value={number}
onInput={(event) => setNumber(arabicToEnglish(event.target.value))}
inputMode={props.inputMode ?? "numeric"}
/>
</>
);
}
Qwik
// GENERATED BY MITOSIS
import { Fragment, component$, h, useStore } from "@builder.io/qwik";
const arabicToEnglish = (string) => {
// removing non numeric characters
const number = string.replace(/[^0-9Ù -Ù©.,]+/g, "");
// replacing arabic numbers with english numbers
return number.replace(/[\u0660-\u0669]/g, (digit) =>
"٠١٢٣٤٥٦٧٨٩".indexOf(digit)
);
};
export const MyComponent = component$((props) => {
const state = useStore({ number: "" });
return (
<Fragment>
<label>This input changes arabic numbers to english numbers! </label>
<br></br>
<input
value={state.number}
onInput$={(event) =>
(state.number = arabicToEnglish(event.target.value))
}
inputMode={props.inputMode ?? "numeric"}
></input>
</Fragment>
);
});
export default MyComponent;
Web Components
export interface MyComponentProps {
inputMode?: "numeric" | "tel" | "decimal";
}
const arabicToEnglish = (string) => {
// removing non numeric characters
const number = string.replace(/[^0-9Ù -Ù©.,]+/g, "");
// replacing arabic numbers with english numbers
return number.replace(/[\u0660-\u0669]/g, (digit) =>
"٠١٢٣٤٥٦٧٨٩".indexOf(digit)
);
};
/**
* Usage:
*
* <my-component></my-component>
*
*/
class MyComponent extends HTMLElement {
get _root() {
return this.shadowRoot || this;
}
constructor() {
super();
const self = this;
this.state = { number: "" };
if (!this.props) {
this.props = {};
}
this.componentProps = ["inputMode"];
// used to keep track of all nodes created by show/for
this.nodesToDestroy = [];
// batch updates
this.pendingUpdate = false;
// Event handler for 'input' event on input-my-component-1
this.onInputMyComponent1Input = (event) => {
this.state.number = arabicToEnglish(event.target.value);
this.update();
};
if (undefined) {
this.attachShadow({ mode: "open" });
}
}
destroyAnyNodes() {
// destroy current view template refs before rendering again
this.nodesToDestroy.forEach((el) => el.remove());
this.nodesToDestroy = [];
}
connectedCallback() {
this.getAttributeNames().forEach((attr) => {
const jsVar = attr.replace(/-/g, "");
const regexp = new RegExp(jsVar, "i");
this.componentProps.forEach((prop) => {
if (regexp.test(prop)) {
const attrValue = this.getAttribute(attr);
if (this.props[prop] !== attrValue) {
this.props[prop] = attrValue;
}
}
});
});
this._root.innerHTML = `
<label>This input changes arabic numbers to english numbers!</label>
<br />
<input
data-el="input-my-component-1"
data-dom-state="MyComponent-input-my-component-1"
/>`;
this.pendingUpdate = true;
this.render();
this.onMount();
this.pendingUpdate = false;
this.update();
}
onMount() {}
onUpdate() {}
update() {
if (this.pendingUpdate === true) {
return;
}
this.pendingUpdate = true;
this.render();
this.onUpdate();
this.pendingUpdate = false;
}
render() {
// grab previous input state
const preStateful = this.getStateful(this._root);
const preValues = this.prepareHydrate(preStateful);
// re-rendering needs to ensure that all nodes generated by for/show are refreshed
this.destroyAnyNodes();
this.updateBindings();
// hydrate input state
if (preValues.length) {
const nextStateful = this.getStateful(this._root);
this.hydrateDom(preValues, nextStateful);
}
}
getStateful(el) {
const stateful = el.querySelectorAll("[data-dom-state]");
return stateful ? Array.from(stateful) : [];
}
prepareHydrate(stateful) {
return stateful.map((el) => {
return {
id: el.dataset.domState,
value: el.value,
active: document.activeElement === el,
selectionStart: el.selectionStart,
};
});
}
hydrateDom(preValues, stateful) {
return stateful.map((el, index) => {
const prev = preValues.find((prev) => el.dataset.domState === prev.id);
if (prev) {
el.value = prev.value;
if (prev.active) {
el.focus();
el.selectionStart = prev.selectionStart;
}
}
});
}
updateBindings() {
this._root
.querySelectorAll("[data-el='input-my-component-1']")
.forEach((el) => {
el.value = this.state.number;
el.removeEventListener("input", this.onInputMyComponent1Input);
el.addEventListener("input", this.onInputMyComponent1Input);
el.setAttribute("inputMode", this.props.inputMode ?? "numeric");
});
}
// Helper to render content
renderTextNode(el, text) {
const textNode = document.createTextNode(text);
if (el?.scope) {
textNode.scope = el.scope;
}
if (el?.context) {
textNode.context = el.context;
}
el.after(textNode);
this.nodesToDestroy.push(el.nextSibling);
}
}
customElements.define("my-component", MyComponent);
Angular
import { NgModule } from "@angular/core";
import { CommonModule } from "@angular/common";
import { Component, Input } from "@angular/core";
export interface MyComponentProps {
inputMode?: "numeric" | "decimal" | "tel";
}
const arabicToEnglish = (string) => {
// removing non numeric characters
const number = string.replace(/[^0-9Ù -Ù©.,]+/g, "");
// replacing arabic numbers with english numbers
return number.replace(/[\u0660-\u0669]/g, (digit) =>
"٠١٢٣٤٥٦٧٨٩".indexOf(digit)
);
};
@Component({
selector: "my-component, MyComponent",
template: `
<ng-container>
<label>This input changes arabic numbers to english numbers!</label>
<br />
<input
[attr.value]="number"
(input)="number = arabicToEnglish($event.target.value)"
[attr.inputMode]='inputMode ?? "numeric"'
/>
</ng-container>
`,
})
export class MyComponent {
arabicToEnglish = arabicToEnglish;
@Input() inputMode: MyComponentProps["inputMode"];
number = "";
}
@NgModule({
declarations: [MyComponent],
imports: [CommonModule],
exports: [MyComponent],
})
export class MyComponentModule {}
Swift
import SwiftUI
import JavaScriptCore
final class UpdateTracker: ObservableObject {
@Published var value = 0;
func update() {
value += 1
}
}
struct MyComponent: View {
@ObservedObject var updateTracker = UpdateTracker()
private var jsContext = JSContext()
@State private var input1: String = ""
func eval(code: String) -> JSValue! {
return jsContext?.evaluateScript(code)
}
func setComputedState() {
input1 = eval(code: "state.number").toString()!
}
init() {
let jsSource = """
const state = new Proxy(
{ number: "" },
{
set: (target, key, value) => {
const returnVal = Reflect.set(target, key, value);
update();
return returnVal;
},
}
);
"""
jsContext?.exceptionHandler = { context, exception in
print("JS Error: \(exception!)")
}
let updateRef = updateTracker.update
let updateFn : @convention(block) () -> Void = { updateRef() }
jsContext?.setObject(updateFn, forKeyedSubscript: "update" as NSString)
jsContext?.evaluateScript(jsSource)
}
var body: some View {
VStack {
VStack() {Text("This input changes arabic numbers to english numbers!")}
VStack() {}
TextField("", text: $input1)
}
.onAppear {
setComputedState()
}
}
}
Flutter
import 'package:flutter/material.dart';
class MyComponent extends StatefulWidget {
const MyComponent({Key? key}) : super(key: key);
@override
State<MyComponent> createState() => _MyComponentState();
}
class _MyComponentState extends State<MyComponent> {
String arabicToEnglish(String input) {
final numericValue = input.replaceAll(RegExp(r'[^Ù -Ù©0-9.,]+'), "");
return numericValue.replaceAllMapped(RegExp(r'[\u0660-\u0669]'),
(match) => "٠١٢٣٤٥٦٧٨٩".indexOf(match[0].toString()).toString());
}
final TextEditingController _controller = TextEditingController();
// ٠١٢٣٤٥٦٧٨٩0123456
@override
void dispose() {
_controller.dispose();
super.dispose();
}
@override
Widget build(BuildContext context) {
return MaterialApp(
home: Scaffold(
body: Center(
child: SizedBox(
width: MediaQuery.of(context).size.width / 3,
child: TextField(
controller: _controller,
onChanged: (val) {
final newInput = arabicToEnglish(_controller.text);
_controller.value = _controller.value.copyWith(
text: newInput,
selection: TextSelection.collapsed(offset: newInput.length),
);
},
decoration: const InputDecoration(
border: OutlineInputBorder(),
hintText: 'Enter a search term'
),
),
),
),
),
);
}
}