Default CRUD​
By default you can create an AutoQueryGrid that allows authorized users the ability to Create, Read, Update & Delete records with just the DataModel, e.g:
<AutoQueryGrid type="Booking" />
This will utilize your App's existing AutoQuery APIs for the specified DataModel to enable its CRUD functionality.
Read Only​
You can use apis to limit which AutoQuery APIs AutoQueryGrid should use, so if only the AutoQuery DTO is provided, the AutoQueryGrid will only be browsable in read-only mode:
<AutoQueryGrid type="Booking" apis="QueryBookings"  />
Table Styles
The same DataGrid Table Styles can also be used to style AutoQueryGrid, e.g:
<AutoQueryGrid type="Booking" tableStyle="verticalLines,uppercaseHeadings" />
Custom Styles
The AutoQueryGrid's appearance is further customizable with the property classes & functions below:
defineProps<{
  toolbarButtonClass: string
  tableStyle: "simple" | "fullWidth" | "stripedRows" | "whiteBackground" | "uppercaseHeadings" | "verticalLines"
  gridClass: string
  grid2Class: string
  grid3Class: string
  grid4Class: string
  tableClass: string
  theadClass: string
  tbodyClass: string
  theadRowClass: string
  theadCellClass: string
  rowClass:(model:any,i:number) => string
  rowStyle:(model:any,i:number) => StyleValue
}>()
Custom AutoQueryGrid
Different AutoQueryGrid features can be hidden with hide and functionality disabled with deny, e.g:
<AutoQueryGrid type="Booking" hide="pagingNav,copyApiUrl,downloadCsv" deny="filtering" />
Features that can be hidden and disabled include:
defineProps<{
    deny: "filtering" | "queryString" | "queryFilters"
    hide: "toolbar"   | "preferences" | "pagingNav" | "pagingInfo" | "downloadCsv" | "refresh" 
       | "copyApiUrl" | "filtersView" | "newItem"   | "resetPreferences" 
}>()
Global AutoQueryGrid Configuration
These features can also be disabled at a global level, applying to all <AutoQueryGrid> components with setConfig, e.g:
const { setAutoQueryGridDefaults } = useConfig()
setAutoQueryGridDefaults({
  hide: ['pagingNav','copyApiUrl','downloadCsv']
})
Limit Columns
By default AutoQueryGrid displays all public properties returned in its AutoQuery API which can be further limited with selected-columns:
<AutoQueryGrid type="Booking" selectedColumns="id,name,roomType,roomNumber,cost" />
Simple Responsive Columns
Using visible-from is a simple way to enable a responsive DataGrid by specifying at which Tailwind breakpoints
columns should be visible from and header-titles to use friendlier aliases for different columns, e.g:
<AutoQueryGrid type="Booking" 
  selectedColumns="id,name,roomType,roomNumber,cost,bookingStartDate,bookingEndDate" 
  :headerTitles="{ roomNumber:'Room', bookingStartDate:'Start', bookingEndDate:'End' }"
  :visibleFrom="{ bookingStartDate:'lg', bookingEndDate:'xl' }" />
Custom Responsive Columns
Which columns are displayed and how they're formatted are further customizable with <template #column> slots:
<AutoQueryGrid type="Booking" :visibleFrom="{ name:'xl', bookingStartDate:'sm', bookingEndDate:'xl', createdBy:'2xl' }">
    <template #id="{ id }">
        <span class="text-gray-900" v-html="id"></span>
    </template>
    
    <template #name="{ name }" v-html="name"></template>
    
    <template #roomNumber-header>
        <span class="hidden lg:inline">Room </span>No
    </template>
    <template #cost="{ cost }">
        <span v-html="currency(cost)"></span>
    </template>
    
    <template #bookingStartDate-header>
        Start<span class="hidden lg:inline"> Date</span>
    </template>
    
    <template #bookingEndDate-header>
        End<span class="hidden lg:inline"> Date</span>
    </template>
    <template #createdBy-header>
        Employee
    </template>
    <template #createdBy="{ createdBy }" v-html="createdBy"></template>
</AutoQueryGrid>
Custom Functionality
The column template slots can be leveraged to implement custom functionality, e.g. instead of navigating to separate pages to manage related data we can use a custom column to manage Booking Coupons from within the same grid, e.g:
<AutoQueryGrid type="Booking" selectedColumns="id,name,cost,bookingStartDate,bookingEndDate,discount">
    <template #discount="{ discount }">
        <TextLink v-if="discount" class="flex items-end" @click.stop="showCoupon(discount.id)" :title="discount.id">
            <Icon class="w-5 h-5 mr-1" type="Coupon" />
            <PreviewFormat :value="discount.description" />
        </TextLink>
    </template>
