Michael added a comment.
Using vuejs dependency injections API `provide`/`inject` in practice -------------------------------------------------------------------- In the design system (and query builder) we need a component to toggle between two options. To make it easier to adjust the contents of the individual options, we decided to go with one wrapping component that get's the individual buttons in its default slot. Like so: <ToggleButtonGroup> <ToggleButton> <ToggleButton> <ToggleButton> </ToggleButtonGroup> However, we also would like the wrapping component, i.e. ToggleButtonGroup, to do the internal state management for us. That creates a challenge, because usually components do not have meaningful access to the content in their slots, let alone listen to their events or tell them which `isActive` prop they are supposed to have. That being said, it has to be possible, because that is exactly the functionality that vuetify <https://vuetifyjs.com/en/components/button-groups/#usage> provides: <v-btn-toggle v-model="toggle_exclusive"> <v-btn> <v-icon>mdi-format-align-left</v-icon> </v-btn> <v-btn> <v-icon>mdi-format-align-center</v-icon> </v-btn> <v-btn> <v-icon>mdi-format-align-right</v-icon> </v-btn> <v-btn> <v-icon>mdi-format-align-justify</v-icon> </v-btn> </v-btn-toggle> The scavenger hunt to figure out what they are doing lead through vuetify's registrable <https://github.com/vuetifyjs/vuetify/blob/f33d0c1356c5eb3a685c86f754bdf85c5dd706d0/packages/vuetify/src/mixins/registrable/index.ts> mixin, used in their groupable <https://github.com/vuetifyjs/vuetify/blob/f33d0c1356c5eb3a685c86f754bdf85c5dd706d0/packages/vuetify/src/mixins/groupable/index.ts> mixin used in their VBtn <https://github.com/vuetifyjs/vuetify/blob/f33d0c1356c5eb3a685c86f754bdf85c5dd706d0/packages/vuetify/src/components/VBtn/VBtn.ts> component with the methods defined in the ItemGroup <https://github.com/vuetifyjs/vuetify/blob/f33d0c1356c5eb3a685c86f754bdf85c5dd706d0/packages/vuetify/src/components/VItemGroup/VItemGroup.ts#L126-L170> component. The solution is that they are using provide/inject to register the `<v-btn>` buttons in the slot inside the `<v-btn-toggle>`. Our own solution is somewhat less sophisticated, but still has to make use of the provide/inject API that vuejs provides for dependency injection (vue2 docs <https://vuejs.org/v2/api/#provide-inject>, vue3 docs <https://v3.vuejs.org/guide/component-provide-inject.html>). In the Proof of Concept <https://github.com/wmde/wikit/pull/358> for the ToggleButtonGroup, we are providing a listener for each button and a method to get the currently selected value for the group: export interface ToggleButtonGroupInjection { groupValue: ( () => string ) | null; toggleListener: ( ( value: string ) => void ) | null; } export default Vue.extend( { name: 'ToggleButtonGroup', provide(): ToggleButtonGroupInjection { return { groupValue: (): string => this.value, toggleListener: ( event: string ): void => { this.$emit( 'input', event ); }, }; }, // props etc. } ); That is then injected in the ToggleButton: import { ToggleButtonGroupInjection } from '@/components/ToggleButtonGroup.vue'; export default ( Vue as VueConstructor<Vue & ToggleButtonGroupInjection> ).extend( { name: 'ToggleButton', methods: { onClick(): void { if ( this.toggleListener !== null ) { this.toggleListener( this.value ); return; } /** * only emitted when not use as part of a ToggleButtonGroup */ this.$emit( 'click' ); }, }, inject: { groupValue: { default: null }, toggleListener: { default: null }, } as Record<keyof ToggleButtonGroupInjection, object>, computed: { buttonIsActive(): boolean { if ( this.groupValue !== null ) { return this.groupValue() === this.value; } return this.isActive; }, }, // props etc. } ); Note the line export default ( Vue as VueConstructor<Vue & ToggleButtonGroupInjection> ).extend( { That is needed so that TypeScript knows about these two fields on `this`. That way it is possible to directly transfer knowledge between a component and the children in its slots. TASK DETAIL https://phabricator.wikimedia.org/T272460 EMAIL PREFERENCES https://phabricator.wikimedia.org/settings/panel/emailpreferences/ To: Michael Cc: Michael, Charlie_WMDE, Aklapper, Sarai-WMDE, Lydia_Pintscher, Akuckartz, Nandana, Lahi, Gq86, GoranSMilovanovic, QZanden, LawExplorer, _jensen, rosalieper, Scott_WUaS, Wikidata-bugs, aude, Mbch331
_______________________________________________ Wikidata-bugs mailing list Wikidata-bugs@lists.wikimedia.org https://lists.wikimedia.org/mailman/listinfo/wikidata-bugs