Browse Source

docs: Add docs on custom fields on custom entities

Relates to #1848
Michael Bromley 2 years ago
parent
commit
33d8e28869

+ 63 - 0
docs/docs/guides/developer-guide/database-entity/index.md

@@ -118,3 +118,66 @@ The full list of TypeORM decorators can be found in the [TypeORM decorator refer
 ## Corresponding GraphQL type
 
 Once you have defined a new DB entity, it is likely that you want to expose it in your GraphQL API. Here's how to [define a new type in your GraphQL API](/guides/developer-guide/extend-graphql-api/#defining-a-new-type).
+
+## Supporting custom fields
+
+From Vendure v2.2, it is possible to add support for [custom fields](/guides/developer-guide/custom-fields/) to your custom entities. This
+is useful when you are defining a custom entity as part of a plugin which is intended to be used by other developers. For example, a plugin
+which defines a new entity for storing product reviews might want to allow the developer to add custom fields to the review entity.
+
+First you need to update your entity class to implement the `HasCustomFields` interface, and provide an empty class
+which will be used to store the custom field values:
+
+```ts title="src/plugins/reviews/entities/product-review.entity.ts"
+import {
+    DeepPartial,
+    HasCustomFields,
+    Product,
+    VendureEntity,
+} from '@vendure/core';
+import { Column, Entity, ManyToOne } from 'typeorm';
+
+// highlight-next-line
+export class CustomProductReviewFields {}
+
+@Entity()
+// highlight-next-line
+export class ProductReview extends VendureEntity implements HasCustomFields {
+    constructor(input?: DeepPartial<ProductReview>) {
+        super(input);
+    }
+
+    // highlight-start
+    @Column(type => CustomProductReviewFields)
+    customFields: CustomProductReviewFields;
+    // highlight-end
+    
+    @ManyToOne(type => Product)
+    product: Product;
+
+    @EntityId()
+    productId: ID;
+
+    @Column()
+    text: string;
+
+    @Column()
+    rating: number;
+}
+```
+
+Now you'll be able to add custom fields to the `ProductReview` entity via the VendureConfig:
+
+```ts title="src/vendure-config.ts"
+import { VendureConfig } from '@vendure/core';
+
+export const config: VendureConfig = {
+    // ...
+    customFields: {
+        ProductReview: [
+            { name: 'reviewerName', type: 'string' },
+            { name: 'reviewerLocation', type: 'string' },
+        ],
+    },
+};
+```

+ 95 - 0
docs/docs/guides/extending-the-admin-ui/creating-detail-views/index.md

@@ -235,3 +235,98 @@ export default [
     // highlight-end
 ]
 ```
+
+## Supporting custom fields
+
+From Vendure v2.2, it is possible for your [custom entities to support custom fields](/guides/developer-guide/database-entity/#supporting-custom-fields).
+
+If you have set up your entity to support custom fields, and you want custom fields to be available in the Admin UI detail view,
+you need to add the following to your detail component:
+
+```ts title="src/plugins/reviews/ui/components/review-detail/review-detail.component.ts"
+// highlight-next-line
+import { getCustomFieldsDefaults } from '@vendure/admin-ui/core';
+
+@Component({
+    selector: 'review-detail',
+    templateUrl: './review-detail.component.html',
+    styleUrls: ['./review-detail.component.scss'],
+    changeDetection: ChangeDetectionStrategy.OnPush,
+    standalone: true,
+    imports: [SharedModule],
+})
+export class ReviewDetailComponent extends TypedBaseDetailComponent<typeof getReviewDetailDocument, 'review'> implements OnInit, OnDestroy {
+
+    // highlight-next-line
+    customFields = this.getCustomFieldConfig('ProductReview');
+
+    detailForm = this.formBuilder.group({
+        title: [''],
+        rating: [1],
+        authorName: [''],
+        // highlight-next-line
+        customFields: this.formBuilder.group(getCustomFieldsDefaults(this.customFields)),
+    });
+
+    protected setFormValues(entity: NonNullable<ResultOf<typeof getReviewDetailDocument>['review']>, languageCode: LanguageCode): void {
+        this.detailForm.patchValue({
+            title: entity.name,
+            rating: entity.rating,
+            authorName: entity.authorName,
+            productId: entity.productId,
+        });
+        // highlight-start
+        if (this.customFields.length) {
+            this.setCustomFieldFormValues(this.customFields, this.detailForm.get('customFields'), entity);
+        }
+        // highlight-end
+    }
+}
+```
+
+Then add a card for your custom fields to the template:
+
+```html title="src/plugins/reviews/ui/components/review-detail/review-detail.component.html"
+<form class="form" [formGroup]="detailForm">
+    <vdr-page-detail-layout>
+        <!-- The sidebar is used for displaying "metadata" type information about the entity -->
+        <vdr-page-detail-sidebar>
+            <vdr-card *ngIf="entity$ | async as entity">
+                <vdr-page-entity-info [entity]="entity" />
+            </vdr-card>
+        </vdr-page-detail-sidebar>
+
+        <!-- The main content area is used for displaying the entity's fields -->
+        <vdr-page-block>
+            <!-- The vdr-card is the container for grouping items together on a page -->
+            <!-- it can also take an optional [title] property to display a title -->
+            <vdr-card>
+                <!-- the form-grid class is used to lay out the form fields -->
+                <div class="form-grid">
+                    <vdr-form-field label="Title" for="title">
+                        <input id="title" type="text" formControlName="title" />
+                    </vdr-form-field>
+                    <vdr-form-field label="Rating" for="rating">
+                        <input id="rating" type="number" min="1" max="5" formControlName="rating" />
+                    </vdr-form-field>
+
+                    <!-- etc -->
+                </div>
+            </vdr-card>
+            // highlight-start
+            <vdr-card
+                    formGroupName="customFields"
+                    *ngIf="customFields.length"
+                    [title]="'common.custom-fields' | translate"
+            >
+                <vdr-tabbed-custom-fields
+                        entityName="ProductReview"
+                        [customFields]="customFields"
+                        [customFieldsFormGroup]="detailForm.get('customFields')"
+                ></vdr-tabbed-custom-fields>
+            </vdr-card>
+            // highlight-end
+        </vdr-page-block>
+    </vdr-page-detail-layout>
+</form>
+```

+ 85 - 0
docs/docs/guides/extending-the-admin-ui/creating-list-views/index.md

@@ -244,3 +244,88 @@ export default [
     // highlight-end
 ]
 ```
+
+## Supporting custom fields
+
+From Vendure v2.2, it is possible for your [custom entities to support custom fields](/guides/developer-guide/database-entity/#supporting-custom-fields).
+
+If you have set up your entity to support custom fields, and you want custom fields to be available in the Admin UI list view,
+you need to add the following to your list component:
+
+```ts title="src/plugins/reviews/ui/components/review-list/review-list.component.ts"
+@Component({
+    selector: 'review-list',
+    templateUrl: './review-list.component.html',
+    styleUrls: ['./review-list.component.scss'],
+    changeDetection: ChangeDetectionStrategy.OnPush,
+    standalone: true,
+    imports: [SharedModule],
+})
+export class ReviewListComponent extends TypedBaseListComponent<typeof getReviewListDocument, 'reviews'> {
+
+    // highlight-next-line
+    customFields = this.getCustomFieldConfig('ProductReview');
+
+    readonly filters = this.createFilterCollection()
+        .addIdFilter()
+        .addDateFilters()
+        .addFilter({
+            name: 'title',
+            type: {kind: 'text'},
+            label: 'Title',
+            filterField: 'title',
+        })
+        .addFilter({
+            name: 'rating',
+            type: {kind: 'number'},
+            label: 'Rating',
+            filterField: 'rating',
+        })
+        .addFilter({
+            name: 'authorName',
+            type: {kind: 'text'},
+            label: 'Author',
+            filterField: 'authorName',
+        })
+        // highlight-next-line
+        .addCustomFieldFilters(this.customFields)
+        .connectToRoute(this.route);
+
+    readonly sorts = this.createSortCollection()
+        .defaultSort('createdAt', 'DESC')
+        .addSort({name: 'createdAt'})
+        .addSort({name: 'updatedAt'})
+        .addSort({name: 'title'})
+        .addSort({name: 'rating'})
+        .addSort({name: 'authorName'})
+        // highlight-next-line
+        .addCustomFieldSorts(this.customFields)
+        .connectToRoute(this.route);
+    
+    // rest of class omitted for brevity
+}
+```
+
+and then add the `vdr-dt2-custom-field-column` component to your data table:
+
+```html title="src/plugins/reviews/ui/components/review-list/review-list.component.html"
+<vdr-data-table-2
+    id="review-list"
+    [items]="items$ | async"
+    [itemsPerPage]="itemsPerPage$ | async"
+    [totalItems]="totalItems$ | async"
+    [currentPage]="currentPage$ | async"
+    [filters]="filters"
+    (pageChange)="setPageNumber($event)"
+    (itemsPerPageChange)="setItemsPerPage($event)"
+>
+    <!-- rest of data table omitted for brevity -->
+    // highlight-start
+    <vdr-dt2-custom-field-column
+            *ngFor="let customField of customFields"
+            [customField]="customField"
+            [sorts]="sorts"
+    />
+    // highlight-end
+</vdr-data-table-2>
+```