Разработка кастомных виджетов Appsmith

Наша компания занимается разработкой, поддержкой и обслуживанием сайтов любой сложности. От простых одностраничных сайтов до масштабных кластерных систем построенных на микро сервисах. Опыт разработчиков подтвержден сертификатами от вендоров.

Разработка и обслуживание любых видов сайтов:

Информационные сайты или веб-приложения
Сайты визитки, landing page, корпоративные сайты, онлайн каталоги, квиз, промо-сайты, блоги, новостные ресурсы, информационные порталы, форумы, агрегаторы
Сайты или веб-приложения электронной коммерции
Интернет-магазины, B2B-порталы, маркетплейсы, онлайн-обменники, кэшбэк-сайты, биржи, дропшиппинг-платформы, парсеры товаров
Веб-приложения для управления бизнес-процессами
CRM-системы, ERP-системы, корпоративные порталы, системы управления производством, парсеры информации
Сайты или веб-приложения электронных услуг
Доски объявлений, онлайн-школы, онлайн-кинотеатры, конструкторы сайтов, порталы предоставления электронных услуг, видеохостинги, тематические порталы

Это лишь некоторые из технических типов сайтов, с которыми мы работаем, и каждый из них может иметь свои специфические особенности и функциональность, а также быть адаптированным под конкретные потребности и цели клиента

Предлагаемые услуги
Показано 1 из 1 услугВсе 2065 услуг
Разработка кастомных виджетов Appsmith
Средняя
~3-5 рабочих дней
Часто задаваемые вопросы

Наши компетенции:

Этапы разработки

Последние работы

  • image_website-b2b-advance_0.png
    Разработка сайта компании B2B ADVANCE
    1262
  • image_web-applications_feedme_466_0.webp
    Разработка веб-приложения для компании FEEDME
    1171
  • image_websites_belfingroup_462_0.webp
    Разработка веб-сайта для компании БЕЛФИНГРУПП
    874
  • image_ecommerce_furnoro_435_0.webp
    Разработка интернет магазина для компании FURNORO
    1094
  • image_crm_enviok_479_0.webp
    Разработка веб-приложения для компании Enviok
    831
  • image_bitrix-bitrix-24-1c_fixper_448_0.png
    Разработка веб-сайта для компании ФИКСПЕР
    851

Разработка кастомных виджетов Appsmith

Appsmith — open-source конкурент Retool с аналогичной моделью кастомизации. Custom Widget в Appsmith — это тоже iframe с postMessage, но API немного отличается. Если Retool использует npm-пакет с хуками, Appsmith предоставляет глобальный объект appsmith прямо в iframe-контексте.

Механизм Custom Widget

Кастомный виджет в Appsmith получает данные через appsmith.model, отправляет события через appsmith.triggerEvent и обновляет состояние через appsmith.updateModel. Всё это синхронизируется с основным приложением через postMessage без необходимости устанавливать SDK.

Виджет подключается как HTML-страница — можно писать vanilla JS прямо в редакторе Appsmith или задать внешний URL с собранным бандлом.

Встроенный редактор vs внешний бандл

Для простых компонентов — код прямо в Appsmith:

<!-- Inline HTML в редакторе Custom Widget -->
<!DOCTYPE html>
<html>
<head>
  <script src="https://cdn.jsdelivr.net/npm/[email protected]/dist/chart.umd.min.js"></script>
</head>
<body>
  <canvas id="chart"></canvas>
  <script>
    let chart = null;

    function initChart(data) {
      const ctx = document.getElementById('chart').getContext('2d');
      chart = new Chart(ctx, {
        type: 'doughnut',
        data: {
          labels: data.map(d => d.label),
          datasets: [{
            data: data.map(d => d.value),
            backgroundColor: data.map(d => d.color),
          }],
        },
        options: {
          responsive: true,
          onClick: (event, elements) => {
            if (elements.length > 0) {
              const idx = elements[0].index;
              appsmith.triggerEvent('onSegmentClick', { item: data[idx] });
            }
          },
        },
      });
    }

    // Инициализация при загрузке
    appsmith.onReady(() => {
      initChart(appsmith.model.items || []);
    });

    // Реакция на изменение данных
    appsmith.onModelChange((model) => {
      if (chart) {
        chart.data.labels = model.items.map(d => d.label);
        chart.data.datasets[0].data = model.items.map(d => d.value);
        chart.update();
      }
    });
  </script>
