### 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 (
{model.hasErrors('username') && ( {model.getFirstError('username')} )}
{model.hasErrors('email') && ( {model.getFirstError('email')} )}
); } ``` -------------------------------- ### 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
Initializing...
; } return (
{isLoading &&
Loading...
} handleSearch(e.target.value)} /> {data && data.map((model, index) => ( ))}
ID Username Email
{model.id} {model.username} {model.email}
{/* Pagination controls would go here */}
); } // Alternative: Direct event subscription function UserListWithEvents({ dp }) { const { loading, models, isLoad } = useDpEvent(dp); useEffect(() => { dp.refresh(); }, []); return (
{loading ? 'Loading...' : `${models.length} users loaded`}
); } ``` -------------------------------- ### Ledap DataProvider Sorting: Client and Server Side Source: https://context7.com/ethercap/ledap/llms.txt Demonstrates how to manage sorting operations for list data using Ledap's DataProvider. It covers server-side sorting via AJAX requests and client-side sorting of loaded models, including toggling, setting explicit sorts, checking sort states, and custom sorting functions. ```javascript import { DataProvider, WebDataProvider } from 'ledap'; // Server-side sorting (triggers new AJAX request) const dp = new WebDataProvider({ httpOptions: { url: '/api/products' }, httpRequest: (opts, success, fail) => { axios.request(opts).then(r => success(r.data)).catch(fail); } }); // Initial load dp.refresh(); // Toggle sort on click (ASC -> DESC -> ASC) dp.toggleSort('price'); // Single sort by price dp.toggleSort(['name', 'price']); // Multi-column sort // Set explicit sort dp.setSort('name,-price,created_at'); // name ASC, price DESC, created_at ASC dp.setSort({ name: DataProvider.SORT_ASC, price: DataProvider.SORT_DESC }); // Check current sort state if (dp.isSortAsc('price')) { console.log('Sorting by price ascending'); } if (dp.isSortDesc('created_at')) { console.log('Sorting by created_at descending'); } // Get sort as string for API console.log(dp.sort); // "name,-price,created_at" // Trigger reload with new sort dp.setSort('name', true, false); // Reload without changing page // Client-side sorting (no AJAX, sorts loaded models) dp.localSort(); // Sort by current sort rules // Custom sort function dp.sortModels('price', true, (value1, value2, isAsc) => { // Custom comparison logic if (value1 === value2) return 0; const comparison = value1 > value2 ? 1 : -1; return isAsc ? comparison : -comparison; }); // In a table header component function TableHeader({ attribute, label, dp }) { const handleSort = () => { dp.toggleSort(attribute); dp.refresh(); // Reload with new sort }; return ( {label} {dp.isSortAsc(attribute) && ' ↑'} {dp.isSortDesc(attribute) && ' ↓'} ); } ``` -------------------------------- ### Ledap Model Events - Reactive Data Flow (JavaScript) Source: https://context7.com/ethercap/ledap/llms.txt This snippet demonstrates how to listen to various model lifecycle events in Ledap, such as before load, load, after load, before validate, and after validate. It shows how to trigger these events and manage one-time listeners and removal of listeners. ```javascript import { Model } from 'ledap'; const model = new Model(); // Listen to load events model.on(Model.EVENT_BEFORELOAD, (model) => { console.log('About to load data into model'); }); model.on(Model.EVENT_LOAD, (model, key, value) => { console.log(`Loading ${key} = ${value}`); }); model.on(Model.EVENT_AFTERLOAD, (model) => { console.log('Model loaded successfully'); console.log(model); }); // Listen to validation events model.on(Model.EVENT_BEFORE_VALIDATE, (model) => { console.log('Starting validation'); }); model.on(Model.EVENT_AFTER_VALIDATE, (model) => { if (model.hasErrors()) { console.log('Validation failed:', model.getErrors()); } else { console.log('Validation passed'); } }); // Trigger by loading data model.load({ username: 'john', email: 'john@example.com' }); // One-time event listener model.once(Model.EVENT_AFTERLOAD, (model) => { console.log('This runs only once'); }); // Remove event listener const callback = (model) => console.log('Loaded'); model.on(Model.EVENT_AFTERLOAD, callback); model.off(Model.EVENT_AFTERLOAD, callback); ``` -------------------------------- ### Ledap DataProvider Events - AJAX Lifecycle (JavaScript) Source: https://context7.com/ethercap/ledap/llms.txt This snippet illustrates how to monitor the AJAX request lifecycle using Ledap's WebDataProvider. It covers events like EVENT_BEFOREGETDATA and EVENT_AFTERGETDATA to manage loading indicators, handle request parameters, and process responses or errors. ```javascript import { WebDataProvider } from 'ledap'; const dp = new WebDataProvider({ httpOptions: { url: '/api/products' }, httpRequest: function(httpOptions, success, failure) { axios.request(httpOptions).then(response => { success(response.data); }).catch(error => { failure(error); }); } }); // Before AJAX request dp.on(WebDataProvider.EVENT_BEFOREGETDATA, (dp, { dp: dataProvider }) => { console.log('Loading started...'); console.log('Request params:', dp.httpOptions.params); // Show loading spinner document.getElementById('spinner').style.display = 'block'; }); // After AJAX request (success or failure) dp.on(WebDataProvider.EVENT_AFTERGETDATA, (dp, { dp: dataProvider, success, data }) => { console.log('Loading finished'); document.getElementById('spinner').style.display = 'none'; if (success) { console.log('Data loaded successfully:', dp.models.length, 'items'); console.log('Total pages:', dp.pager.totalPages); } else { console.error('Failed to load data:', data); alert('Error loading data: ' + data.message); } }); // Modify request before sending dp.on(WebDataProvider.EVENT_BEFOREGETDATA, (dp) => { // Add authentication token dp.httpOptions.headers = { 'Authorization': 'Bearer ' + localStorage.getItem('token') }; }); // Load data (triggers events) dp.refresh(); ``` === COMPLETE CONTENT === This response contains all available snippets from this library. No additional content exists. Do not make further requests.