Skip to main content

Page Customization

Prerequisites

If you haven't created a full-code page yet, please refer to Creating Full-code Pages first to learn how to create React and Vue full-code pages.

This document covers specific development technologies and usage patterns for full-code pages, including style processing, component usage, resource management, and data operations.

Creating a React full-code page

Using styles

In full-code pages, you can choose from various styling solutions: inline styles, CSS-in-JS, or plain CSS—all of which work out of the box without additional build configuration. However, native LESS or SCSS requires enabling the corresponding build configuration in your project.

Loading...

LESS and SCSS style files require configuring parsing plugins. Refer to Introducing build plugins for details.

// Inline style example - define styles directly in JSX
<div style={{color: "red"}}>hello world - inline styles</div>
tip

When using CSS-in-JS, you can directly consume Ant Design's theme tokens to naturally align with the platform's default styles. You can also access and reuse custom variables defined in the platform's "Global Styles," enabling centralized management of brand colors, border radius, shadows, and more. See Global Styles for details.

Using local resources

The platform provides built-in parsing capabilities for common resources. In full-code pages, you can directly use import statements to import resources. Here's an image example:

import logo from './logo.png';

export const Render = () =>{
return <img src={logo} alt="logo" />
}

For additional resource parsing capabilities, see Default loader mapping. You can also extend loader mappings via Using build configuration.

Using Ant Design components

The platform is built on the React framework with the Ant Design UI component library pre-installed, allowing you to directly use all Ant Design components. For mobile applications, the Ant Design Mobile component library is also available.

import { Button } from 'antd';

export const Render = () =>{
return <Button>Button</Button />
}

For a complete list of built-in packages, see System built-in package overview.

Embedding existing standard pages

Reusing existing standard pages within full-code pages reduces duplicate development and improves code reusability. The following demonstrates interaction between full-code pages and embedded standard pages.

Loading...

This example demonstrates cross-page component interaction: buttons in the full-code page control data refresh of the embedded page's table, while listening to table row click events to retrieve and display the current row's ID.

Implementation:

import { useRef } from "react";
import { Button, message } from "antd";
import { Jit } from "jit";
import { ElementRender } from "jit-widgets";

// Full-code implementation includes: renderer and logic processing class
// Render is the page renderer, UI part is implemented here, it's a React component
const Render = (props) => {
const embeddedPageRef = useRef(null);

// Refresh embedded page table
const handleRefreshTable = () => {
if (embeddedPageRef.current?.Table1) {
embeddedPageRef.current.Table1.call();
}
};

// Bind embedded page instance and events
const handlePageInit = (pageInstance) => {
embeddedPageRef.current = pageInstance;

// Bind table row click event
pageInstance.Table1?.subscribeEvent("clickRow", () => {
const activeRowId = pageInstance.Table1.activeRow?.id?.value;
message.info(`Table row clicked, ID: ${activeRowId}`);
});
};

return (
<div>
<Button type="primary" onClick={handleRefreshTable}>
Refresh Table
</Button>
<h3>Below is the embedded page; click the button above to interact with the table, click the table to trigger bound events.</h3>
<ElementRender
elementPath="pages.embeddedPages"
onInitAfter={handlePageInit}
/>
</div>
);
};
// This is the full-code page logic processing class, logic part is implemented here, it's a JavaScript class
class PageCls extends Jit.BasePage {
// You can add page-specific methods here
}

export { Render, PageCls };

The ElementRender component can render both standard page elements and other full-code pages—simply configure the element's fullName to the elementPath property. To interact with the embedded page, configure the onInitAfter property. Upon initialization, the embedded page's instance will be passed as a parameter. Here's an example of an embedded page instance:

import type { ComponentPageScheme } from "jit";
import { Jit } from "jit";
import schemeJson from "./scheme.json";
type BaseComponent = InstanceType<typeof Jit.BaseComponent>;

class PageCls extends Jit.GridPage {
Table1!: BaseComponent;
scheme: ComponentPageScheme = schemeJson;
bindEvent() {}
}

export default PageCls;

