Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Refines the create template function APIs #866

Merged
merged 2 commits into from
Dec 1, 2020
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
8 changes: 4 additions & 4 deletions docs/en/resources/introduction.md
Original file line number Diff line number Diff line change
Expand Up @@ -15,18 +15,18 @@ Dojo Resources is designed to provide a consistent pattern to make widgets "reso

In order to work with Dojo resources, widgets need to use the `resource` middleware created with the `createResourceMiddleware` factory from `@dojo/framework/middleware/resources`. There are two types of "resource-aware" widgets: widgets that expose a `resource` on their property API and widgets that need to use a resource internally. The same factory is used to create both types of middleware, but the main difference is for widgets that require resources to be passed via properties, a resource type is needed on creation.

Using the `resource` middleware enables working with resource templates in your widget. Resources templates are created using the `createResourceTemplate` and `createResourceTemplateWithInit` factories from `@dojo/framework/middleware/resources`. Dojo resources also provides a utility factory `createMemoryResourceTemplate` which can be used to create a resource template that can be populated on initialization and works with the data in the client. The initialization includes a `data` and an `id` that is required to identify the instance of the resource and is passed with `template` into the `resource` middleware to use with a "resource" aware widget.
Using the `resource` middleware enables working with resource templates in your widget. Resources templates are created using the `createResourceTemplate` factory from `@dojo/framework/middleware/resources`. If a custom template is not passed to the `createResourceTemplate` factory the default resources template will be used. The default template required `initOptions` which include `data` and an `id` to identify the instance of the resource and is passed with `template` into the `resource` middleware to use with a "resource" aware widget.

> App.tsx

```tsx
import { create, tsx } from '@dojo/framework/core/vdom';
import { createMemoryResourceTemplate, createResourceMiddleware } from '@dojo/framework/core/middleware/resources';
import { createResourceTemplate, createResourceMiddleware } from '@dojo/framework/core/middleware/resources';
import DataAwareWidget from './DataAwareWidget';

const resource = createResourceMiddleware();
const factory = create({ resource });
const myTemplate = createMemoryResourceTemplate<{ foo: string }>();
const myTemplate = createResourceTemplate<{ foo: string }>();

const App = factory(function App({ id, middleware: { resource } }) {
return <DataAwareWidget resource={resource({ template, initOptions: { id, data: [{ foo: 'string' }] } })} />;
Expand Down Expand Up @@ -72,7 +72,7 @@ interface ResourceData {
value: string;
}

const resource = createDataMiddleware<ResourceData>();
const resource = createResourceMiddleware<ResourceData>();

const factory = create({ resource });

Expand Down
22 changes: 11 additions & 11 deletions docs/en/resources/supplemental.md
Original file line number Diff line number Diff line change
Expand Up @@ -232,14 +232,14 @@ The `type` describes how to use the query to find the item in the resource, ther

## `init()`

The `init` function is used to deal with options passed with the `template` using the `resource` middleware. These options are defined when creating the template using `createResourceTemplateWithInit` as the second generic parameter.
The `init` function is used to deal with options passed with the `template` using the `resource` middleware. These options are defined when creating the template and passing an interface for the required options, `createResourceTemplate<RESOURCE, INIT>` as the second generic parameter.

```tsx
import { createResourceTemplateWithInit } from '@dojo/framework/core/middleware/resources';
import { createResourceTemplate } from '@dojo/framework/core/middleware/resources';


