Bind page props to root instance? #1015
-
In the previous version of my app I had supplied information into the window itself and bound it to $user, which was then read into vue on the root instance to enable some helper functions. I was hoping to avoid doing this since inertia appears to allow me to supply the same information in the page props. I just wanted to decorate it a bit so the API is nicer. It allowed me some nicer conditionals site wide like tl;dr is there a way to decorate Update: Lessons Learned (Dec 28th, 2021)I thought I would come back in case anyone found this and was like "that's a good idea!", don't do it this way. I am posting the new way to do this, and this may be obsolete soon too as I learn more. All rebinding I ended up moving to the new api to allow me to use // GlobalBindings.ts
const useUser = () : MyAppUser => {
// @ts-ignore
return new MyAppUser(usePage().props.value.myapp.user);
} Where MyAppUser.ts is a class: class MyAppUser {
id: number | null;
name: string | null;
role: string | null;
avatar: string | null;
isLoggedIn: boolean;
permissions: string[];
constructor(user: User | null) {
if(!user) {
this.id = null;
this.role = null;
this.name = null;
this.avatar = null;
this.permissions = [];
this.isLoggedIn = false;
} else {
this.id = user.id;
this.name = user.name;
this.role = user.role;
this.avatar = user.avatar;
this.isLoggedIn = true;
this.permissions = user.permissions;
}
}
can(permission: string) {
if(!this.isLoggedIn) {
return false;
}
return this.role === 'super admin' || this.permissions.indexOf(permission) !== -1;
}
}
export default MyAppUser; This allows me to use the new API for vue 3 the same way that inertia recommends doing it. My files now look like this: <template>
<div>
<span v-if="user.can('view:whatever')">Hi</span>
</div>
</template>
<script setup lang="ts">
const user = useUser();
const pageVariableWhatever = usePage().props.value.whatever;
</script> Old Workaround (Don't do)Here is my current solution which could fall apart at any second I'm pretty sure: // AuthInjector.ts
import {App} from "vue";
import {usePage} from "@inertiajs/inertia-vue3";
export default {
install(app: App) {
Object.defineProperty(app.config.globalProperties, '$user', {
get: function() {
// @ts-ignore
return usePage().props.value.mysticwalrus.user;
}
});
}
} I added a export {}
import axios from "axios";
interface LoggedInUser {
name: string
id: number | null
role: string
permissions: string[]
}
declare module '@vue/runtime-core' {
export interface ComponentCustomProperties {
$http: typeof axios
$user: LoggedInUser
}
} In my middleware, I do the following: 'mysticwalrus' => [
'user' => fn () => $request->user() ? [
'name' => $request->user()->name,
'id' => $request->user()->id,
'role' => $request->user()->getRole(),
'permissions' => $request->user()->permissions->pluck('name'),
] : ['name' => 'guest', 'id' => null, 'role' => 'guest', 'permissions' => []]
] |
Beta Was this translation helpful? Give feedback.
Replies: 1 comment 1 reply
-
Hey @WalrusSoup |
Beta Was this translation helpful? Give feedback.
Hey @WalrusSoup
what you are currently doing is imHo totally fine. You could also use a global composable or store (like Pinia) or
provide/inject
but in the end theapp.config.globalProperties
is the easiest way to access a property globally without defining/importing over and over again.