The embedded page contains a table instance named Table1, which the full-code page can interact with via the page instance.

Using standard components

Reusing existing standard components within full-code pages reduces duplicate development and improves code reusability. The following demonstrates interaction between full-code pages and standard components.

Loading...

This example demonstrates cross-page component interaction: buttons in the full-code page control table component data refresh, while listening to table row click events to retrieve and display the current row's ID.

All standard components are configuration-driven—the component renderer accepts a component instance constructed from configuration. Due to the complexity of component configuration, when using standard components in full-code pages, we recommend first creating a generic page, adding and configuring standard components there, then copying the component configuration to your full-code page.

Loading...

Navigate to the standard page containing the component to copy, switch to source code mode, open scheme.json, locate the componentList configuration item, and copy the desired component configuration to your full-code page.

Example code:

import { Button, message } from 'antd';
import { Jit } from 'jit';

import ComponentRender from './ComponentRender';
import tableConfig from './tableConfig.json';

// Full-code implementation includes: renderer and logic processing class
// Render is the page renderer, UI part is implemented here, it's a React component
const Render = (props) => {
// Page renderer receives a page parameter, page is an instance object of the page logic processing class
const page = props.page;

// Refresh embedded page table
const handleRefreshTable = () => {
if (page[tableConfig.name]) {
page[tableConfig.name].call();
}
};

const handleComponentReady = (compIns: any) => {
compIns.subscribeEvent('clickRow', () => {
const activeRowId = compIns.activeRow?.id?.value;
message.info(`Table row clicked, ID: ${activeRowId}`);
});
};

return (
<div>
<Button type="primary" onClick={handleRefreshTable}>
Refresh Table
</Button>
<h3>Below is the standard component, click the button above to interact with the table</h3>
<ComponentRender config={tableConfig} page={page} onReady={handleComponentReady} />
</div>
);
};

// This is the full-code page logic processing class, logic part is implemented here, it's a JavaScript class
class PageCls extends Jit.BasePage {}

export { Render, PageCls };

index.tsx - Main page component implementing UI rendering and event interaction logic.

ComponentRender.tsx - Reusable standard component renderer responsible for dynamically loading and instantiating standard components.

tableConfig.json - Table component configuration example containing data model reference models.cascadeTableData. Replace with your project's actual data model in practice.

e.json - Page element definition file with type "pages.NormalType", specifying a React full-code page type. The frontBundleEntry points to the entry file.

Calling data model functions

Full-code pages provide convenient access to data model functions. We recommend using visual pages to configure function parameters first, then copying the generated function code to your full-code page. For specific instructions, refer to CRUD operations for data models.

For detailed data model function calling methods and syntax, see: Calling Data Model Functions in Pages

Here's an example of retrieving a single record from a data model:

Loading...

Clicking the button calls the model's get-one-record function and displays the result in a message. Example code:

import { Button, message } from 'antd';
import { Jit } from 'jit';

const Render = ({ page }) => {
const handleClick = async () => {
message.success(await page.getData());
};

return (
<div>
<Button type="primary" onClick={handleClick}>
Click Me!
</Button>
</div>
);
};

class PageCls extends Jit.BasePage {
/**
* Get data, page method
*/
async getData() {
return JSON.stringify(
await this.app.models.cascadeTableData.get(
Q(Q('id', '=', 1)),
null,
2
)
);
}
}

export { Render, PageCls };

The syntax for calling model functions is: this.app.models.[model name].[method name]([param1], [param2], ...)

Calling service functions

Service functions follow the same calling pattern as data model functions, using the syntax: this.app.services.[service name].[method name]([param1], [param2], ...).

For detailed service function calling methods and examples, see: Calling Service Functions in Pages

Creating a Vue full-code page

Basic structure

Vue full-code pages consist of four core files:

<script setup>
import { ref } from 'vue'

const message = ref('Hello JIT!');
const dialogVisible = ref(false);
const props = defineProps({
page: Object
});

const callPageMethod = () => {
alert(props.page.getData());
}
</script>

