'Use same method for inertia response and json response Laravel Jetstream
I have been using Laravel powered API and VueJS powered frontend, two separate projects for single page application. Now I want to switch to Laravel Jetstream with Inertia.js as I can create SPA in a single project. Here is an example how inertia works-
class UsersController extends Controller
{
public function index()
{
$users = User::active()
->orderByName()
->get(['id', 'name', 'email']);
return Inertia::render('Users', [
'users' => $users
]);
}
}
Now we can define Route::get('users',['UserController::class','index']);
and get user list going to localhost:8000/users
and see the user list in the web page.
My question is, can I use the same controller and method for API response to use in Mobile App?
I have to build web application and mobile application with same features. For web, I need inertia response and for mobile app, I need json response. For showing the user list in Laravel project, I can use the code above. But how do I return the same response as JSON like return response($users);
for mobile application? I can create API routes in api.php
and make separate controller or method or add condition for API or Inertia response, but I think there might be a better way to handle both Inertia and JSON response using same controller and method.
Solution 1:[1]
Yes, you can totally do that by checking wether or not request wants a json response. Something like this:
public function index()
{
$users = User::active()
->orderByName()
->get(['id', 'name', 'email']);
if (request()->wantsJson()) {
return $users;
}
return Inertia::render('Users', [
'users' => $users
]);
}
Solution 2:[2]
Being honest here, partial reloads doesn't always cut it. The reason I'm not a big fan is because most things I personally work with are Promise
based. With partial reloads, you would be using a callback. I'll show both ways you can do it since recently this has piqued my interest.
If you want to go about doing it yourself via axios for example:
<script>
import { usePage } from '@inertiajs/inertia-vue3';
const { version } = usePage();
export default {
name: 'Users',
props: {
users: Object,
},
data() {
return {
userObj: [],
loading: false,
};
},
methods: {
customReload() {
this.loading = true;
this.axios.get('/users', {
headers: {
'X-Inertia': true,
'X-Inertia-Partial-Component': 'Users',
'X-Inertia-Partial-Data': 'users',
'X-Inertia-Version': version.value,
}
}).then(({data}) => {
console.log(data.props.users);
this.userObj = data.props.users;
})
.catch(console.error)
.then(() => {
this.loading = false;
});
},
},
};
</script>
Pros
- Access ANY endpoint and get it's props
- You can access the data and manipulate it however you like
- Props are untainted(if you'd like to reference to a previous version)
Cons
- Does not update props
- Adds more code complexity
- Storing multiple objects isn't the best use of ram
Now this other approach, we can look into partial reloads.
You can call a partial reload
by calling this.$inertia.reload({ only: ['PROP_NAME_HERE'] })
, but this isn't all the parameters you can insert.
<script>
export default {
name: 'Users',
props: {
users: Object,
},
data() {
return {
loading: false,
};
},
methods: {
partialReload() {
this.loading = true;
this.$inertia.reload({
only: ['users'],
onSuccess() {
// Print new props!
console.log(this.users);
},
onBefore(PendingVisit) {},
onError(Errors) {},
onStart() {},
onProgress() {},
onComplete() {},
onAbort() {},
onCancel() {},
onFinish(ActiveVisit) {
this.loading = false;
},
});
},
},
};
</script>
Pros
- Refresh data in props as per documentation
- Less memory overhead
Con
- (bias)Callbacks
I do certainly see a point where both of these can be used. Storing the data you get from your custom axios call, may not be necessary, you could be using it for a small object prop. But point is, the option is yours!
Sources
This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.
Source: Stack Overflow
Solution | Source |
---|---|
Solution 1 | cdruc |
Solution 2 |