-
Notifications
You must be signed in to change notification settings - Fork 254
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
feat: Add Vue3 Provide/Inject Plugin #518
Conversation
src/js/vue3.js
Outdated
install: (app, options) => { | ||
const _route = (name, params, absolute, config = options) => route(name, params, absolute, options); | ||
|
||
app.config.globalProperties.route = _route; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
What exactly does this line do? Adding it to globalProperties
specifically.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Without this line, a user would have to have to inject route()
into every component, even if they don't need it in the setup()
function. This allows route()
to be used in templates globally.
The below would have to be in every Vue component that wants to use route()
.
<script>
import { inject } from 'vue';
export default {
setup() {
const route = inject('route');
return { route };
},
};
</script>
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Serving as the mixin
to make the function globally available to Vue.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Do you know if the globalProperties
thing works exactly the same as mixins? Can you still call this.route()
inside components using the Options API?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@bakerkretzmar What do you mean by "inside components" do you mean in the template or in the script? Because if it's in the script the composition API doesn't have a this
that's why traditional mixins don't work in the composition API and we need a useRoute
method, the reason being mixins are anti patterns because they are globally on the vue instance and there is a lot of conflicts between mixins of different libraries because none uses a unique name, but for the template route
remains accessible without declaring anything just like a mixin
And if youre just asking about
this.route` within template, you're pretty much not allowed to use this in a template, eslint will remove them, but if you don't have eslint then it doesn't matter because vue-template-compiler compiles them like they don't exist
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Yeah I just meant using this.route()
inside the script part of a component using the Options API.
Thanks for the PR! Making |
@bakerkretzmar I can def give it a shot to add it to the existing Vue plugin, but on the Vue 2 docs the provide/inject API is only supported in |
@bakerkretzmar After spinning up a Vue2 Inertiajs demo, I don't think it will be possible with one plugin. I believe that the Vue2 provide/inject is only from parent to child component and not possible globally. I could be wrong if you have better Vue2 chops than I do and want to give it a shot, sorry. |
I was about to make a similar PR so I'll add my 2 grains of salt, it's definitely possible to support it in a single plugin The prefered method is to export a "useRoute" method which will return the route method created when installing the plugin |
This is pretty much the PR I was gonna make import route from './index.js';
let installedRoute = null;
export const ZiggyVue = {
install: (v, options, property = 'route') => {
installedRoute = (name, params, absolute, config = options) => route(name, params, absolute, config);
if (property) {
v.config && (v.config.globalProperties[property] = installedRoute);
v.mixin && v.mixin({
methods: {
[property]: installedRoute,
},
});
}
},
};
export const useRoute = () => installedRoute; The inject provide is a good addition to support the possibility of multiple vue instances in the entry point with multiple installation of the plugin but then makes the plugin dependant on vue version and it would indeed need 2 separate plugins for vue2 and vue3 Usage in a setup import {useRoute} from "ziggy-vue";
const route = useRoute(); I updated #512 with this |
I think we can probably get this working without a separate Vue 3 plugin, Vue has a I don't want to split it out into two different plugins if possible. |
@bakerkretzmar Well, I have a version not using inject provide that does that, I'd like to use inject provide as well, the problem is with the |
Not |
I don't think you understood the issue, the problem is with |
Okay, so I have read up on this a little more and just pushed an update to this PR. @Tofandel I tested your solution and it works, but it may present some unneeded complexity with the options of changing the In the new implementation, I just pushed I also decided to remove the below line since the new version left the Vue 2 implementation unaffected.
The new version allows the Vue 2 implementation to work without any breaking changes and provides Vue 3 with Provide/Inject, also without changing the installation steps. Mixins are available in Vue 3 but there are many places in the docs saying they are no longer recommended. There are many blog posts out there listing the reasons why. I tested all the below implementations and can confirm they work. So this version provides a clear break in the plugin to align with Vue best practices, Vue 2 - Mixin is okay, Vue 3 - Provide/Inject.
Vue 2 - Unaffected<template>
<a :href="route('home')">route</a>
<a :href="url">url</a>
</template>
<script>
export default {
data() {
return {
url: this.route('home'),
}
},
};
</script> Vue 3 - Options API<template>
<a :href="route('home')">route</a>
<a :href="url">url</a>
</template>
<script>
export default {
inject: ['route'],
data() {
return {
url: this.route('home'),
}
}
}
</script> Vue 3 - Composition API<template>
<a :href="route('home')">route</a>
<a :href="url">url</a>
</template>
<script setup>
import { inject } from 'vue';
const route = inject('route');
const url = route('home');
</script> |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@c-fitzmaurice thanks a lot for digging into this further. I had another look at it last week too and landed on something very similar but forgot to come back and comment 🤦🏻
Vue 2: https://codesandbox.io/s/ziggy-vue-2-n3x2e0
Vue 3: https://codesandbox.io/s/ziggy-vue-3-xnz66z
I left a couple comments but after they're resolved I think this is ready to go. I'm on board with removing the mixin eventually but that's a significant breaking change so it'll have to wait until v2.
@bakerkretzmar Updated the PR with the code from the below as discussed. |
@c-fitzmaurice thanks a lot! |
The check should not have been on the version but just whether or not |
Installing |
Interesting find, then I guess users of vue2 composition API will have to provide it manually in their root component |
Ziggy Vue plugin allows `route()` to be injected into `setup()` function in components[1][2], which is needed for Inertia SSR since the @routes blade directive isn't available. [1]: tighten/ziggy#518 [2]: tighten/ziggy#564 (comment)
* Use Ziggy Vue plugin instead of route mixin Ziggy Vue plugin allows `route()` to be injected into `setup()` function in components[1][2], which is needed for Inertia SSR since the @routes blade directive isn't available. [1]: tighten/ziggy#518 [2]: tighten/ziggy#564 (comment) * Fix quotations * Update app.js Co-authored-by: Taylor Otwell <[email protected]>
This reverts commit 5661ec3
The ideal would be to use composables with the Vue Composition API
Provide / Inject serve to pass information from a parent component to another child component, without going through the parent component. With the "Composition API" option, using Provide/Inject is not best practice in Vue 3. |
* Use Ziggy Vue plugin instead of route mixin Ziggy Vue plugin allows `route()` to be injected into `setup()` function in components[1][2], which is needed for Inertia SSR since the @routes blade directive isn't available. [1]: tighten/ziggy#518 [2]: tighten/ziggy#564 (comment) * Fix quotations * Update app.js Co-authored-by: Taylor Otwell <[email protected]>
* Use Ziggy Vue plugin instead of route mixin Ziggy Vue plugin allows `route()` to be injected into `setup()` function in components[1][2], which is needed for Inertia SSR since the @routes blade directive isn't available. [1]: tighten/ziggy#518 [2]: tighten/ziggy#564 (comment) * Fix quotations * Update app.js Co-authored-by: Taylor Otwell <[email protected]>
This PR adds a new plugin for Vue3 using Ziggy via the Provide/Inject Composition API. Using the advanced Vue set up, I ran into my problem when trying to use
route()
insetup()
. I saw a possible solution in #454 (comment) but it didn't feel like a super maintainable solution, alsomixins
are not recommended in Vue3 anymore.For this to work, you have to update your
mix
alias like below:and the import of
ZiggyVue3
:The
route()
helper will still be registered globally and you gain the below functionality: