Skip to content

Editor Component

The FlyQL editor is a Vue 3 component published as the flyql-vue npm package. It provides a schema-driven query input with autocomplete, syntax highlighting, and keyboard navigation.

<script setup>
import { ref } from 'vue'
import { FlyqlEditor, ColumnSchema } from 'flyql-vue'
const query = ref('')
const columns = ColumnSchema.fromPlainObject({
status: { type: 'number', suggest: true },
level: { type: 'enum', suggest: true, autocomplete: true, values: ['debug', 'info', 'error'] },
service: { type: 'string', suggest: true, autocomplete: true },
host: { type: 'string', suggest: true },
})
function onSubmit() {
console.log('Query submitted:', query.value)
}
function onParseError(error) {
console.log('Parse error:', error)
}
</script>
<template>
<FlyqlEditor
v-model="query"
:columns="columns"
placeholder="Type a FlyQL query..."
@submit="onSubmit"
@parse-error="onParseError"
/>
</template>

This renders a text input with autocomplete suggestions for columns, type-aware operators, and boolean operators — all driven by the columns schema.

Terminal window
npm install flyql-vue

flyql-vue automatically pulls in the flyql core package as a regular dependency, so you do not need to install it separately. The editor requires Vue 3 as a peer dependency:

Terminal window
npm install vue

Import from flyql-vue:

import { FlyqlEditor, FlyqlColumns } from 'flyql-vue'

The components do not import the stylesheet automatically — import flyql.css once in your application entrypoint:

import 'flyql-vue/flyql.css'

This provides theme variables, suggestion panel styles, and token highlighting.

PropTypeDefaultDescription
modelValueString''Query text (v-model)
columnsObject{}Column schema
onAutocompleteFunctionnullAsync value callback
onKeyDiscoveryFunctionnullRemote key discovery callback
placeholderString''Placeholder text
autofocusBooleanfalseAuto-focus on mount
debugBooleanfalseDebug logging
debounceMsNumber300Debounce delay (ms) for async autocomplete calls. Set to 0 to disable
darkBooleanfalseEnable dark theme (see theming)
labelString''Text shown inside the field, to the left of the query
iconString | Object | Function | BooleannullIcon shown before the label: a string renders as text, a component renders as-is, false removes it
multilineBooleantrueAllow multi-line input. When false, newlines are collapsed to spaces and the field stays one line
hasClearBooleanfalseShow a clear button at the trailing edge; it appears only when the field has a value
clearButtonLabelString'Clear'Accessible name of the clear button
panelContainerString | Object'body'Where to portal the suggestion panel: a selector or an element. Defaults to body

Callback signatures:

  • onAutocomplete(key, value) — returns Promise<{ items: string[], incomplete?: boolean }>
  • onKeyDiscovery(columnName, segments) — returns Promise<Array<{ name, type?, hasChildren? }>>

When incomplete is true in the response, the editor knows the returned list is partial and will re-fetch on the next keystroke. Async calls are debounced (default 150ms) and in-flight requests are automatically cancelled when a new one starts.

label and icon share the slot on the left of the field, ahead of the query text. Clicking either focuses the input, and an overlong label is truncated with an ellipsis at half the field width instead of squeezing the input. A text label also becomes the input’s accessible name, replacing the component’s default aria-label.

<template>
<FlyqlEditor v-model="query" :columns="columns" label="Filter" />
<FlyqlEditor v-model="query" :columns="columns" icon="🔎" />
<FlyqlEditor v-model="query" :columns="columns" :icon="MyIcon" />
<FlyqlEditor v-model="query" :columns="columns" :icon="false" label="Filter" />
</template>

The icon and label slots take precedence over the props when you need richer content:

<template>
<FlyqlEditor v-model="query" :columns="columns">
<template #icon><MyIcon /></template>
<template #label><strong>Filter</strong></template>
</FlyqlEditor>
</template>
EventPayloadDescription
update:modelValuestringQuery text changed (v-model)
submitUser pressed Ctrl/Cmd+Enter
parse-errorstringParse error message when query is invalid
focusEditor gained focus
blurEditor lost focus

Access via template ref:

<script setup>
import { ref } from 'vue'
import { FlyqlEditor } from 'flyql-vue'
const editorRef = ref(null)
function checkStatus() {
const status = editorRef.value.getQueryStatus()
console.log(status.valid, status.message)
}
</script>
<template>
<FlyqlEditor ref="editorRef" v-model="query" :columns="columns" />
<button @click="checkStatus">Check</button>
</template>
MethodReturnsDescription
focus()Focus the editor input
blur()Blur the editor input
getQueryStatus(){ valid: boolean, message: string }Validate the current query

Provide an onAutocomplete callback to fetch value suggestions from your API:

<script setup>
import { ref } from 'vue'
import { FlyqlEditor, ColumnSchema } from 'flyql-vue'
const query = ref('')
const columns = ColumnSchema.fromPlainObject({
service: { type: 'string', suggest: true, autocomplete: true },
level: { type: 'enum', suggest: true, autocomplete: true, values: ['info', 'error'] },
})
async function onAutocomplete(key, value) {
const resp = await fetch(`/api/autocomplete?key=${encodeURIComponent(key)}`)
const data = await resp.json()
return { items: data.values }
}
</script>
<template>
<FlyqlEditor v-model="query" :columns="columns" :on-autocomplete="onAutocomplete" />
</template>

The callback receives the column key and current value prefix. Return { items: string[], incomplete?: boolean }. A loading indicator appears automatically after 200ms.

The editor uses a stateful autocomplete flow that minimizes server calls:

  • Initial load — When entering value context (e.g., service=), the editor fetches immediately with no debounce. A full spinner is shown until results arrive.
  • Complete list (incomplete: false) — The editor stores the returned items and switches to client-side filtering. Subsequent keystrokes filter instantly without server calls, until the user changes to a different column.
  • Incomplete list (incomplete: true) — The editor keeps showing current suggestions while a debounced re-fetch runs in the background. An inline spinner appears in the header. When new results arrive, they replace the current suggestions.

If the server returns 0 items, the editor displays “No matching values”. For client-side filtering of a complete list, an empty result simply shows no suggestions (the user can backspace to see more).

Columns with autocomplete: true and static values use those values directly without calling the callback. Columns with autocomplete: true but no values trigger the callback.

KeyAction
Arrow Up/DownNavigate suggestions
Enter / TabAccept selected suggestion
EscapeDismiss suggestions
Ctrl/Cmd+EnterSubmit query (emits submit event)
Shift+EnterInsert a newline (unless multiline is false)