Models
Coalesce generates TypeScript interfaces for each of your exposed C# data model types. These interfaces are pure data representations and have no functionality of their own. These model interfaces are generated in models.g.ts
, with each one containing all the Properties of that type, as well as a $metadata
property that references the metadata object for that type. Enums and Data Sources are also generated here.
The generated model interfaces are also each accompanied by a generated TypeScript class that can be used to easily instantiate a valid implementation of its corresponding interface. However, it is not necessary for these classes to be used.
Model Interfaces
An example of a generated model interface, along with its corresponding enum dependency, is as follows:
export interface Person extends Model<typeof metadata.Person> {
personId: number | null
title: Titles | null
name: string | null
email: string | null
birthDate: Date | null
}
export enum Titles {
Mr = 0,
Ms = 1,
Mrs = 2,
Miss = 4,
}
You can then use the interface in the type signatures of your custom code to accept instances obtained from API calls, or those you instantiated yourself.
import { Person } from '@/models.g'
const person = new Person({ name: 'Bob' });
Data Sources
For each custom Data Source you define for your C# models, a corresponding TypeScript class is generated that includes the Custom Parameters of the data source.
These classes are generated in a namespace named DataSources
that is nested inside a namespace named after their parent model type. As a convenience, and unlike the regular model interfaces, their instances are automatically reactive with Vue since they are commonly instantiated and bound to as top-level objects in Vue components.
An example usage:
import { Person } from '@/models.g'
const dataSource = new Person.DataSources.NamesStartingWith;
dataSource.startsWith = "A";
<c-input :model="dataSource" for="startsWith" />
These generated data source classes are also available through the generated ViewModel classes for convenience:
import { PersonListViewModel } from '@/models.g'
const list = new PersonListViewModel();
list.$dataSource
= new PersonListViewModel.DataSources.NamesStartingWith({startsWith: 'A'});
list.$load();
Model Functions
The following functions exported from coalesce-vue
can be used with your Models or View Models when building custom pages or components.
useBindToQueryString()
Binds a value on an object, or the value of a ref, to the query string.
Type
tsfunction useBindToQueryString(obj: {}, key: string, options?: BindToQueryStringOptions): void function useBindToQueryString(ref: Ref<any>, queryKey: string): void function useBindToQueryString(ref: Ref<any>, options: BindToQueryStringOptions): void interface BindToQueryStringOptions { mode?: 'push' | 'replace' parse?: (value: string) => any stringify?: (value: any) => string }
Details
When the object's value changes, the query string will be updated using vue-router. When the query string changes, the object's value will be updated.
The query string will be updated using either
router.push
orrouter.replace
depending on the value of parametermode
.If the query string contains a value when this is called, the object will be updated with that value immediately.
If the object being bound to has
$metadata
, information from that metadata will be used to serialize and parse values to and from the query string. Otherwise, thestringify
option (default:String(value)
) will be used to serialize the value, and theparse
option (if provided) will be used to parse the value from the query string.Example
tsimport { useBindToQueryString } from 'coalesce-vue'; // Bind pagination information to the query string: const list = new PersonListViewModel(); useBindToQueryString(list.$params, 'pageSize', { parse: parseInt }); const activeTab = ref("1") useBindToQueryString(activeTab, 'activeTab');
useBindKeyToRouteOnCreate()
When a model is created, add the new primary key to the current page URL.
Type
tsfunction useBindKeyToRouteOnCreate( model: Model<ModelType>, routeParamName: string = 'id', keepQuery: boolean = false ): void
Details
When
model
is created (i.e. its primary key becomes non-null), replace the current URL with one that includes the primary key for the route parameter named byrouteParamName
.The query string will not be kept when the route is changed unless
true
is given tokeepQuery
.The route will be replaced directly via the HTML5 History API such that vue-router will not observe the change as an actual route change, preventing the current view from being recreated if a path-based key is being used on the application's
<router-view>
component.Example
First, define your router with a route that has an optional ID parameter:
ts// router.ts const router = createRouter({ routes: [ { path: '/person/:id?', component: () => import('@/views/Person.vue'), props: true } ] })
Then use
useBindKeyToRouteOnCreate
in your component:ts// views/Person.vue import { useBindKeyToRouteOnCreate } from 'coalesce-vue'; const props = defineProps<{id?: number}>(); const person = new PersonViewModel(); if (props.id) { person.$load(props.id); } else { // When a new person is saved, the URL will change from: // /person → /person/123 (where 123 is the new person's ID) useBindKeyToRouteOnCreate(person); }
Advanced Model Functions
The following functions exported from coalesce-vue
can be used with your models.
Note
These functions are used to implement the higher-order layers in the Vue stack.
While you're absolutely free to use them in your own code and can rely on their interface and behavior to remain consistent, you will find that you seldom need to use them directly - that's why we've split them into their own section here in the documentation.
convertToModel()
Convert any JavaScript value into a valid implementation of the value or type described by metadata.
Type
tsfunction convertToModel(value: any, metadata: Value | ClassType): any
Details
Given any JavaScript value
value
, convert it into a valid implementation of the value or type described bymetadata
.For metadata describing a primitive or primitive-like value, the input will be parsed into a valid implementation of the correct JavaScript type. For example, for
metadata
that describes a boolean, a string"true"
will return a booleantrue
, and ISO 8601 date strings will result in a JavaScriptDate
object.For metadata describing a type, the input object will be mutated into a valid implementation of the appropriate model interface. Missing properties will be set to null, and any descendent properties of the provided object will be recursively processed with
convertToModel
.If any values are encountered that are fundamentally incompatible with the requested type described by the metadata, an error will be thrown.
mapToModel()
Create a new object that is a valid implementation of the value or type described by metadata.
Type
tsfunction mapToModel(value: any, metadata: Value | ClassType): any
Details
Performs the same operations as
convertToModel
, except that any objects encountered will not be mutated - instead, a new object or array will always be created.
mapToDto()
Map a value to a representation suitable for JSON serialization.
Type
tsfunction mapToDto(value: any, metadata: Value | ClassType): any
Details
Maps the input to a representation suitable for JSON serialization.
Will not serialize child objects or collections whose metadata includes
dontSerialize
. Will only recurse to a maximum depth of 3.
modelDisplay()
Return a string representing a model suitable for display in a user interface.
Type
tsfunction modelDisplay(model: Model, options?: DisplayOptions): string
Details
Returns a string representing the
model
suitable for display in a user interface.Uses the
displayProp
defined on the object's metadata. If nodisplayProp
is defined, the object will be displayed as JSON. The display prop on a model can be defined in C# with [ListText].See DisplayOptions for available options.
propDisplay()
Return a string representing a property of a model suitable for display.
Type
tsfunction propDisplay(model: Model, prop: Property | string, options?: DisplayOptions): string
Details
Returns a string representing the specified property of the given object suitable for display in a user interface.
The property can either be a string, representing one of the model's properties, or the actual
Property
metadata object of the property.See DisplayOptions for available options.
valueDisplay()
Return a string representing a value suitable for display.
Type
tsfunction valueDisplay(value: any, metadata: Value, options?: DisplayOptions): string
Details
Returns a string representing the given value (described by the given metadata).
See DisplayOptions for available options.
DisplayOptions
The following options are available to functions in coalesce-vue that render a value or object for display:
export interface DisplayOptions {
/** Date format options. One of:
* - A UTS#35 date format string (https://date-fns.org/docs/format)
* - An object with options for https://date-fns.org/docs/format or https://github.com/marnusw/date-fns-tz#format, including a string `format` for the format itself. If a `timeZone` option is provided per https://github.com/marnusw/date-fns-tz#format, the date being formatted will be converted to that timezone.
* - An object with options for https://date-fns.org/docs/formatDistance */
format?:
| string
| ({
/** A UTS#35 date format string (https://date-fns.org/docs/format) */
format: string;
} & Parameters<typeof format>[2])
| {
/** Format date with https://date-fns.org/docs/formatDistanceToNow */
distance: true;
/** Append/prepend `'in'` or `'ago'` if date is after/before now. Default `true`. */
addSuffix?: boolean;
/** Include detail smaller than one minute. Default `false`. */
includeSeconds?: boolean;
};
collection?: {
/** The maximum number of items to display individually.
* When there are more than this number of items, the count of items will be displayed instead.
* Default `5`.
* */
enumeratedItemsMax?: number;
/** The separator to place between enumerated items. Default `', '` */
enumeratedItemsSeparator?: string;
};
}
Note
Dates rendered with the formatDistanceToNow
function into a Vue component will not automatically be updated in realtime. If this is needed, you should use a strategy like using a key that you periodically update to force a re-render.
Time Zones
In Coalesce Vue, all DateTimeOffset
-based properties, for both inputs and display-only contexts, are by default formatted into the user's computer's system time zone. This is largely just a consequence of how the JavaScript Date type works. However, this behavior can be overridden by configuring a global default timezone, or by providing a time zone name to individual usages.
Fields with a type of DateTime
are agnostic to time zone and UTC offset and so are not subject to any of the following rules.
For comprehensive information about working with dates and timezones, see Working with Dates.
setDefaultTimeZone()
Set the default time zone used by Coalesce.
Type
tsfunction setDefaultTimeZone(timeZoneName: string | null): void
Details
Sets the default time zone used by Coalesce. The time zone should be an IANA Time Zone Database name, e.g.
"America/Los_Angeles"
.The time zone provided here is used in the following ways:
- It will be used as
DisplayOptions.format.timeZone
if no other value was provided for this option. This is used by functions modelDisplay, propDisplay, and valueDisplay, as well as the c-display component. - It will be used by c-datetime-picker, used to both interpret the user input and display the selected date. This can also be set on individual component usages via the
timeZone
prop. - It will be used when serializing DateTimeOffset fields into JSON DTOs, representing the ISO 8601 date string in the specified time zone rather than in the user's computer's system time zone.
- It will be used as
getDefaultTimeZone()
Get the current configured default time zone.
Type
tsfunction getDefaultTimeZone(): string | null
Details
Returns the current configured default time zone. Default is
null
, falling back on the user's computer's system time zone.