Appearance
Components
codecannon apps create a set of reusable components that can be used to build the frontend of your application. These components are designed to be used with Vue 3 and PrimeVue.
ModelSelect
ModelSelect
is a component that allows the user to select a entity from a list of entities for a particular model. The list of models is fetched from the server.
The ModelSelect
component is a wrapper around the PrimeVue Select
commponent, so you can pass the Select
props to the ModelSelect
component.
vue
<template>
<ModelSelect
v-model="form.app_id"
:api="new UsersApi()"
option-label="name" />
</template>
<script>
import { ModelSelect } from '@/components'
import AppsApi from '@/models/Users/Api'
- See also
FormInput
FormInput
is a form input wrapper commponent that allows you to easily add a label and error text to a form input. It also allows you to mark an input as required.
vue
<template>
<FormInput
label="Email"
required
:errors="formErrors.email">
<InputText v-model="form.email" />
</FormInput>
</template>
<script>
import FormInput from '@/components/FormInput.vue'
import InputText from 'primevue/inputtext'
- See also
Container
Container
is a wrapper component that allows you to add default sizing to your app views.
vue
<template>
<div class="ui-container">
<slot></slot>
</div>
</template>
<style scoped lang="scss">
.ui-container {
width: 100%;
padding: 24px 10%;
}
</style>
FormContainer
The FormContainer
component is a wrapper component that adds forms the ability to be rendered either as a card or as a dialog.
vue
<template>
<Dialog
v-if="asDialog"
:visible="visible"
modal
class="form-container"
:header="title"
@update:visible="emit('close')">
<slot />
</Dialog>
<Card
v-else
border
class="form-container">
<template #title>
{{ title }}
</template>
<template #content>
<slot />
</template>
</Card>
</template>
<script setup lang="ts">
import Card from 'primevue/card'
import Dialog from 'primevue/dialog'
const emit = defineEmits(['close'])
withDefaults(
defineProps<{
asDialog?: boolean
visible?: boolean
title: string
}>(),
{
asDialog: false,
visible: false,
},
)
</script>
<style lang="scss">
.form-container {
width: 100%;
max-width: 600px;
}
</style>
Usage as dialog
The FormContainer
component can be used as a dialog by setting the asDialog
prop to true
. The dialog will be displayed when the visible
prop is set to true
.
vue
<template>
<FormContainer
asDialog
:visible="visible"
title="Create User"
@update:visible="visible = $event">
<!-- Form content -->
</FormContainer>
</template>
<script setup lang="ts">
import { ref } from 'vue'
import FormContainer from '@/components/FormContainer.vue'
const visible = ref(false)
</script>
By changing the visible
prop, you can control the visibility of the dialog.
You can listen to the visible status of the FormContainer
component by listening to the update:visible
event.
Usage as card
The FormContainer
component can be used as a card by setting the asDialog
prop to false
. The card will be displayed with the title provided.
vue
<template>
<FormContainer
title="Create user">
<!-- Form content -->
</FormContainer>
</template>
ApiTable
The ApiTable
component is designed for displaying paginated API data. It leverages PrimeVue components (such as DataTable
, Paginator
, and Card
) to render a fully functional table with pagination support. By providing a listState instance, the component can manage data fetching, loading states, and pagination interactions automatically.
vue
<template>
<ApiTable
:list-state="listState">
<Column
field="title"
header="Title" />
<Column
field="body"
header="Body" />
</ApiTable>
</template>
<script setup lang="ts">
import { onBeforeMount } from 'vue'
import ApiTable from '@/components/Table/ApiTable.vue'
import Column from 'primevue/column'
import { usePostListState } from '@/models/Post/States'
const listState = usePostListState()
const router = useRouter()
onBeforeMount(() => {
listState.getList()
})
</script>
The example above is how the table is used in List views. The ApiTable
component is used to display a list of posts. The Column
component is used to define the columns of the table. The ApiTableRemoveButton
component is used to remove a post from the list.
Table data
The ApiTable
component requires a listState
prop to be passed in. The listState
prop is an instance of the ListState
class. It allows the ApiTable
component to manage data fetching, loading states, and pagination interactions.
The data is not automatically loaded on mount, so you have to call the getList
method on the listState
instance to fetch the data. This is so you can control when the data is fetched.
Since the API table works with ListState
, all requests will be made with the default parameters or saved queries on the ListState
instance.
- See also
Pagination
The ApiTable
component uses the Paginator
component from PrimeVue to handle pagination. The Paginator
component is automatically rendered at the bottom of the table. The ApiTable
automatically handles pagintation state using the ListState
instance provided.
Row click
The ApiTable
component emits a row-click
event when a row is clicked. The event is emitted with the row data as the payload. This allows you to handle click events on rows in the table.
vue
<template>
<ApiTable
:list-state="listState"
@row-click="openDetails">
<Column
field="title"
header="Title" />
<Column
field="body"
header="Body" />
</ApiTable>
</template>
<script setup lang="ts">
import { useRouter } from 'vue-router'
import ApiTable from '@/components/Table/ApiTable.vue'
import Column from 'primevue/column'
import { usePostListState } from '@/models/Post/States'
import type { Post } from '@/models/Post/Model'
const listState = usePostListState()
const router = useRouter()
function openDetails(item: { data: Post }) {
router.push({ name: 'posts-edit', params: { id: item.data.id } })
}
</script>
Selection
The ApiTable
component supports row selection. You can enable row selection by setting the selectionMode
prop to 'single'
or 'multiple'
. The selected rows are stored in the selected
prop as a reactive set.
You can pass a selected
prop to the ApiTable
component to control the selected rows from the parent component.
vue
<template>
<ApiTable
:list-state="listState"
:selected="selected"
selection-mode="multiple">
<Column
field="title"
header="Title" />
<Column
field="body"
header="Body" />
</ApiTable>
</template>
<script setup lang="ts">
import { ref } from 'vue'
import { usePostListState } from '@/models/Post/States'
import type { Post } from '@/models/Post/Model'
const listState = usePostListState()
const selected = ref<Set<Post>>(new Set())
</script>
Loading
The ApiTable
component automatically handles loading states. The loading
prop can be used to override the loading state of the table should you need it.
If the loading
prop is set to true
, the table will display a loading indicator.
If the listState
loading state is set to true
, the table will display a loading indicator regardless of the loading
prop.
vue
<template>
<ApiTable
:list-state="listState"
:loading="loading">
<Column
field="title"
header="Title" />
<Column
field="body"
header="Body" />
</ApiTable>
</template>
<script setup lang="ts">
import { ref } from 'vue'
import { usePostListState } from '@/models/Post/States'
const listState = usePostListState()
const loading = ref(false)
</script>
ApiTableRemoveButton
The ApiTableRemoveButton
component is a button that allows you to remove a row from the table. The component is designed to be used inside the ApiTable
component.
vue
<template>
<ApiTable
:list-state="listState">
<Column
field="title"
header="Title" />
<Column
field="body"
header="Body" />
<Column header="">
<template #body="slotProps">
<ApiTableRemoveButton :item="slotProps.data" />
</template>
</Column>
</ApiTable>
</template>
<script setup lang="ts">
import { onBeforeMount } from 'vue'
import ApiTable from '@/components/Table/ApiTable.vue'
import Column from 'primevue/column'
import ApiTableRemoveButton from '@/components/Table/ApiTableRemoveButton.vue'
import { usePostListState } from '@/models/Post/States'
const listState = usePostListState()
onBeforeMount(() => {
listState.getList()
})
</script>
The ApiTableRemoveButton
component requires an item
prop to be passed in. The item
prop is the entity that the button will remove via the API.
The user will be prompted with a confirmation dialog before the item is removed.