Skip to content
This repository was archived by the owner on Oct 16, 2024. It is now read-only.
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 0 additions & 1 deletion examples/react/develop/multieditor-ts/.env
Original file line number Diff line number Diff line change
@@ -1,2 +1 @@
SKIP_PREFLIGHT_CHECK=true
BROWSER=chrome
7 changes: 5 additions & 2 deletions examples/react/develop/multieditor-ts/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -11,21 +11,24 @@
"react-dom": "^16.13.1",
"react-router-dom": "^5.2.0",
"react-scripts": "3.4.3",
"typescript": "^3.9.7"
"typescript": "^3.9.7",
"yup": "^0.32.9"
},
"devDependencies": {
"@testing-library/react": "^9.3.2",
"@testing-library/user-event": "^7.1.2",
"@types/node": "^12.0.0",
"@types/react": "^16.9.0",
"@types/react-dom": "^16.9.0",
"@types/react-router-dom": "^5.1.5"
"@types/react-router-dom": "^5.1.5",
"source-map-explorer": "^2.5.2"
},
"scripts": {
"start": "react-scripts start",
"build": "react-scripts build",
"test": "react-scripts test",
"eject": "react-scripts eject",
"analyze": "yarn run build && source-map-explorer 'build/static/js/*.js'",
"install:dev:agile": "yalc add @agile-ts/core @agile-ts/react @agile-ts/multieditor & yarn install",
"install:prod:agile": "yalc add @agile-ts/core @agile-ts/react @agile-ts/multieditor & yarn install"
},
Expand Down
81 changes: 47 additions & 34 deletions examples/react/develop/multieditor-ts/src/App.tsx
Original file line number Diff line number Diff line change
@@ -1,41 +1,45 @@
import React from "react";
import "./App.css";
import ErrorMessage from "./components/ErrorMessage";
import { useAgile } from "@agile-ts/react";
import { signUpEditor } from "./core/signUpEditor";
import { generateColor, generateId } from "./core/utils";
import React from 'react';
import './App.css';
import ErrorMessage from './components/ErrorMessage';
import { useAgile } from '@agile-ts/react';
import { signUpEditor } from './core/signUpEditor';
import { generateColor, generateId } from './core/utils';

let renderCount = 0;

