Skip to content

Commit

Permalink
Merge pull request #704 from andrewnicols/MDL-78324
Browse files Browse the repository at this point in the history
[docs] Update information about modal instantiation (MDL-78324)
  • Loading branch information
andrewnicols authored Sep 19, 2023
2 parents ca0df55 + c56f736 commit 4ade47c
Show file tree
Hide file tree
Showing 2 changed files with 187 additions and 32 deletions.
76 changes: 56 additions & 20 deletions docs/devupdate.md
Original file line number Diff line number Diff line change
Expand Up @@ -255,62 +255,98 @@ export default class MyModal extends Modal {
</TabItem>
</Tabs>

### Registration helper
### Instantiation and deprecation of `core/modal_factory`

<Since version="4.3" issueNumber="MDL-78306" />
<Since version="4.3" issueNumber="MDL-78324" />

Moodle 4.3 introduces a new way to instantiate modals which is significantly simpler than earlier versions. Rather than calling the `create` method on the `modal_factory`, it can now be called on the class that you are instantiating.

In addition, a new `configure` method is introduced which allows you to override configuration options, provide your own, and more.

Modals which are instantiated using the new method *do not* need to be registered if they are not consumed using the modal factory.

Moodle 4.3 introduces a new `registerModalType` method on the Modal class to aid in registering a modal.
This change will increase encapsulation and allow modals to handle common actions such as showing on creation, and removing on close much more easily.

:::note Compatibility with Moodle 4.2 and older

If your code is intended to work with Moodle 4.2 and older, then you must continue to use the old method of registration. This legacy method will be maintained until Moodle 4.6.
If your code is intended to work with Moodle 4.2 and older, then you must continue to use the existing `core/modal_factory`, and you must continue to register your modal. This legacy method will be maintained until Moodle 4.6.

:::

<Tabs groupId="beforeAfter">
<TabItem value="before" label="Before Moodle 4.3">

<InvalidExample
title="A modal using the legacy registration approach"
title="A modal created and instantiated using the legacy approach"
>
The legacy registration will continue to work and should be used if your plugin will be used in Moodle 4.2, or earlier.

```js
var MyModal = function(root) {
Modal.call(this, root);
};

MyModal.TYPE = 'mod_example/myModal';
MyModal.prototype = Object.create(Modal.prototype);
MyModal.prototype.constructor = MyModal;
```js title="mod/example/amd/src/mymodal.js"
export default class MyModal extends Modal {
static TYPE = 'mod_example/myModal';
static TEMPLATE = 'mod_example/my_modal';

myCustomSetter(value) {
this.value = value;
}
}
let registered = false;
if (!registered) {
ModalRegistry.register(MyModal.TYPE, MyModal, 'mod_example/my_modal');
registered = true;
}
```

return MyModal;
```js title="mod/example/amd/src/consumer.js"
import MyModal from './mymodal';
import ModalFactory from 'core/modal_factory';

// ...
ModalFactory.create({
TYPE: MyModal.TYPE,
}).then((modal) => {
modal.show();
modal.myCustomSetter('someValue');

return modal;
})
```

</InvalidExample>
</TabItem>

<TabItem value="after" label="From Moodle 4.3 onwards" default>
<ValidExample
title="A modal using the new shortcut helper"
title="A modal using the new approach"
>
The shortcut helper for Modal registration is suitable for Moodle 4.3 onwards.

```js
```js title="mod/example/amd/src/mymodal.js"
export default class MyModal extends Modal {
static TYPE = 'mod_example/myModal';
static TEMPLATE = 'mod_example/my_modal';

configure(modalConfig) {
// Specify any defaults you like here.
modalConfig.show = true;
super.configure(modalConfig);

this.myCustomSetter(modalConfig.myCustomValue);
}

myCustomSetter(value) {
this.value = value;
}
}
```

```js title="mod/example/amd/src/consumer.js"
import MyModal from './mymodal';

MyModal.registerModalType();
// ...
MyModal.create({
myCustomValue: 'someValue',
show: true,
});
```

</ValidExample>
Expand Down
143 changes: 131 additions & 12 deletions docs/guides/javascript/modal/index.md
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@ tags:

<Since version="3.2" />

import { CodeBlock, CodeExample, InvalidExample, ValidExample, Since } from '@site/src/components';
import { CodeBlock, CodeExample, InvalidExample, ValidExample, Since, DeprecatedSince } from '@site/src/components';

The use of modal modules provides a simplified developer experience for creating modal dialogues within Moodle.

Expand All @@ -20,6 +20,36 @@ Moodle ships with several standard modal types for you to re-use including a sim

## Creating a basic modal

<Since version="4.3" issueNumber="MDL-78324" />

Modals can be created by calling the static `create` method on the modal type you wish to create, for example:

```javascript title="Creating a stadard modal"
import Modal from 'core/modal';

export const init = async () => {
const modal = await Modal.create({
title: 'Test title',
body: '<p>Example body content</p>',
footer: 'An example footer content',
show: true,
removeOnClose: true,
});
}
```

Other standard options are described in the JS Documentation for [the MoodleConfig type](https://jsdoc.moodledev.io/master/module-core_modal.html#~MoodleConfig).

:::note Support for earlier versions

If you are supporting an earlier version of Moodle, then you must use the Modal Factory and register your modal.

:::

### Modal Factory

<DeprecatedSince version="4.3" issueNumber="MDL-78324" />

The Modal Factory can be used to instantiate a new Modal. The factory provides a `create` function, accepting some configuration which is used to create the modal instance, and an optional _trigger element_. The `create` function returns a Promise that is resolved with the created modal.

The configuration is provided as an object with key/value pairs. The options are:
Expand Down Expand Up @@ -65,7 +95,9 @@ export const init = async () => {
};
```

### Using the 'trigger'
#### Using the 'trigger'

<DeprecatedSince version="4.3" issueNumber="MDL-78324" />

Moodle Modals created using the Modal Factory support an optional _trigger_ element. Whilst this is available, it is no longer recommended and support for it will likely be removed in Moodle 4.3.

Expand Down Expand Up @@ -93,6 +125,59 @@ A number of commonly used modals are available as standard, these include:
- a Save / Cancel modal
- a Cancel modal

import Tabs from '@theme/Tabs';
import TabItem from '@theme/TabItem';

<Tabs groupId="43Split">
<TabItem value="after43" label="Moodle 4.3">
<Since version="4.3" issueNumber="MDL-78324" />

:::note

If you are developing code for use in Moodle 4.2, or earlier, then you must continue to follow the 4.2 guidelines.

:::

To use these modals you can call the `create` method on the relevant Modal Class.

```javascript title="Creating a save/cancel modal"
import ModalSaveCancel from 'core/modal_save_cancel';
import {get_string as getString} from 'core/str';

export const init = async () => {
const modal = await ModalSaveCancel.create({
title: 'test title',
body: getString('confirmchange', 'mod_example'),
});

// ...
};
```

Each type of modal may fire additional events to allow your code to handle the new functionality being offered -- for example, if you wanted to have a save/cancel modal that you did some form validation on before saving you could do something like the example below.

```javascript title="Listening to a Save event"
import ModalSaveCancel from 'core/modal_save_cancel';
import ModalEvents from 'core/modal_events';
import {get_string as getString} from 'core/str';

export const init = async () => {
const modal = await ModalSaveCancel.create({
title: 'test title',
body: getString('confirmchange', 'mod_example'),
});

modal.getRoot().on(ModalEvents.save, (e) => {
// ...
})

// ...
};
```

</TabItem>
<TabItem value="pre43" label="Moodle 4.2 and earlier">

To use these modals you can provide the `type` argument to the `ModalFactory.create` method. This argument takes a string value and values can be found for these modals in `ModalFactory.TYPES`.

```javascript title="Creating a save/cancel modal"
Expand Down Expand Up @@ -132,6 +217,9 @@ export const init = async () => {
};
```

</TabItem>
</Tabs>

## Creating a custom modal type

In some situations it is desirable to write a brand new modal.
Expand All @@ -141,19 +229,21 @@ There are two parts to this:
- a new Modal class which extends the `core/modal` class; and
- a template

Creating the Modal class is as simple as extending the `core/modal` class, providing a `TYPE` property, a `TEMPLATE` property, and registering the modal with the modal factory.
:::important Custom modals in Moodle 4.2 and earlier

Since Moodle 4.3, creating the Modal class is as simple as extending the `core/modal` class, and providing a `TYPE` property, and `TEMPLATE` property.

For older versions of Moodle, refer to the [Moodle 4.2 documentation](/versioned_docs/version-4.2/guides/javascript/modal/index.md#creating-a-custom-modal-type).

:::

```javascript title="mod/example/amd/src/my_modal.js"
import Modal from 'core/modal';
import ModalFactory from 'core/modal_factory';

export default MyModal extends Modal {
static TYPE = "mod_example/my_modal";
static TEMPLATE = "mod_example/my_modal";
}

// Modal Registration process for Moodle 4.3 onwards.
MyModal.registerModalType();
```

The template should extend the `core/modal` core template and can override any of the title, body, or footer regions, for example:
Expand Down Expand Up @@ -186,18 +276,47 @@ The template should extend the `core/modal` core template and can override any o
{{/ core/modal }}
```

Once defined, the new modal can be instantiated using the Modal Factory, for example:
Once defined, the new modal can be instantiated using the standard `create` method, for example:

```javascript title="Instantiating a custom modal"
import ModalFactory from 'core/modal_factory';
import MyModal from 'mod_example/my_modal';

export default const init = async() => {
// ...
const modal = await ModalFactory.create({
type: MyModal.TYPE,
});
const modal = await MyModal.create({});

modal.show();
}
```

### Overriding default configuration

When creating your own modal type, you may wish to override the standard configuration. This can be achieved by overriding the `configure` class and providing your own options, for example:

```javascript title="Overriding standard options"
import Modal from 'core/modal';

export default MyModal extends Modal {
static TYPE = "mod_example/my_modal";
static TEMPLATE = "mod_example/my_modal";

configure(modalConfig) {
// Show this modal on instantiation.
modalConfig.show = true;

// Remove from the DOM on close.
modalConfig.removeOnClose = true;

super.configure(modalConfig);

// Accept our own custom arguments too.
if (modalConfig.someValue) {
this.setSomeValue(someValue);
}
}

setSomeValue(value) {
this.someValue = value;
}
}
```

0 comments on commit 4ade47c

Please sign in to comment.