<template>
<div class="demo">
<h1>{{ message }}</h1>
<h2>Current page name is: {{props.page.title}}</h2>
<el-button plain @click="dialogVisible = true">
element-plus component usage
</el-button>
<hr/>
<el-button type="info" @click="callPageMethod">
Call current page instance method
</el-button>
<hr/>
<el-button type="danger" @click="props.page.closePage">
Close current page
</el-button>
</div>

<el-dialog
v-model="dialogVisible"
title="Tips"
width="500"
>
<span>hello World!</span>
<template #footer>
<div class="dialog-footer">
<el-button @click="dialogVisible = false">Close</el-button>
<el-button type="primary" @click="dialogVisible = false">
Confirm
</el-button>
</div>
</template>
</el-dialog>
</template>

<style scoped>
.demo{
display: flex;
align-items: center;
flex-direction: column;
}
</style>

App.vue - Vue component using Composition API syntax that receives the page instance via props.

index.ts - Render entry that creates the Vue application, registers Element Plus, and passes the page instance as props to the App component.

page.ts - Page logic processing class that inherits from Jit.BasePage. Add custom methods here for Vue component calls.

e.json - Element definition file with type "pages.VueType", specifying a Vue page type.

Using Element Plus components

Vue full-code pages have the Element Plus UI component library pre-installed, allowing you to directly use all Element Plus components:

<template>
<el-button type="primary">Primary Button</el-button>
<el-dialog v-model="visible">Dialog Content</el-dialog>
<el-table :data="tableData">Table Component</el-table>
</template>

Interacting with the page instance

Vue components receive the page instance via props and can call methods and access properties:

<script setup>
const props = defineProps({
page: Object
});

// Call page methods
const handleClick = () => {
props.page.getData();
props.page.closePage();
};

// Access page properties
const pageTitle = props.page.title;
</script>
tip

Vue full-code pages deliver a native Vue development experience with full support for data model functions, service functions, local resource references, and other core capabilities, allowing you to leverage the Vue ecosystem while benefiting from platform features.

Related Materials

CRUD operations for data models

Backend data models provide comprehensive CRUD functionality. See the API Documentation for details.

However, backend functions can only be called in backend runtime contexts (service functions, scheduled task functions, event functions). To address this, the platform also provides data model operation interfaces for the frontend environment:

Loading...

In the event panel of standard pages, click the Please Select text on blank statements in the function panel. Select Data Model[Model Name] to view multiple model operation functions. For example, select Get One Data for query operations.

Using model functions in full-code

Model functions often have multiple parameters. To simplify this complexity, you can visually configure parameters and quickly locate the generated code to copy directly into your full-code page.

Loading...

Click Parameter Settings and configure the function parameters. At the end of the generated function statement, click the </> button to jump to the source code area with the function statement highlighted. Copy the function statement (e.g., await this.app.models.CalendarTestModel.get(Q(Q("id", "=", 1)), null, 2);) into your full-code page.

warning

Note: Data model functions in pages always start with this.app. If you're in a context without this.app, import and use the runtime app:

import { getRuntimeApp } from 'jit';
const app = getRuntimeApp();
// app.models.xxx;

Using service functions

See CRUD operations for data models for usage patterns.

Calling service functions in full-code

See Using model functions in full-code for the same approach.

Using third-party packages

In full-code page development, you can flexibly integrate third-party npm packages to extend functionality. In the editor's source code mode, modify the package.json file by adding the required dependencies to the dependencies field, then click "Save." The system will automatically run pnpm install on the backend to install the new packages, after which you can import and use them normally in your code.

For example, to add rxjs, modify package.json:

Loading...

Add the rxjs dependency to the dependencies field in package.json, then click "Save" to install.

Using network resources

The system's bundler supports importing packages from the network, but requires them to be in ES Module format or errors will occur. We recommend using https://esm.sh. For rxjs, you can directly import it in your page:

Loading...

After importing import { Observable } from 'https://esm.sh/rxjs?bundle' in your frontend files, you can use the third-party package directly.

tip