const App = () => {
useAgile(signUpEditor.deps);

renderCount++;

return (
<form>
<h1>Sign Up</h1>
<label>First Name:</label>
<input
onChange={(e) => signUpEditor.setValue("firstName", e.target.value)}
value={signUpEditor.getValueById("firstName")}
onChange={(e) => signUpEditor.setValue('firstName', e.target.value)}
defaultValue={signUpEditor.getItemInitialValue('firstName')}
/>
<ErrorMessage error={signUpEditor.getStatus("firstName")?.message} />
<ErrorMessage error={signUpEditor.getStatus('firstName')?.message} />

<label>Last Name:</label>
<input
onChange={(e) =>
signUpEditor.setValue("lastName", e.target.value, {
signUpEditor.setValue('lastName', e.target.value, {
background: false,
})
}
value={signUpEditor.getValueById("lastName")}
defaultValue={signUpEditor.getItemInitialValue('lastName')}
value={signUpEditor.getItemValue('lastName')}
/>
<ErrorMessage error={signUpEditor.getStatus("lastName")?.message} />
<ErrorMessage error={signUpEditor.getStatus('lastName')?.message} />

<label>Image</label>
<div
style={{ display: "flex", flexDirection: "row", alignItems: "center" }}
>
style={{ display: 'flex', flexDirection: 'row', alignItems: 'center' }}>
<div
style={{
backgroundColor: signUpEditor.getValueById("image")?.color,
backgroundColor: signUpEditor.getItemValue('image')?.color,
width: 100,
height: 100,
borderRadius: 100,
Expand All @@ -45,64 +49,73 @@ const App = () => {
style={{ marginLeft: 50 }}
onClick={(event) => {
signUpEditor.setValue(
"image",
'image',
{
id: generateId(),
color: generateColor(),
},
{ background: false }
);
event.preventDefault();
}}
>
}}>
Reset Image
</button>
</div>
<ErrorMessage error={signUpEditor.getStatus("image")?.message} />
<ErrorMessage error={signUpEditor.getStatus('image')?.message} />

<label>Gender</label>
<select
defaultValue={""}
onChange={(e) => signUpEditor.setValue("gender", e.target.value)}
>
<option value={""}>Select...</option>
defaultValue={''}
onChange={(e) => signUpEditor.setValue('gender', e.target.value)}>
<option value={''}>Select...</option>
<option value="male">Male</option>
<option value="female">Female</option>
</select>
<ErrorMessage error={signUpEditor.getStatus("gender")?.message} />
<ErrorMessage error={signUpEditor.getStatus('gender')?.message} />

<label>Username</label>
<input
onChange={(e) => signUpEditor.setValue("userName", e.target.value)}
onChange={(e) => signUpEditor.setValue('userName', e.target.value)}
defaultValue={signUpEditor.getItemInitialValue('userName')}
/>
<ErrorMessage error={signUpEditor.getStatus("userName")?.message} />
<ErrorMessage error={signUpEditor.getStatus('userName')?.message} />

<label>Email</label>
<input onChange={(e) => signUpEditor.setValue("email", e.target.value)} />
<ErrorMessage error={signUpEditor.getStatus("email")?.message} />
<input
onChange={(e) => signUpEditor.setValue('email', e.target.value)}
defaultValue={signUpEditor.getItemInitialValue('email')}
/>
<ErrorMessage error={signUpEditor.getStatus('email')?.message} />

<label>Age</label>
<input onChange={(e) => signUpEditor.setValue("age", e.target.value)} />
<ErrorMessage error={signUpEditor.getStatus("age")?.message} />
<input
onChange={(e) =>
signUpEditor.setValue('age', e.target.value, { background: false })
}
defaultValue={signUpEditor.getItemInitialValue('age')}
value={signUpEditor.getItemValue('age')}
/>
<ErrorMessage error={signUpEditor.getStatus('age')?.message} />

<label>About you</label>
<textarea
onChange={(e) => signUpEditor.setValue("aboutYou", e.target.value)}
onChange={(e) => signUpEditor.setValue('aboutYou', e.target.value)}
defaultValue={signUpEditor.getItemInitialValue('aboutYou')}
/>
<ErrorMessage error={signUpEditor.getStatus("aboutYou")?.message} />
<ErrorMessage error={signUpEditor.getStatus('aboutYou')?.message} />

<button
style={{ marginLeft: 50 }}
onClick={async (event) => {
event.preventDefault();
console.log(signUpEditor);
await signUpEditor.submit();
}}
>
}}>
Submit
</button>
<p>Is Modified: {signUpEditor.isModified.toString()}</p>
<p>Is Valid: {signUpEditor.isValid.toString()}</p>
<p>Render Count: {renderCount}</p>
</form>
);
};
Expand Down
88 changes: 60 additions & 28 deletions examples/react/develop/multieditor-ts/src/core/signUpEditor.ts
Original file line number Diff line number Diff line change
@@ -1,24 +1,42 @@
import { createMultieditor, Validator } from '@agile-ts/multieditor';
import { generateColor, generateId, isLight } from './utils';
import {
agileResolver,
createMultieditor,
isEmail,
isNumber,
isRequired,
isString,
matchesRegex,
maxLength,
maxNumber,
minLength,
minNumber,
yupResolver,
} from '@agile-ts/multieditor';
import { globalBind } from '@agile-ts/core';
import * as Yup from 'yup';
import { generateColor, generateId, isLight } from './utils';
import { assignSharedLogger, createLogger, Logger } from '@agile-ts/logger';

export const isValidNameValidator = new Validator()
.required()
.string()
.min(2)
.max(10)
.matches(/^([^0-9]*)$/, 'No Numbers allowed!');
assignSharedLogger(createLogger({ level: Logger.level.DEBUG }));

export const isValidNameValidator = agileResolver(
isRequired,
isString,
minLength(2),
maxLength(10),
matchesRegex(/^([^0-9]*)$/, 'No Numbers allowed!')
);

export const signUpEditor = createMultieditor((editor) => ({
data: {
initialData: {
id: 'myCoolId',
firstName: 'Jeff',
lastName: '',
gender: undefined,
userName: '',
email: '',
aboutYou: '',
age: undefined,
aboutYou: '',
image: {
id: generateId(),
color: generateColor(),
Expand All @@ -27,39 +45,53 @@ export const signUpEditor = createMultieditor((editor) => ({
onSubmit: async (preparedData) => {
alert(JSON.stringify(preparedData));
},
validateMethods: {
validationSchema: {
// Outsourced Validator
firstName: isValidNameValidator,
lastName: isValidNameValidator,

// Validation with Yup
lastName: yupResolver(
Yup.string()
.required()
.min(2)
.max(10)
.matches(/^([^0-9]*)$/, 'No Numbers allowed!')
),

// Outsourced Validator with additional validation method
userName: isValidNameValidator
.clone()
.copy()
.addValidationMethod(async (key, value, editor) => {
const isValid = value === 'Jeff';
if (!isValid)
editor.setStatus(key, 'error', 'Sry only the name Jeff is allowed!');
return isValid;
}),
email: editor.Validator().required().string().email(),
aboutYou: editor
.Validator()
.required()
.string()
.min(10)

// Validation with Agile
email: agileResolver(isRequired, isString, isEmail),

age: agileResolver(isRequired, isNumber, minNumber(18), maxNumber(100)),

// Validation with Yup and Agile
aboutYou: agileResolver(isRequired)
.append(yupResolver(Yup.string().min(10)))
.addValidationMethod(async (key, value, editor) => {
const isValid = typeof value === 'string' && !value.includes('fuck');
if (!isValid)
editor.setStatus(key, 'error', 'The word fuck is not allowed!');
return isValid;
}),
age: editor.Validator().required().number().min(18).max(100),
gender: editor.Validator().required(),
image: editor
.Validator()
.required()
.addValidationMethod(async (key, value, editor) => {

gender: agileResolver(isRequired),

image: agileResolver(isRequired).addValidationMethod(
async (key, value, editor) => {
const isValid = isLight(value.color);
if (!isValid) editor.setStatus(key, 'error', 'The Image is to dark!');
return isValid;
}),
}
),
},
computeMethods: {
lastName: (value) => {
Expand All @@ -70,8 +102,8 @@ export const signUpEditor = createMultieditor((editor) => ({
},
},
fixedProperties: ['id'],
reValidateMode: 'afterFirstSubmit',
reValidateMode: 'onChange',
}));

// For better debugging
globalBind('__core__', { isValidNameValidator, signUpEditor });
globalBind('__core__', { signUpEditor });
Loading