Updating a component's props
There is two situations where you might need to update a component's prop : from the plugin that registered the component or from another plugin. Both situations are valid use cases, but they require different mechanisms.
Updating a prop from the same plugin
When the plugin that uses a component is the same one as the one registering it you can set up the reactivity directly in the definition, this way your code is more declarative and descriptive, which will make it easier to understand and reason about later on.
We saw previously that definitions are static, modifying them after the fact will not update the resulting harness or mounted component. We also saw in Describing components: Passing props that we can bind reactive values in props like we would do in a normal Vue component, so we can update this reactive value instead:
import { definePlugin } from '@xoram/core';
import { defineComponentDefinition, register } from '@xoram/plugin-panoramique';
import { ref } from 'vue';
import NewsletterSubscriptionModal from './NewsletterSubscriptionModal.vue';
export default definePlugin(setup:() => {
const email = ref(value:'');
register(definition:defineComponentDefinition(
id:'email-prompt',
type:NewsletterSubscriptionModal,
setup:({ bind }) => {
bind('email', email);
},
));
// initialize the email when the user logs in
onEvent(
target:'user',
on:'loggedIn',
handler:({ user }) => { email.value = user.email;}
);
});
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
import { definePlugin, onEvent } from '@xoram/core';
import { register } from '@xoram/plugin-panoramique';
import { ref } from 'vue';
import NewsletterSubscriptionModal from './NewsletterSubscriptionModal.vue';
export default definePlugin(setup:() => {
const email = ref(value:'');
register(definition:{
id: 'email-prompt',
type: NewsletterSubscriptionModal,
props: { email },
})
// initialize the email when the user logs in
onEvent(
target:'user',
on:'loggedIn',
handler:({ user }) => { email.value = user.email;}
);
})
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
Because email
is set as a model in NewsletterSubscriptionModal
, any changes to the value done by the user (or any other part of the application) would also be applied to the email
ref bound to the prop. This allows you to use Vue's reactivity in your plugin's code to implement more complex behaviors.
Updating a prop from another plugin
Using reactive values as props is only possible if the plugin that uses the component is also the one registering it. In some situations you might have to update a component's prop from another plugin, for example if multiple plugins need to open the same modal. In those cases you will need to update the harness value directly by overriding the existing value with another one.
To edit a harness you need to have access to it, this is done via the service's get
method, which will return a computed holding the harness corresponding to the given id :
import { definePlugin, dependsOn, onCreated } from '@xoram/core';
import { panoramiquePlugin } from '@xoram/plugin-panoramique';
import { emailPromptDefinition } from './definitions';
export default definePlugin(() => {
// remember to declare the dependency
dependsOn(panoramiquePlugin.id);
onCreated(app => {
// getting the id from the definition
let harness = app.services.panoramique.get(id:emailPromptDefinition.id);
// or using a magic string
harness = app.services.panoramique.get(id:'email-prompt');
});
});
2
3
4
5
6
7
8
9
10
11
12
13
14
15
If you provide an id that doesn't correspond to an existing harness get
will return a computed holding undefined. This computed will be updated with the corresponding harness if one is registered later on.
Harnesses are reactive object, an update to their properties will be applied to any corresponding mounted component. If we have a simple popup component that becomes visible when a isVisible
prop is set to true
:
<script setup lang="ts">
import { useTemplateRef, watchEffect } from 'vue';
const { isVisible = false } = defineProps<{ isVisible?: boolean }>();
const popover = useTemplateRef<HTMLDivElement>('popover');
watchEffect(() => {
if (isVisible) { popover.value?.showPopover(); }
});
</script>
<template>
<div class="popup" popover ref="popover">
<slot></slot>
</div>
</template>
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
We can toggle it on by simply binding a new value in the corresponding prop :
import { definePlugin, dependsOn, onCreated } from '@xoram/core';
import { panoramiquePlugin } from '@xoram/plugin-panoramique';
import { emailPromptDefinition } from './definitions';
export default definePlugin(() => {
// remember to declare the dependency
dependsOn(panoramiquePlugin.id);
onCreated(app => {
// getting the id from the definition
const harness = app.services.panoramique.get(id:emailPromptDefinition.id).value;
// make sure the harness is available
if (harness === undefined) { return; }
harness.props.isVisible = true;
});
});
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17