Vue
Vue 3 with Vite. Install the packages, tell the compiler about the custom element, copy the fonts, and wrap the element in a component with v-model.
npm install ./vendor/rd-designer-1.0.0.tgz ./vendor/rd-core-1.0.0.tgz ./vendor/rd-fonts-1.0.0.tgz
npm install ./vendor/rd-fonts-cjk-1.0.0.tgz # optional: Chinese, Japanese, Korean
Configure the compiler#
Tell the Vue compiler that report-designer is a custom element (vite.config.ts):
import { defineConfig } from 'vite';
import vue from '@vitejs/plugin-vue';
export default defineConfig({
plugins: [vue({ template: { compilerOptions: { isCustomElement: (tag) => tag === 'report-designer' } } })],
});
A wrapper component with v-model#
A wrapper component with v-model for the template. Don't name the file ReportDesigner.vue: a component can refer to itself by its file name, which would
make <report-designer> inside it resolve to the wrapper instead of the custom element.
<script setup lang="ts">
import '@rd/designer'; // registers <report-designer>
import type { Template, TemplateChangeDetail } from '@rd/designer';
const template = defineModel<Template | null>({ default: null });
const props = withDefaults(defineProps<{
schema?: object | null;
lang?: string;
fontBaseUrl?: string;
}>(), { schema: null, lang: '', fontBaseUrl: '/rd-fonts/' });
const emit = defineEmits<{ save: [template: Template] }>();
function onTemplateChange(e: Event) {
template.value = (e as CustomEvent<TemplateChangeDetail>).detail.template;
}
function onSave(e: Event) {
emit('save', (e as CustomEvent<TemplateChangeDetail>).detail.template);
}
</script>
<template>
<!-- .prop binds DOM properties (objects); plain attributes stay strings. -->
<report-designer
:template.prop="template"
:schema.prop="props.schema"
:lang="props.lang"
:font-base-url="props.fontBaseUrl"
style="display: block; height: 100%"
@template-change="onTemplateChange"
@save="onSave"
/>
</template>
Use it in a page#
Keep the template in a shallowRef: a deep reactive proxy is unnecessary for a JSON document you only replace.
<script setup lang="ts">
import { onMounted, shallowRef } from 'vue';
import type { Template } from '@rd/designer';
import RdDesigner from './RdDesigner.vue';
const props = defineProps<{ templateId: string }>();
const template = shallowRef<Template | null>(null);
const schema = bolSchema; // your data contract
onMounted(async () => {
template.value = await loadTemplate(props.templateId);
});
async function save(t: Template) {
await saveTemplate(props.templateId, t);
}
</script>
<template>
<div style="height: 100vh">
<RdDesigner v-model="template" :schema="schema" @save="save" />
</div>
</template>
Copy the fonts#
Before building, copy the contents of node_modules/@rd/fonts/fonts/ and, if installed, node_modules/@rd/fonts-cjk/fonts/ into public/rd-fonts/,
and keep font-base-url="/rd-fonts/".