esm.sh provides optimization parameters like ?bundle, which compresses multiple ES Modules into a single file, reducing request count and improving performance. Since esm.sh is open source, we recommend self-hosting in production environments for better availability and security.

Using build configuration

The platform's frontend bundler is built on esbuild, with configuration options matching esbuild's API. In the jit.config.ts file at your application root, you can customize build parameters to meet specific requirements.

Loading...

The esBuildOptions configuration aligns with esbuild. For details, refer to the esbuild documentation.

Source map debugging

In development, you can enable the sourcemap option in jit.config.ts. For production, set it to false to significantly reduce bundle size.

Introducing build plugins

For example, to add Less and SCSS parsing plugins—both already integrated in the platform's bundler jit-builder—you can include jit-builder in package.json following the method in Using third-party packages.

Loading...

Since the default package.json already includes jit-builder, simply change it from devDependencies to dependencies, then save. Next, modify the build configuration file jit.config.ts.

Loading...

Import styleInJsPlugin and scssInJsPlugin in jit.config.ts, then add them to the plugins array.

tip

This method applies to all esbuild plugins. To find plugins, refer to the esbuild plugins directory.

System built-in package overview

The platform pre-includes commonly used third-party libraries that can be imported and used directly in code without declaring them in package.json:

Package NameVersionGlobal Variable NameDescription
React Ecosystem
react18.2.0ReactReact core library
react-dom18.2.0ReactDomReact DOM library
react-dom/client18.2.0ReactDomClientReact 18 client API
react-dom/server18.2.0ReactDomServerReact server rendering API
react-router6.18.0ReactRouterReact Router core
react-router-dom6.18.0ReactRouterDomReact Router DOM bindings
react-dnd16.0.1ReactDndReact drag-and-drop library
react-dnd-html5-backend16.0.1ReactDndHtml5BackendHTML5 drag-and-drop backend
Vue Ecosystem
vue3.5.13VueVue.js framework
element-plus2.8.8ElementPlusVue 3 UI component library
UI Component Libraries
antd5.24.0JitAntdAnt Design component library
antd-mobile5.33.0antdMobileAnt Design Mobile components
@ant-design/cssinjs1.17.5antCssInJsAnt Design CSS-in-JS
Style Processing
@emotion/react11.13.3EmotionReactCSS-in-JS library
@emotion/styled11.13.0EmotionStyledEmotion styled components
@emotion/cache11.13.1EmotionCacheEmotion cache
Utility Libraries
lodash4.17.21lodashJavaScript utility library
lodash-es4.17.21lodashLodash ES module version
dayjs1.11.11dayjsLightweight date library
axios1.6.1axiosHTTP client
ahooks3.7.8ahooksReact Hooks library
localforage1.10.0localforageLocal storage library
recast0.23.4recastJavaScript AST tool
Platform-Specific
jit-JitCoreJitAi core library
jit-utils-JitUtilsJitAi utilities
jit-ui-JitUiJitAi UI components
jit-widgets-JitWidgetsJitAi widgets
tip

These libraries can be imported and used directly without installation, e.g., import { useState } from 'react' or import { Button } from 'antd'.

Default loader mapping

The platform is built on esbuild. The following shows the default file type processor configuration:

File TypeLoaderDescription
.pngdataurlPNG images, converted to base64 data URLs
.jpedataurlJPE images, converted to base64 data URLs
.jpegdataurlJPEG images, converted to base64 data URLs
.gifdataurlGIF images, converted to base64 data URLs
.svgdataurlSVG vector graphics, converted to base64 data URLs
.cssdataurlCSS stylesheets, converted to base64 data URLs
.pytextPython scripts, processed as text
.webpdataurlWebP images, converted to base64 data URLs
tip

To customize processing for other file types, configure them in esBuildOptions.loader within jit.config.ts.

Creating full-code pages

Learn how to create React and Vue full-code pages: Creating Full-code Pages

Full-code components

Learn about developing with full-code components in pages: Full-Code Component Interface Specifications

JitAI AssistantBeta
Powered by JitAI