Model.Template.tsx Implementation Guide

Model.Template.tsx files are client-side React components that define the form structure for creating/editing models in Akan.js applications. They serve as reusable form blueprints with built-in state management, validation, and internationalization support.
File Location and Naming Convention
Template files follow a consistent naming pattern and directory structure:
1
2// Standard path pattern
3{apps,libs}/*/lib/[model]/[Model].Template.tsx
4
5// Examples:
6libs/game/lib/map/Map.Template.tsx
7apps/lu/lib/feeling/Feeling.Template.tsx
8        
Basic Structure and Component Patterns
Component Organization
1
2// Single-file pattern
3export const General = () => { /* main form */ }
4export const Advanced = () => { /* advanced fields */ }
5
6// Multi-file pattern (recommended)
7[Model].Template/
8├─ General.tsx
9├─ Sections/
10│  ├─ BasicInfo.tsx
11│  ├─ ContactDetails.tsx
12        
State Initialization
1
2useEffect(() => {
3  if (id) {
4    // Load existing data
5    void st.do.load[Model](id);
6  }
7  
8  return () => {
9    // Reset form on unmount
10    st.do.reset[Model]Form();
11  };
12}, [id]);
13        
Field Types and Form Components
Text

Standard text input field

1<Field.Text />
TextArea

Multi-line text input

1<Field.TextArea />
Select

Dropdown selection input

1<Field.Select />
ToggleSelect

Toggleable options selector

1<Field.ToggleSelect />
Img

Image upload component

1<Field.Img sliceName='model' />
Parent

Relationship selector

1<Field.Parent sliceName='relatedModel' />
Complex Field Example
1
2<Field.List
3  label={l.field("map", "spawnPositions")}
4  value={form.spawnPositions}
5  onAdd={() => st.do.addSpawnPosition(defaultPosition)}
6  renderItem={(position, idx) => (
7    <div className="flex gap-4">
8      <Field.Text
9        value={position.key}
10        onChange={(v) => st.do.writeOnMap(["spawnPositions", idx, "key"], v)}
11      />
12      <Field.DoubleNumber
13        value={position.position}
14        onChange={(v) => st.do.writeOnMap(["spawnPositions", idx, "position"], v)}
15      />
16    </div>
17  )}
18/>
19        
Form Validation Approaches
Field-Level Validation
1
2<Field.Email
3  value={form.email}
4  validate={(v) => /^[^\s@]+@[^\s@]+\.[^\s@]+$/.test(v)}
5  errorMessage="Invalid email format"
6  required
7/>
8        
required:boolean:false

Makes field mandatory

1required
min/max:number:-

Number range constraints

1min={0} max={100}
validate:function:-

Custom validation function

1validate={(v) => isValidEmail(v)}
errorMessage:string:-

Custom error message

1errorMessage="Invalid format"
Form Layout Patterns
Responsive Grid Layout
1
2<div className="grid grid-cols-1 gap-4 md:grid-cols-2">
3  <Field.Text label="First Name" />
4  <Field.Text label="Last Name" />
5  <Field.Email label="Email" className="md:col-span-2" />
6</div>
7        
Conditional Sections
1
2{form.type === "business" && (
3  <section className="mt-6 p-4 bg-base-200 rounded-lg">
4    <h3 className="text-lg font-semibold mb-3">Business Details</h3>
5    <Field.Text label="Company Name" />
6    <Field.Text label="Tax ID" />
7  </section>
8)}
9        
State Management
Store Action Patterns
1
2// Simple field update
3st.do.setNameOn[Model](value);
4
5// Nested field update
6st.do.writeOn[Model](["address", "city"], value);
7
8// List operations
9st.do.addItemOn[Model](newItem);
10st.do.removeItemOn[Model](index);
11        
Performance Optimization
Memoization Techniques
1
2const FormSection = React.memo(({ fields }) => {
3  // Component implementation
4});
5
6// Debounced inputs
7import { useDebounce } from "@akanjs/hooks";
8const [input, setInput] = useState("");
9const debouncedInput = useDebounce(input, 300);
10        
Accessibility
Accessible Form Patterns
1
2// Proper labeling
3<label htmlFor="email-field">Email</label>
4<input id="email-field" type="email" />
5
6// Error messaging
7<div role="alert" aria-live="polite">
8  {error && <p className="text-error">{error}</p>}
9</div>
10        
Common Patterns
Reusable Form Sections
1
2// AddressSection.tsx
3export const AddressSection = () => (
4  <div className="space-y-3">
5    <Field.Text label="Street" />
6    <Field.Text label="City" />
7    <Field.Text label="Zip Code" />
8  </div>
9);
10        
Form Submission
Submission Workflow
1
2const handleSubmit = async () => {
3  try {
4    // Validate form
5    const errors = validateForm(form);
6    if (Object.keys(errors).length) throw errors;
7    
8    // Submit data
9    if (id) await st.do.updateModel(id, form);
10    else await st.do.createModel(form);
11    
12    // Redirect on success
13    router.push("/success");
14  } catch (error) {
15    // Handle API errors
16    st.do.setFormErrors(error);
17  }
18};
19        
Troubleshooting
Form Not Updating

Verify Zustand store actions are properly connected

1st.do.setNameOn[Model]
Type Mismatches

Ensure constant types match form state

1ProjectInput vs ProjectForm
Missing Translations

Verify dictionary keys and scopes

1l.field("model", "name")
Best Practices
1. Use consistent spacing (gap-4, mb-4) 2. Group related fields visually 3. Place important fields above the fold 4. Provide clear validation feedback 5. Meet WCAG 2.1 accessibility standards
Released under the MIT License
Official Akan.js Consulting onAkansoft
Copyright © 2025 Akan.js. All rights reserved.
System managed bybassman