</body>
</html>

Для сложных компонентов с React и TypeScript — внешний бандл:

// src/Widget.tsx
import { useEffect, useState } from 'react';

declare global {
  interface Window {
    appsmith: {
      model: Record<string, unknown>;
      onReady: (cb: () => void) => void;
      onModelChange: (cb: (model: Record<string, unknown>) => void) => void;
      triggerEvent: (name: string, payload?: unknown) => void;
      updateModel: (updates: Record<string, unknown>) => void;
    };
  }
}

interface ScheduleItem {
  id: string;
  title: string;
  start: string;
  end: string;
  resourceId: string;
}

export function SchedulerWidget() {
  const [items, setItems] = useState<ScheduleItem[]>([]);
  const [resources, setResources] = useState([]);

  useEffect(() => {
    window.appsmith.onReady(() => {
      const model = window.appsmith.model;
      setItems((model.items as ScheduleItem[]) || []);
      setResources((model.resources as []) || []);
    });

    window.appsmith.onModelChange((model) => {
      setItems((model.items as ScheduleItem[]) || []);
      setResources((model.resources as []) || []);
    });
  }, []);

  const handleEventDrop = (item: ScheduleItem, newStart: string, newEnd: string) => {
    const updated = { ...item, start: newStart, end: newEnd };
    window.appsmith.triggerEvent('onEventReschedule', { item: updated });
    window.appsmith.updateModel({ lastAction: { type: 'reschedule', item: updated } });
  };

  return (
    <FullCalendarWrapper
      items={items}
      resources={resources}
      onEventDrop={handleEventDrop}
    />
  );
}

Сборка для внешнего деплоя

// vite.config.ts
import { defineConfig } from 'vite';
import react from '@vitejs/plugin-react';

export default defineConfig({
  plugins: [react()],
  build: {
    outDir: 'dist',
    rollupOptions: {
      input: 'index.html',
    },
  },
  base: './',
});

index.html в dist деплоится на Vercel/Netlify/S3 с публичным доступом. В Appsmith Custom Widget указывается URL index.html.

Передача событий и двусторонняя синхронизация

// Обновление состояния виджета из Appsmith-кода (через Model binding)
// В поле "Default Model" в настройках виджета:
{
  "items": "{{fetchData.data}}",
  "selectedId": "{{appState.selectedItem}}"
}

// В виджете — реакция на смену selectedId
appsmith.onModelChange((model) => {
  highlightItem(model.selectedId);
});

// Из виджета — обновить глобальное состояние Appsmith
appsmith.updateModel({ selectedId: clickedItem.id });

// Это значение доступно как Widget.model.selectedId в других запросах и виджетах

Разница с Retool в разработке

В Retool можно использовать npm-пакеты через bundler seamlessly. В Appsmith inline-редактор не имеет npm — только CDN. Для серьёзных компонентов всегда нужен внешний бандл. Зато Appsmith полностью open-source — можно self-hosted без лицензионных ограничений, и кастомный виджет будет работать идентично на cloud и self-hosted.

Типичные задачи

Самые частые запросы: Gantt-планировщик ресурсов (FullCalendar + custom resource view), тепловые карты активности (D3 или ECharts heatmap), inline-редактор сложных JSON-конфигов (Monaco Editor), геоаналитика (Mapbox GL с фильтрами из Appsmith).

Сроки

Простой компонент на Chart.js или аналоге с передачей данных и одним событием — 1–2 дня. Компонент с двусторонней синхронизацией состояния, кастомной стилизацией и сложной интерактивностью — 3–5 дней. Тяжёлый планировщик или data grid с персистентностью — 1–2 недели.