### Ledap React Hooks - Model Integration (JavaScript)
Source: https://context7.com/ethercap/ledap/llms.txt
This snippet demonstrates how to integrate Ledap models with React components using custom hooks like useLedapModel and useModelEvent. It covers setting and getting model values, handling form input changes, validation, and displaying model attributes and errors.
```javascript
import React from 'react';
import { useLedapModel, useModelEvent } from 'ledap/react';
import { Model } from 'ledap';
function UserForm({ userData }) {
const model = new Model();
model.load(userData);
const { setValue, getValue, updateView, model: boundModel } = useLedapModel(model);
const { loaded } = useModelEvent(model, 'username');
const handleChange = (attr) => (e) => {
setValue(attr, e.target.value);
// Model is updated and component re-renders
};
const handleSubmit = () => {
if (!model.validate()) {
console.log('Validation errors:', model.getErrors());
updateView(); // Force re-render to show errors
return;
}
// Submit valid data
axios.post('/api/users', {
username: getValue('username'),
email: getValue('email')
});
};
if (!loaded) {
return
Loading...
;
}
return (
);
}
```
--------------------------------
### Ledap: Create Custom Validators for Model Fields
Source: https://context7.com/ethercap/ledap/llms.txt
Shows how to define custom validation rules for model attributes in Ledap using the `Model` and `ValidatorFactory` classes. It includes examples of built-in validators like `required`, `string`, `number`, `regex`, `compare`, and `dict`, as well as dynamic validator addition. Requires `ledap`.
```javascript
import { Model, ValidatorFactory } from 'ledap';
// Define a model with custom rules
class UserModel extends Model {
rules() {
return {
username: {
required: {},
string: { min: 3, max: 20 }
},
email: {
required: {},
email: {}
},
age: {
number: { min: 18, max: 120 },
required: {}
},
password: {
required: {},
regex: {
pattern: /^(?=.*[A-Za-z])(?=.*\d)[A-Za-z\d]{8,}$/,
message: 'Password must be at least 8 characters with letters and numbers'
}
},
confirmPassword: {
compare: {
compareAttribute: 'password',
operator: '===',
message: 'Passwords must match'
}
},
role: {
dict: {
list: ['admin', 'user', 'guest'],
message: 'Invalid role selected'
}
}
};
}
attributeLabels() {
return {
username: 'Username',
email: 'Email Address',
age: 'Age',
password: 'Password',
confirmPassword: 'Confirm Password',
role: 'User Role'
};
}
attributeHints() {
return {
username: 'Choose a unique username',
password: 'At least 8 characters with letters and numbers'
};
}
}
// Usage
const userModel = new UserModel();
userModel.load({
username: 'jo',
email: 'invalid-email',
age: 15,
password: 'weak',
confirmPassword: 'different',
role: 'superuser'
});
if (!userModel.validate()) {
console.log(userModel.getErrors());
// {
// username: ['Username must be at least 3 characters'],
// email: ['Invalid email format'],
// age: ['Age must be at least 18'],
// password: ['Password must be at least 8 characters...'],
// confirmPassword: ['Passwords must match'],
// role: ['Invalid role selected']
// }
}
// Validate specific attributes
userModel.validate(['username', 'email']);
// Add validators dynamically
userModel.addValidator('username', 'regex', {
pattern: /^[a-zA-Z0-9_]+$/,
message: 'Username can only contain letters, numbers, and underscores'
});
```
--------------------------------
### Model Creation and Validation in JavaScript
Source: https://context7.com/ethercap/ledap/llms.txt
Demonstrates how to create a Model instance, load data with extended metadata including labels, hints, and validation rules, and perform validation. It covers accessing attribute metadata and handling validation errors manually.
```javascript
import { Model } from 'ledap';
// Create a new model instance
const model = new Model();
// Load data with extended metadata (labels, hints, rules)
model.load({
username: {
value: 'john_doe',
label: 'Username',
hint: 'Enter your username',
rules: [
{
type: 'required',
options: { message: 'Username is required' }
},
{
type: 'string',
options: { min: 3, max: 20, message: 'Username must be 3-20 characters' }
}
]
},
email: {
value: 'john@example.com',
label: 'Email Address',
rules: [
{ type: 'required' },
{ type: 'email', options: { message: 'Invalid email format' } }
]
},
age: 25
});
// Get attribute metadata
console.log(model.getAttributeLabel('username')); // "Username"
console.log(model.getAttributeHint('username')); // "Enter your username"
console.log(model.isRequired('email')); // true
// Validate the model
if (!model.validate()) {
console.log(model.getErrors()); // { username: ['Username is required'], ... }
console.log(model.getFirstError('email')); // First error for email field
}
// Manual error handling
model.addError('username', 'This username is already taken');
model.clearErrors('username');
console.log(model.hasErrors()); // false if no errors
```
--------------------------------
### WebDataProvider for List Data Management in JavaScript
Source: https://context7.com/ethercap/ledap/llms.txt
Illustrates the usage of WebDataProvider for managing paginated list data, including AJAX loading, search filters, and sorting. It shows how to configure the HTTP request, manipulate pagination, update parameters, and perform local operations on the data.
```javascript
import { App, WebDataProvider } from 'ledap';
// Global configuration (set once in your app)
App.config({
webDpConfig: {
httpRequest: function(httpOptions, success, failure) {
axios.request(httpOptions).then(response => {
success(response.data);
}).catch(error => {
failure(error);
});
}
}
});
// Create a data provider instance
const dp = new WebDataProvider({
httpOptions: {
url: '/api/users',
params: { status: 'active' }
},
primaryKey: 'id', // For deduplication
timeWait: 600 // Debounce time in ms
});
// Load initial data
dp.refresh();
// Access loaded data
console.log(dp.models); // Array of Model instances
console.log(dp.isLoading); // true during AJAX request
console.log(dp.isLoad); // true after first successful load
// Pagination controls
dp.changePage(2); // Load page 2
dp.nextPage(); // Load next page
dp.prePage(); // Load previous page
console.log(dp.pager.currentPage); // Current page number
console.log(dp.pager.hasPre()); // Has previous page?
console.log(dp.pager.hasNext()); // Has next page?
// Mobile pull-to-refresh scenarios
dp.refresh('header'); // Pull down - reset to page 1
dp.refresh('footer'); // Pull up - load next page and append
// Update search filters
dp.setParams({ status: 'inactive', keyword: 'john' }); // Resets to page 1
dp.setParams({ status: 'all' }, true, false); // Keep current page
// Sorting
dp.toggleSort('created_at'); // Toggle between ASC and DESC
dp.setSort('name,-created_at'); // name ASC, created_at DESC
console.log(dp.isSortAsc('name')); // true
console.log(dp.isSortDesc('created_at')); // true
// Local operations
dp.remove(0); // Remove first item
dp.localSort(); // Sort models locally by current sort rules
```
--------------------------------
### Configure Global HTTP Requests and DataProvider Settings with Ledap
Source: https://context7.com/ethercap/ledap/llms.txt
Sets up global configurations for HTTP requests, including adding common headers like Authorization, and defines default settings for WebDataProvider. It also shows how to create models and data providers using App helpers and access built-in libraries like lodash and axios.
```javascript
import { App } from 'ledap';
import axios from 'axios';
// Configure global settings once at app initialization
App.config({
// Global HTTP request handler
request: function(httpOptions, success, fail) {
// Add common headers
httpOptions.headers = {
...httpOptions.headers,
'Authorization': 'Bearer ' + localStorage.getItem('token'),
'X-Requested-With': 'XMLHttpRequest'
};
axios.request(httpOptions)
.then(response => {
if (response.data.code === 0) {
success(response.data.data);
} else {
fail(response.data);
}
})
.catch(error => {
console.error('Request failed:', error);
fail({ message: error.message, error });
});
},
// WebDataProvider default configuration
webDpConfig: {
primaryKey: 'id',
timeWait: 600,
httpRequest: function(httpOptions, success, fail) {
// Can override request handler specifically for data providers
App.request(httpOptions, success, fail);
}
},
// Global validators
validators: {
// Custom validator implementations
}
});
// Create models using App helpers
const userData = { username: 'john', email: 'john@example.com' };
const userModel = App.getModel(userData);
// Create data providers using App helpers
const userListDp = App.getWebDp({
httpOptions: { url: '/api/users' }
});
userListDp.refresh();
// Access built-in libraries
const merged = App.lodash.merge({}, obj1, obj2);
const response = await App.axios.get('/api/data');
```
--------------------------------
### React Hooks: Integrate Ledap DataProvider for List Management
Source: https://context7.com/ethercap/ledap/llms.txt
Demonstrates how to use `useLedapDataProvider` and `useDpEvent` React hooks to manage and display data fetched from a Ledap data provider. It covers initialization, parameter setting for searching, and handling loading states. Requires `react` and `ledap/react`.
```javascript
import React, { useEffect } from 'react';
import { useLedapDataProvider, useDpEvent } from 'ledap/react';
import { WebDataProvider } from 'ledap';
function UserList() {
const dpConfig = {
httpOptions: { url: '/api/users' },
httpRequest: (httpOptions, success, failure) => {
axios.request(httpOptions)
.then(response => success(response.data))
.catch(error => failure(error));
},
primaryKey: 'id'
};
const { isLoading, data, setParams, isLoad } = useLedapDataProvider(dpConfig);
const handleSearch = (keyword) => {
setParams({ keyword }, true, true); // Reload and reset to page 1
};
const handlePageChange = (page) => {
dp.changePage(page);
};
if (!isLoad) {
return