Skip to content

Commit 5bb6f82

Browse files
committed
docs: viewmodel improvements
1 parent c63a148 commit 5bb6f82

File tree

2 files changed

+32
-26
lines changed

2 files changed

+32
-26
lines changed

docs/modeling/model-types/dtos.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -166,7 +166,7 @@ public class CaseDtoSource : ProjectedDtoDataSource<Case, CaseDto, AppDbContext>
166166
## Surgical Saves
167167

168168
<!-- MARKER:surgical-saves-warning -->
169-
Surgical saves require DTOs on the server that can determine which of their properties have been set by the model binder, as surgical saves are sent from the client by entirely omitting properties from the ``x-www-form-urlencoded`` body that is sent to the server.
169+
Surgical saves require DTOs on the server that can determine which of their properties have been set by the model binder, as surgical saves are sent from the client by entirely omitting properties from the HTTP request body that is sent to the server.
170170

171171
The [Generated C# DTOs](/stacks/agnostic/dtos.md) implement the necessary logic for this; however, any [Custom DTOs](/modeling/model-types/dtos.md) must have this logic manually written by you, the developer. Either implement the same pattern that can be seen in the [Generated C# DTOs](/stacks/agnostic/dtos.md), or do not use surgical saves with Custom DTOs.
172172
<!-- MARKER:end-surgical-saves-warning -->

docs/stacks/vue/layers/viewmodels.md

Lines changed: 31 additions & 25 deletions
Original file line numberDiff line numberDiff line change
@@ -1,12 +1,14 @@
1-
# ViewModels
1+
# View Models
22

33
<!-- MARKER:summary -->
44

5-
Coalesce's generated TypeScript ViewModels provide rich, stateful wrappers around your data model types that handle common UI concerns like loading, saving, validation, and auto-save functionality. They serve as the primary interface between your Vue components and your backend APIs, offering features like automatic dirty tracking on property changes, API callers with loading/error states, and transactional bulk save operations.
5+
Coalesce's generated TypeScript ViewModels provide rich, stateful wrappers around your [CRUD Models](/modeling/model-types/crud.md) and [Services](/modeling/model-types/services.md) that handle common UI concerns like loading, saving, validation, and auto-save functionality. They serve as the primary interface between your Vue components and your backend APIs, offering features like automatic dirty tracking on property changes, API callers with loading/error states, and transactional bulk save operations.
66

7-
The ViewModels are generated as `viewmodels.g.ts` and export a ViewModel class for each API-backed type in your data model ([CRUD Models](/modeling/model-types/crud.md) and [Services](/modeling/model-types/services.md)), as well as a ListViewModel type for [CRUD Models](/modeling/model-types/crud.md).
7+
The ViewModels are generated as `viewmodels.g.ts` and export the following:
88

9-
These classes provide a wide array of functionality that is useful when interacting with your data model through a user interface. The generated ViewModels are the primary way that Coalesce is used when developing a Vue application.
9+
- A [ViewModel](#viewmodels) type for each [CRUD Model](/modeling/model-types/crud.md).
10+
- A [ListViewModel](#listviewmodels) type for each [CRUD Model](/modeling/model-types/crud.md).
11+
- A [ServiceViewModel](#service-viewmodels) for each [Service](/modeling/model-types/services.md).
1012

1113
<!-- MARKER:summary-end -->
1214

@@ -22,34 +24,38 @@ Changing the value of a property will automatically flag that property as dirty.
2224

2325
There are a few special behaviors when assigning to different kinds of data properties on View Models as well:
2426

25-
#### Model Object Properties
26-
- If the object being assigned to the property is not a ViewModel instance, a new instance will be created automatically and used instead of the incoming object.
27-
- If the model property is a reference navigation, the corresponding foreign key property will automatically be set to the primary key of that object. If the incoming value was null, the foreign key will be set to null.
28-
- If deep auto-saves are enabled on the instance being assigned to, auto-save will be spread to the incoming object, and to all other objects reachable from that object.
27+
- **Model Object Properties**
2928

30-
#### Model Collection Properties
31-
- When assigning an entire array, any items in the array that are not a ViewModel instance will have an instance created for them.
32-
- The same rule goes for pushing items into the existing array for a model collection - a new ViewModel instance will be created and used instead of the object(s) being pushed.
29+
If the object being assigned to the property is not a ViewModel instance, a new instance will be created and used instead of the incoming object.
30+
If model property is a reference navigation, the corresponding foreign key property will be set to the primary key of that object.
31+
32+
- **Model Collection Properties**
33+
34+
When assigning an entire array, any items in the array that are not a ViewModel instance will have an instance created for them.
35+
The same rule goes for pushing items into the existing array for a model collection - a new ViewModel instance will be created and used instead of the object(s) being pushed.
3336

34-
#### Foreign Key Properties
35-
- If the corresponding navigation property contains an object, and that object's primary key doesn't match the new foreign key value being assigned, the navigation property will be set to null.
37+
- **Foreign Key Properties**
3638

39+
If the corresponding navigation property contains an object, and that object's primary key doesn't match the new foreign key value being assigned, the navigation property will be set to null.
3740

3841

39-
### Other Generated Members
42+
In addition to the getters and setters for the model's basic data properties, the following are also generated:
4043

41-
#### API Callers
42-
- For each of the instance [Methods](/modeling/model-components/methods.md) of the type, an [API Caller](/stacks/vue/layers/api-clients.md#api-callers) will be generated.
44+
- **API Callers**
4345

44-
#### `addTo*()` Functions
45-
- For each [collection navigation property](/modeling/model-components/properties.md), a method is generated that will create a new instance of the ViewModel for the collected type, add it to the collection, and then return the new object.
46+
For each of the instance [Methods](/modeling/model-components/methods.md) of the type, an [API Caller](/stacks/vue/layers/api-clients.md#api-callers) will be generated.
47+
48+
- **`addTo*()` Functions**
49+
50+
For each [collection navigation property](/modeling/model-components/properties.md), a method is generated that will create a new instance of the ViewModel for the collected type, add it to the collection, and then return the new object.
4651

47-
#### Many-to-many helper collections
48-
- For each [[ManyToMany]](/modeling/model-components/attributes/many-to-many.md) [collection navigation property](/modeling/model-components/properties.md), a getter-only property is generated that returns a collection of the object on the far side of the many-to-many relationship. Nulls are filtered from this collection.
52+
- **Many-to-many helper collections**
53+
54+
For each [[ManyToMany]](/modeling/model-components/attributes/many-to-many.md) [collection navigation property](/modeling/model-components/properties.md), a getter-only property is generated that returns a collection of the object on the far side of the many-to-many relationship. Nulls are filtered from this collection.
4955

5056

5157

52-
### Data Properties & Functions
58+
### Data & Display
5359

5460
<Prop def="readonly $metadata: ModelType" lang="ts" />
5561

@@ -68,7 +74,7 @@ Useful for uniquely identifying instances with ``:key="vm.$stableId"`` in a Vue
6874
A getter/setter property that wraps the primary key of the model. Used to interact with the primary key of any ViewModel in a polymorphic way.
6975

7076

71-
<Prop def="$display(prop?: string | Property): string" lang="ts" />
77+
<Prop def="$display(prop?: string | Property, options?: DisplayOptions): string" lang="ts" />
7278

7379
Returns a string representation of the object, or one of its properties if specified, suitable for display.
7480

@@ -105,7 +111,7 @@ Getter/setter wrapper around `$params.dataSource`. Takes an instance of a [Data
105111
Getter/setter wrapper around `$params.includes`. See [Includes String](/concepts/includes.md) for more information.
106112

107113

108-
<Prop def="$loadCleanData(source: {} | TModel, purgeUnsaved = false)" lang="ts" />
114+
<Prop def="$loadCleanData(source: DeepPartial<TModel>, purgeUnsaved = false)" lang="ts" />
109115

110116
Loads data from the provided model into the current ViewModel, and then clears all dirty flags.
111117

@@ -116,11 +122,11 @@ If auto-save is enabled, only non-dirty properties are updated. This prevents us
116122
If `purgeUnsaved` is true, items without a primary key will be dropped from collection navigation properties. This is used by the `$load` caller in order to fully reset the object graph with the state from the server.
117123

118124

119-
<Prop def="$loadDirtyData(source: {} | TModel)" lang="ts" />
125+
<Prop def="$loadDirtyData(source: DeepPartial<TModel>)" lang="ts" />
120126

121127
Same as `$loadCleanData`, but does not clear any existing dirty flags, nor does it clear any dirty flags that will be set while mutating the data properties of any ViewModel instance that gets loaded.
122128

123-
<Prop def="constructor(initialDirtyData?: {} | TModel | null)" lang="ts" />
129+
<Prop def="constructor(initialDirtyData?: DeepPartial<TModel> | null)" lang="ts" />
124130

125131
Create a new instance of the ViewModel, loading the given initial data with `$loadDirtyData()` if provided.
126132

0 commit comments

Comments
 (0)