</AutoQueryGrid>
<AutoEditForm v-if="coupon" type="UpdateCoupon" v-model="coupon" @done="close" @save="close" />
<script setup lang="ts">
import { ref } from "vue"
import { useClient } from "@servicestack/vue"
import { QueryCoupons } from "dtos"
const client = useClient()
const coupon = ref()
async function showCoupon(id:string) {
    const api = await client.api(new QueryCoupons({ id }))
    if (api.succeeded) {
        coupon.value = api.response!.results[0]
    }
}
const close = () => coupon.value = null
</script>
Data Reference Labels
AutoQuery is able to infer relationships from the POCO References of your Data Models where if your DataModel includes [Reference] attributes so that its related Data is returned in your AutoQuery APIs, AutoQueryGrid will be able to make use of it to render the Contacts & Job Names and Icons instead of just the plain Foreign Key Ids.
An example of this in the JobApplications DataModel DTO:
[Icon(Svg = Icons.Application)]
public class JobApplication : AuditBase
{
    [AutoIncrement]
    public int Id { get; set; }
    [References(typeof(Job))]
    public int JobId { get; set; }
    [References(typeof(Contact))]
    public int ContactId { get; set; }
    [Reference]
    [Format(FormatMethods.Hidden)]
    public Job Position { get; set; }
    [Reference]
    [Format(FormatMethods.Hidden)]
    public Contact Applicant { get; set; }
    [Reference]
    public List<JobApplicationComment> Comments { get; set; }
    public DateTime AppliedDate { get; set; }
    public JobApplicationStatus ApplicationStatus { get; set; }
    //...
}
Which AutoQueryGrid uses to automatically display the Job and Contact name instead of their ids:
<AutoQueryGrid type="JobApplication" :prefs="{take:5}" />
With the original ids are discoverable by hovering over the Job & Contact labels.
Reference Fields​
By default AutoQuery will infer using the first string column of the related table for its label, this information can also be explicitly defined
with the [Ref] attribute, e.g:
public class JobApplication : AuditBase
{
    [AutoIncrement]
    public int Id { get; set; }
    [References(typeof(Job))]
    [Ref(Model=nameof(Job), RefId=nameof(Job.Id), RefLabel=nameof(Job.Title))]
    public int JobId { get; set; }
    [References(typeof(Contact))]
    [Ref(Model=nameof(Contact), RefId=nameof(Contact.Id), RefLabel=nameof(Contact.DisplayName))]
    public int ContactId { get; set; }
    //...
}
Alternatively you can use [Ref(None=true)] to disable any implicit inferences and render the FK property Ids as-is.
When displaying referential data you can tell AutoQueryGrid to hide rendering the complex data references as well columns
using [Format(FormatMethods.Hidden)].
AutoQueryGrid Template Slots​
AutoQueryGrid supports a number of Vue slots to customize its built-in UIs,
including formheader and formfooter slots to insert custom content before and after the Auto Create & Edit components forms:
<template #formheader="{ form, type, apis, model, id }">
<template #formfooter="{ form, type, apis, model, id }">
This feature is used to implement Locode's Audit History UI for displaying the Audit History of each record in the bottom of the Edit Form for Authorized Users, implemented with:
<AutoQueryGrid :key="store.opDataModel" ref="grid" :type="store.opDataModel">
    <template #formfooter="{ form, type, apis, model, id }">
        <AuditEvents v-if="form === 'edit' && canAccessCrudEvents" class="mt-4" :key="id" :type="type" :id="id" />
    </template>
</AutoQueryGrid>
Which loads the AuditEvents.mjs component at the bottom of Edit forms, allowing Admin Users to inspect the Audit History of each record:
Alternatively you can replace the entire Create and Edit Forms used with the createform and editforms slots:
<template #createform="{ form, apis, type }">
<template #editform="{ form, apis, type }">
Additional toolbar buttons can be added with the toolbarbuttons slot, e.g:
<template #toolbarbuttons="{ toolbarButtonClass }">
  <div class="pl-2 mt-1">
      <button type="button" @click="customAction" :class="toolbarButtonClass">
        <span class="whitespace-nowrap">My Action</span>
      </button>
  </div>
</template>
Alternatively you can replace the entire toolbar with your own with:
<template #toolbar>
All other template slots are passed down to the embedded DataGrid component where they can be used to customize column headers and cells.
AutoQueryGrid Properties​
Additional customizations available using AutoQueryGrid properties include:
defineProps<{
    filterDefinitions?: AutoQueryConvention[]
    id?: string
    apis?: string|string[]
    type?: string|InstanceType<any>|Function
    prefs?: ApiPrefs
    deny?: string|GridAllowOptions|GridAllowOptions[]
    hide?: string|GridShowOptions|GridShowOptions[]
    
    selectedColumns?:string[]|string
    toolbarButtonClass?: string
    tableStyle?: TableStyleOptions
    gridClass?: string
    grid2Class?: string
    grid3Class?: string
    grid4Class?: string
    tableClass?: string
    theadClass?: string
    tbodyClass?: string
    theadRowClass?: string
    theadCellClass?: string
    headerTitle?:(name:string) => string
    headerTitles?: {[name:string]:string}
    visibleFrom?: {[name:string]:Breakpoint}
    rowClass?:(model:any,i:number) => string
    rowStyle?:(model:any,i:number) => StyleValue | undefined
    apiPrefs?: ApiPrefs
    canFilter?:(column:string) => boolean
    disableKeyBindings?:(column:string) => boolean
    configureField?: (field:InputProp) => void
    skip?: number
    create?: boolean
    edit?: string|number
}>()
AutoQueryGrid Events​
Whilst the headerSelected and rowSelected events can be used to invoke custom functionality when column headers and rows are selected:
defineEmits<{
    (e: "headerSelected", name:string, ev:Event): void
    (e: "rowSelected", item:any, ev:Event): void
}>()
Powers Locode​
AutoQueryGrid is already used extensively and is the key component that enables Locode's Instant Auto UI to manage your App's AutoQuery CRUD APIs.

