npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2025 – Pkg Stats / Ryan Hefner

formue-crud

v0.2.17

Published

1. [Overview](#overview) 2. [Installation & Setup](#installation--setup) 3. [Core Components](#core-components) 4. [Architecture](#architecture) 5. [API Reference](#api-reference) 6. [Usage Examples](#usage-examples) 7. [Advanced Features](#advanced-featu

Downloads

598

Readme

Formue CRUD - Complete Documentation

Table of Contents

  1. Overview
  2. Installation & Setup
  3. Core Components
  4. Architecture
  5. API Reference
  6. Usage Examples
  7. Advanced Features
  8. Customization
  9. Best Practices
  10. Troubleshooting

Overview

Formue CRUD is a comprehensive Vue.js 3 framework designed for building data-driven applications with advanced CRUD operations. It provides a complete solution for managing data tables, forms, filtering, sorting, pagination, and user permissions.

Key Features

  • Dynamic Data Tables: Tabulator.js integration with advanced sorting and filtering
  • Form Management: Vueform integration for dynamic form generation
  • Permission System: Role-based access control for CRUD operations
  • Advanced Filtering: Multi-field filtering with save/load functionality
  • Export Capabilities: Excel export with customizable data
  • Responsive Design: Mobile-friendly interface with Tailwind CSS
  • State Management: Pinia-based reactive state management
  • Real-time Updates: Event-driven architecture for live data updates

Dependencies

{
  "@vueform/vueform": "^1.5.3",
  "@vueuse/core": "^10.4.0",
  "axios": "^1.6.2",
  "lodash": "^4.17.21",
  "mitt": "^3.0.1",
  "pinia": "^2.1.6",
  "qs": "^6.11.2",
  "tabulator-tables": "^6.2.1",
  "vue": "^3.3.4"
}

Installation & Setup

1. Install the Package

npm install formue-crud

2. Import and Configure

import { createApp } from 'vue'
import { createPinia } from 'pinia'
import FormueCrud from 'formue-crud'

const app = createApp(App)
app.use(createPinia())
app.use(FormueCrud)

3. Basic Setup

<template>
  <MCrud
    :fields="fields"
    :options="options"
    :route="route"
    :hidden-actions="hiddenActions"
    @mounted="onMounted"
  />
</template>

<script setup>
import { MCrud } from 'formue-crud'

const fields = {
  name: {
    type: 'text',
    title: 'Name',
    placeholder: 'Enter name'
  },
  email: {
    type: 'email',
    title: 'Email',
    placeholder: 'Enter email'
  }
}

const options = {
  formMode: 'dialog' // or 'tab'
}

const route = {
  index: '/api/users',
  create: '/api/users',
  update: '/api/users',
  delete: '/api/users'
}

const hiddenActions = [] // ['create', 'update', 'delete', 'show']
</script>

Core Components

MCrud (Main Component)

The primary component that orchestrates all CRUD operations.

Props:

  • fields: Object defining form fields and table columns
  • options: Configuration object for behavior customization
  • structure: Additional form structure configuration
  • hiddenActions: Array of actions to hide from UI
  • tableOptions: Tabulator-specific options
  • route: API endpoints configuration
  • dir: Text direction ('ltr' or 'rtl')

Events:

  • mounted: Emitted when component is fully initialized

MTable

Advanced data table component with sorting, filtering, and pagination.

Features:

  • Column sorting with visual indicators
  • Row selection with batch operations
  • Custom column visibility
  • Loading states and empty data handling
  • Responsive design

MFilter

Dynamic filtering system with save/load functionality.

Features:

  • Field-specific filter types (text, date, select)
  • Multiple filter combinations
  • Save/load filter presets
  • Real-time filter application

FormCore

Dynamic form generation component using Vueform.

Features:

  • Auto-generated forms from field definitions
  • Validation integration
  • Conditional field display
  • Multi-step form support

MButtonBox

Action toolbar with permissions-based button visibility.

Features:

  • Create, export, reload, column selection buttons
  • Permission-based visibility
  • Batch operation support
  • Search integration

Architecture

State Management (Pinia Store)

The framework uses a dynamic store system for managing application state:

// Store Structure
{
  mainKey: '',           // Current data model key
  form: {},             // Current form data
  items: {},            // Data collections by key
  query: '',            // Additional query parameters
  routes: {},           // API endpoints
  fields: [],           // Field definitions
  options: [],          // Configuration options
  filters: [],          // Active filters
  loadings: {},         // Loading states
  dialog: false,        // Dialog visibility
  structure: {},        // Form structure
  paginations: {},      // Pagination data
  searchParam: '',      // Search query
  isEditing: false,     // Edit mode flag
  selected: new Set([]) // Selected items
}

Event System

Uses mitt.js for event communication between components:

import { emitter } from '@/helpers/emitter'

// Listen to events
emitter.listen('saveForm', () => {
  // Handle form save
})

// Emit events
emitter.event('alert', { text: 'Success!', color: 'green' })

Permission System

Role-based access control for UI elements:

import { usePermission } from '@/composables/usePermission'

const { can } = usePermission()

// Check permissions
if (can('create')) {
  // Show create button
}

API Reference

Field Types

Text Field

{
  type: 'text',
  title: 'Field Name',
  placeholder: 'Enter value',
  required: true,
  validation: 'required|min:3'
}

Select Field

{
  type: 'select',
  title: 'Category',
  items: [
    { value: 1, text: 'Option 1' },
    { value: 2, text: 'Option 2' }
  ],
  'label-prop': 'text',
  'value-prop': 'value',
  search: true
}

Date Field

{
  type: 'date',
  title: 'Date',
  placeholder: 'Select date',
  format: 'YYYY-MM-DD'
}

Store Actions

Data Operations

// Load items
store.loadItems(key, page)

// Add new item
store.addItem(data)

// Edit existing item
store.editItem(data)

// Remove item
store.remove(id)

// Reload data
store.reloadData()

Filtering

// Apply filters
store.loadItems()

// Clear all filters
store.filters = []

// Generate filter query
store.convertToFilterForm()

Composables

useDynamicStore

import { useDynamicStore } from '@/composables/useDynamicStore'

const store = useDynamicStore('MyStore')

usePermission

import { usePermission } from '@/composables/usePermission'

const { can, setPermissions } = usePermission()

setPermissions(['create', 'update', 'delete'])

useFetch

import { useFetch } from '@/composables/useFetch'

const { get, post, patch, remove } = useFetch()

const response = await get('/api/users')

Usage Examples

Basic CRUD Setup

<template>
  <MCrud :fields="userFields" :route="userRoutes" :options="{ formMode: 'dialog' }" />
</template>

<script setup>
const userFields = {
  name: {
    type: 'text',
    title: 'Full Name',
    required: true,
    showIn: ['create', 'edit', 'list']
  },
  email: {
    type: 'email',
    title: 'Email Address',
    required: true
  },
  role: {
    type: 'select',
    title: 'Role',
    items: [
      { value: 'admin', text: 'Administrator' },
      { value: 'user', text: 'Regular User' }
    ]
  },
  created_at: {
    type: 'date',
    title: 'Created Date',
    showIn: ['list']
  }
}

const userRoutes = {
  index: '/api/users',
  create: '/api/users',
  update: '/api/users',
  delete: '/api/users'
}
</script>

Custom Field with API Integration

const productFields = {
  category_id: {
    type: 'select',
    title: 'Category',
    items: async (search) => {
      const response = await axios.get(`/api/categories?search=${search}`)
      return response.data.data
    },
    'label-prop': 'name',
    'value-prop': 'id',
    search: true
  }
}

Advanced Filtering Setup

const advancedFields = {
  status: {
    type: 'select',
    title: 'Status',
    items: [
      { value: 'active', text: 'Active' },
      { value: 'inactive', text: 'Inactive' }
    ],
    filterItems: [
      { value: 'active', text: 'Active Only' },
      { value: 'inactive', text: 'Inactive Only' }
    ]
  },
  created_at: {
    type: 'date',
    title: 'Created Date',
    filterable: true
  }
}

Custom Actions

<template>
  <MCrud :fields="fields" :route="route" @mounted="setupCustomActions">
    <template #extra>
      <CustomActionButtons />
    </template>
  </MCrud>
</template>

<script setup>
import { emitter } from '@/helpers/emitter'

const setupCustomActions = () => {
  emitter.listen('customAction', (data) => {
    // Handle custom action
    console.log('Custom action triggered:', data)
  })
}
</script>

Advanced Features

Batch Operations

// Select multiple items
store.selected.add(itemId)

// Batch delete
const selectedIds = Array.from(store.selected)
store.remove(selectedIds)

// Custom batch operation
emitter.listen('batchUpdate', (data) => {
  const selectedItems = store.mainItems.filter((item) => store.selected.has(item.id))
  // Process selected items
})

Export Functionality

// Export filtered data
function exportData() {
  const exportUrl = store.generateQuery() + '/export'
  window.open(exportUrl)
}

// Custom export format
function exportCustom() {
  const selectedData = store.mainItems.filter((item) => store.selected.has(item.id))
  // Process and export selected data
}

Custom Column Rendering

const customFields = {
  avatar: {
    type: 'image',
    title: 'Avatar',
    formatter: (value) => {
      return `<img src="${value}" alt="Avatar" class="w-8 h-8 rounded-full">`
    }
  },
  status: {
    type: 'select',
    title: 'Status',
    formatter: (value) => {
      const color = value === 'active' ? 'green' : 'red'
      return `<span class="px-2 py-1 text-xs rounded bg-${color}-100 text-${color}-800">${value}</span>`
    }
  }
}

Conditional Field Display

const conditionalFields = {
  type: {
    type: 'select',
    title: 'User Type',
    items: [
      { value: 'individual', text: 'Individual' },
      { value: 'company', text: 'Company' }
    ],
    onChange: (value, formData) => {
      // Show/hide fields based on selection
      if (value === 'company') {
        // Show company-specific fields
      }
    }
  },
  company_name: {
    type: 'text',
    title: 'Company Name',
    showIf: (formData) => formData.type === 'company'
  }
}

Customization

Styling

The framework uses Tailwind CSS for styling. You can customize the appearance by:

  1. Override CSS Classes:
.fc-header-icon-btn {
  @apply bg-blue-500 hover:bg-blue-600 text-white;
}

.fc-table-row:hover {
  @apply bg-blue-50;
}
  1. Custom Themes:
const customOptions = {
  theme: {
    primary: 'blue',
    secondary: 'gray',
    success: 'green',
    danger: 'red'
  }
}

Custom Components

<!-- CustomField.vue -->
<template>
  <div class="custom-field">
    <label>{{ field.title }}</label>
    <input v-model="modelValue" :type="field.type" :placeholder="field.placeholder" />
  </div>
</template>

<script setup>
import { registerFields } from 'formue-crud'

registerFields({
  'custom-field': CustomField
})
</script>

API Response Format

Expected API response format:

{
  "data": [
    {
      "id": 1,
      "name": "John Doe",
      "email": "[email protected]"
    }
  ],
  "current_page": 1,
  "last_page": 5,
  "total": 50,
  "per_page": 10
}

Best Practices

1. Field Organization

// Group related fields
const userFields = {
  // Personal Information
  first_name: { type: 'text', title: 'First Name', group: 'personal' },
  last_name: { type: 'text', title: 'Last Name', group: 'personal' },

  // Contact Information
  email: { type: 'email', title: 'Email', group: 'contact' },
  phone: { type: 'tel', title: 'Phone', group: 'contact' }
}

2. Performance Optimization

// Use lazy loading for large datasets
const lazyFields = {
  category: {
    type: 'select',
    items: async (search) => {
      // Only load when needed
      if (search.length < 2) return []
      return await fetchCategories(search)
    }
  }
}

3. Error Handling

// Global error handling
emitter.listen('error', (error) => {
  console.error('CRUD Error:', error)
  // Show user-friendly message
  showNotification(error.message, 'error')
})

4. Validation

const validatedFields = {
  email: {
    type: 'email',
    title: 'Email',
    rules: ['required', 'email'],
    messages: {
      required: 'Email is required',
      email: 'Please enter a valid email'
    }
  }
}

Troubleshooting

Common Issues

1. Data Not Loading

// Check API endpoint
console.log('API URL:', store.generateRoute())

// Verify response format
axios.get('/api/users').then((response) => {
  console.log('Response structure:', response.data)
})

2. Form Validation Errors

// Debug form validation
emitter.listen('validation-error', (errors) => {
  console.log('Validation errors:', errors)
})

3. Permission Issues

// Check permission setup
const { permissions } = usePermission()
console.log('Available permissions:', permissions.value)

4. Filter Not Working

// Debug filter generation
console.log('Filter query:', store.convertToFilterForm())

Debug Mode

Enable debug mode for detailed logging:

const debugOptions = {
  debug: true,
  logging: {
    api: true,
    events: true,
    state: true
  }
}

Performance Monitoring

// Monitor API calls
axios.interceptors.request.use((request) => {
  console.time(`API: ${request.url}`)
  return request
})

axios.interceptors.response.use((response) => {
  console.timeEnd(`API: ${response.config.url}`)
  return response
})

Migration Guide

From Version 0.1.x to 0.2.x

  1. Update field definitions:
// Old format
const fields = [{ field: 'name', type: 'text', title: 'Name' }]

// New format
const fields = {
  name: { type: 'text', title: 'Name' }
}
  1. Update event listeners:
// Old format
this.$emit('update', data)

// New format
emitter.event('update', data)

Contributing

Development Setup

git clone https://github.com/your-repo/formue-crud
cd formue-crud
npm install
npm run dev

Build Process

npm run build
npm run type-check
npm run lint

Testing

npm run test
npm run test:unit
npm run test:e2e

Version: 0.1.77
Last Updated: 2024
License: MIT

For more information, visit the GitHub repository or contact the maintainers.