Module System - cynchro/OldSchoolFrontFrame GitHub Wiki

Module System

A module is the primary building block of an OLS application. Each route maps to exactly one module folder.


File layout

modules/clientes/
├── clientes.html    # Template (required)
├── clientes.js      # defineModule() call (required)
├── clientes.css     # Scoped styles (optional)
└── services/        # Data/API functions (optional)
    └── clientes.service.js

The folder name must match the value used in initApp({ routes }).


defineModule(definition)

import { defineModule } from '../../framework/module/module.js';

defineModule({
  state,
  methods,
  mounted,
  destroyed,
  css,
});

state

A function (or object) that returns the module's initial reactive state.

state: () => ({
  users: [],
  loading: false,
  query: '',
}),

Use a function (not a plain object) so each module instance gets a fresh copy.


methods

An object of functions available in the template as event handlers and callable within mounted/destroyed.

Each method receives ctx as the first argument.

methods: {
  async loadUsers(ctx) {
    ctx.state.loading = true;
    ctx.state.users = await fetchUsers();
    ctx.state.loading = false;
  },

  deleteUser(ctx, event) {
    const id = event.target.dataset.id;
    ctx.state.users = ctx.state.users.filter(u => u.id !== Number(id));
  },
},

mounted(ctx)

Called after the module's HTML is injected and bindings are attached. Use this for initial data loading.

mounted(ctx) {
  ctx.methods.loadUsers(ctx);
},

ctx.methods gives you access to the module's own methods from inside lifecycle hooks.


destroyed(ctx)

Called before the module is removed from the DOM. Use this for cleanup (timers, subscriptions, etc.).

destroyed(ctx) {
  clearInterval(ctx._pollInterval);
},

css

Set to true to load <name>.css alongside the module. Styles are scoped to the module's root element.

defineModule({
  css: true,
  state: () => ({}),
});

Module context (ctx)

Property Description
ctx.state Module's reactive state (Proxy)
ctx.root The module's root DOM element
ctx.store Global store — see Global Store
ctx.config Loaded app configuration
ctx.props.params URL route parameters (e.g. { id: '42' })
ctx.methods The module's methods object, for calling methods from hooks

Full example

// modules/clientes/clientes.js
import { defineModule } from '../../framework/module/module.js';
import { getClientes, deleteCliente } from './services/clientes.service.js';

defineModule({
  state: () => ({
    clientes: [],
    loading: false,
    error: null,
  }),

  methods: {
    async cargar(ctx) {
      ctx.state.loading = true;
      ctx.state.error = null;
      try {
        ctx.state.clientes = await getClientes();
      } catch (e) {
        ctx.state.error = e.message;
      } finally {
        ctx.state.loading = false;
      }
    },

    async eliminar(ctx, event) {
      const id = Number(event.target.dataset.id);
      await deleteCliente(id);
      ctx.state.clientes = ctx.state.clientes.filter(c => c.id !== id);
    },
  },

  mounted(ctx) {
    ctx.methods.cargar(ctx);
  },
});
<!-- modules/clientes/clientes.html -->
<div>
  <h2>Clientes</h2>

  <p data-bind="error" style="color:red"></p>

  <ul data-for="clientes" data-template="cliente-tpl"></ul>

  <template id="cliente-tpl">
    <li>
      <span data-bind="nombre"></span>
      <button data-click="eliminar" data-id="">Eliminar</button>
    </li>
  </template>
</div>

Lifecycle order

Route change detected
  → destroyed() on previous module
  → HTML removed from DOM
  → New HTML injected into mount point
  → Bindings attached
  → Events attached
  → mounted() on new module
⚠️ **GitHub.com Fallback** ⚠️