// only showing the init api
const template = createResourceTemplateWithInit<{ foo: string }, { data: { foo: string; }[]; extra: number; }>({
const template = createResourceTemplate<{ foo: string }, { data: { foo: string; }[]; extra: number; }>({
init: (options, controls) {
// the options matches the type passed as the second generic
const { data, extra } = options;
Expand All @@ -260,15 +260,15 @@ export interface ResourceInit<S, I> {

The init options are injected into the function along with the standard `ResourceControls` to be used to add the initialize the resource store.

## Memory Resource Templates
## Default Resource Templates

Dojo resources offers a pre-configured memory resource template that implements the complete resource template API. The memory template is designed to work with [data passed to a widget when using the template](/learn/resources/using-resource-templates) that initializes the resource store for the template. The memory template is created using the `createMemoryResourceTemplate` factory from `@dojo/framework/core/middleware/resources`, with the type of the resource data being passed to the factory.
Dojo resources offers a pre-configured default resource template that implements the complete resource template API. The default template is designed to work with [data passed to a widget when using the template](/learn/resources/using-resource-templates) that initializes the resource store for the template. The memory template is created using the `createResourceTemplate` factory from `@dojo/framework/core/middleware/resources` passing no arguments.

> MyWidget.tsx

```tsx
import { create, tsx } from '@dojo/framework/core/vdom';
import { createMemoryResourceTemplate, createResourceMiddleware } from '@dojo/framework/core/middleware/resources';
import { createResourceTemplate, createResourceMiddleware } from '@dojo/framework/core/middleware/resources';

interface ResourceItem {
value: string;
Expand All @@ -281,7 +281,7 @@ interface MyWidgetProperties {
const resource = createResourceMiddleware();
const factory = create({ resource }).properties<MyWidgetProperties>();

const template = createMemoryResourceTemplate<ResourceItem>();
const template = createResourceTemplate<ResourceItem>();

export default factory(function MyWidget({ id, properties, middleware: { resource } }) {
const { items } = properties();
Expand Down Expand Up @@ -328,18 +328,18 @@ export default createResourceTemplate<MyResource>({

### Create a Resource Template with initialization options

If the resource template needs to support custom initialization the `createResourceTemplateWithInit` can be used. This requires the template to have an `init` API that will be called when a backing resource is created. The initialize options required are typed using the second generic on the factory function.
If the resource template needs to support custom initialization the `createResourceTemplate` can be used. This requires the template to have an `init` API that will be called when a backing resource is created. The initialize options required are typed using the second generic on the factory function.

```tsx
import { createResourceTemplateWithInit } from '@dojo/framework/core/middleware/resources';
import { createResourceTemplate } from '@dojo/framework/core/middleware/resources';

interface MyResource {
id: string;
name: string;
email: string;
}

export default createResourceTemplateWithInit<MyResource, { data: MyResource[] }>({
export default createResourceTemplate<MyResource, { data: MyResource[] }>({
init: (request: { id: string } & { data: MyResource[] }, controls: ResourceControls) => {
const { data } = request;
// adds any data passed with the template to resource store
Expand Down Expand Up @@ -422,7 +422,7 @@ export factory(function MyWidget({ middleware: { resource }}) {

## Passing Initialization Options

Initialization options can be passed with any template created using the `createResourceTemplateWithInit` factory and are passed to the template's `init` function to initialize the resource. The `initOptions` includes an `id` used to identify the backing resource and optional `data` that can be added to the resource on creation.
Initialization options can be passed with any template created using the `createResourceTemplate` factory and are passed to the template's `init` function to initialize the resource. The `initOptions` includes an `id` used to identify the backing resource and optional `data` that can be added to the resource on creation.

> MyWidget.ts

Expand Down
38 changes: 25 additions & 13 deletions src/core/middleware/resources.ts
Original file line number Diff line number Diff line change
Expand Up @@ -301,23 +301,35 @@ interface ResourceMiddleware<MIDDLEWARE = {}> {
): boolean;
}

export function createResourceTemplate<RESOURCE = void>(
template: ResourceTemplate<RESOURCE>
): ResourceTemplate<RESOURCE> & { type: 'standard' } {
return template as ResourceTemplate<RESOURCE> & { type: 'standard' };
export function createResourceTemplate<RESOURCE = void>(): ResourceTemplateWithInit<RESOURCE, { data: RESOURCE[] }> & {
type: 'init';
};
export function createResourceTemplate<RESOURCE = void, INIT = void>(
template: INIT extends void ? ResourceTemplate<RESOURCE> : ResourceTemplateWithInit<RESOURCE, INIT>
): INIT extends void
? ResourceTemplate<RESOURCE> & { type: 'standard' }
: ResourceTemplateWithInit<RESOURCE, INIT> & { type: 'init' };
export function createResourceTemplate(template?: any): any {
if (template) {
return template;
}
return { ...memoryTemplate };
}

export function createResourceTemplateWithInit<RESOURCE = void, INIT = never>(
/**
* @deprecated Please use `createResourceTemplate` instead
*/
export function createResourceTemplateWithInit<RESOURCE = void, INIT = {}>(
template: ResourceTemplateWithInit<RESOURCE, INIT>
): ResourceTemplateWithInit<RESOURCE, INIT> & { type: 'init' } {
return template as ResourceTemplateWithInit<RESOURCE, INIT> & { type: 'init' };
) {
return createResourceTemplate<RESOURCE, INIT>(template as any);
}

export function createMemoryResourceTemplate<RESOURCE = void>(): ResourceTemplateWithInit<
RESOURCE,
{ data: RESOURCE[] }
> & { type: 'init' } {
return { ...memoryTemplate } as ResourceTemplateWithInit<RESOURCE, { data: RESOURCE[] }> & { type: 'init' };
/**
* @deprecated Please use `createResourceTemplate` instead
*/
export function createMemoryResourceTemplate<RESOURCE = void>() {
return createResourceTemplate<RESOURCE>();
}

export function defaultFilter(query: ResourceQuery<any>, item: any, type: string = 'contains') {
Expand Down Expand Up @@ -985,7 +997,7 @@ const resourceMiddlewareFactory = factory(
) => {
if (!nextProp || !nextProp.template) {
return middleware({
template: createMemoryResourceTemplate(),
template: createResourceTemplate(),
initOptions: { data: [], id: '' },
...nextProp
});
Expand Down
Loading