Is it possible for nuxt to determine what page is using the /slug path? - laravel

I have a post page and a category page in my project as well as the usual internal pages.
Right now I have the following structure in the pages folder:
pages/category/_id.vue - I send a request for a category
pages/post/_id.vue - send request for post
pages/page/_id.vue - send request for page.
The api for the project is written in laravel (don't know if it matters).
I want nuxt to know which request to send, to fetch category or post, and then choose desired template to display category or post. If there is no category or post, then make redirect to the page 404. Is it possible?

The API provider doesn't matter in this case. Only the logic within Vue/Nuxt page template lifecycle.
Every page template so category / post / page with provided id can use different endpoint to fetch the data from API.
Which Nuxt? 2 or 3?
In Nuxt 2 You should use asyncData of specific page template ex: post:
async asyncData ({ store, $axios, params, error }) {
return $axios.get(`${apiEndpoint}/posts`, {
params: {
id: params.id
}
}).then(item => {
if (item.data.length === 0) throw({ statusCode: 404, message: 'Post not found' })
return { item: item.data[0] }
}).catch(e => {
error(e)
})
}
If You want to force 404:
try {
} catch (err) {
if (err.response.status === 404) {
return this.$nuxt.error({ statusCode: 404, message: err.message })
}
}

Related

How to redirect NotFound() to my custom 404 page in ASP.NET Core 6 MVC

In Program.cs I have added this middleware:
app.Use(async (context, next) =>
{
await next();
if (context.Response.StatusCode == 404)
{
context.Request.Path = "/404";
await next();
}
});
And just after in my endpoints I have the 404 route setup:
endPoints.MapControllerRoute(
name: "404",
pattern: "404",
defaults: new { controller = "Error", action = "Error404" });
While this works in general, I've noticed for actions where I am calling a return NotFound() it isn't displaying my custom 404 page. I'm presuming because the middleware isn't caught as it is set up before the endpoints.
I tried replacing my calls with a return RedirectToRoute("404") which works however the url the user see's is simply /404 where I want to display my custom 404 page while retaining the url for the user (which is the default behavior of the middleware above)
How can I achieve this?

Send POST request to Laravel web.php route

I have a simple Vue app in which I am sending POST request with options (table filtering variables) to the back-end. I want to be able to destructure the object and debug it in my TestController in Laravel 8, so I want to send the options to web.php via URL, not to api.php. Since options is an object, I cannot just drop it in the URL.
Ultimately I want to be able to preview my Laravel respond in browser, so I know it returns correct data from server.
So how can I achieve this?
in Vue FormComponent <form #submit="formSubmit"> and script
function formSubmit(e) {
e.preventDefault();
let currentObj = this;
axios.post('/formSubmit', {
name: this.name,
description: this.description
}).then(function(response) {
currentObj.output = response.data;
console.log(currentObj);
}).catch(function(error) {
currentObj.output = error;
});
}
Firstable, create POST route for your request. Then just make POST request to this route url and put your POST params (your object) to request body. You can use Axios as example
let filterOptions = {...};
axios.post(url, filterOptions).then().catch();
UPD And response for your request you can see in browser developer console on network tab

Laravel: Redirect the user to a custom 404 page when the given params are invalid

I made an application where a user can create some papers and see all data in a template. Every paper has a joincode which is generated at its creation.
I defined the join route in my web.php like this:
Route::get('/conceptPaper/lobby/{joincode}', 'App\Http\Controllers\ConceptPaperController#join');
and the join function in the controller the following way:
public function join($joincode)
{
try {
$conceptPaper = ConceptPaper::where('join_code', $joincode)->firstOrFail();
return response()->json($conceptPaper);
} catch(ModelNotFoundException $e)
{
return view('errors.404');
}
}
I used firstOrFail to check if the join code exists. If it exists it should return a response, otherwise it should redirect the user to a custom 404 page.
I created a custom component which gets the join code as a route param and shows the concept paper
{
path: '/conceptPaper/lobby/:joincode',
name: 'conceptPaper',
component: () => import('./views/ConceptPaper.vue')
},
So when the user joins a lobby with the right code he gets redirected to the page with all data from the corresponding paper:
showPaper: async function (conceptPaper) {
const joinCode = conceptPaper.join_code;
this.$router.push({ name: "conceptPaper", params: { joincode: joinCode }, });
},
My problem is that when the user types in the wrong code he still gets redirected to the view. When I check the response in the network tab its shows the 404 page.
I think I built it fundamentally wrong. Can anyone tell me how to do it the right way? When the suer types in the correct join code he should see the ConceptPaper.vue view. When the code is wrong he should be redirected to the 404 page.
From your code I'm assuming that you're using VueJs as an SPA and you're retrieving the data from your laravel backend API.
Based on that, your join function is supposed to return json data that you use in your frontend, but in case the ConceptPaper was not found, you return a view instead of json, which won't change much because you're just changing the data that your front-end receives, but the front-end component is not changed.
What I'd do is remove the try catch block, which will return a 404 response from the API, and handle the 404 case in vue, and create a NotFound view in vue.
Laravel
public function join($joincode)
{
$conceptPaper = ConceptPaper::where('join_code', $joincode)->firstOrFail();
return response()->json($conceptPaper);
}
Vue
router/index.js
const routes = [
// previous routes
{
path: '/not-found',
name: 'NotFound',
component: () => import('../views/NotFound.vue')
}
]
NotFound.vue
<template>
// page here
</template>
export {
name: 'NotFound'
}
And finally handle the not found API call, if you are using axios
axios.get('/conceptPaper/lobby/-1000')
.catch(function (error) {
if (error.response.status === 404) {
this.$router.push('NotFound');
}
});

Nuxt.js router.push doesn't fully redirect to another page while using asyncData query

I am using asyncData query in one of my pages:
async asyncData({$axios, query}) {
const id = query.id;
try {
const {data} = await $axios.$get(`http://localhost:8000/api/question/${id}`);
return {
question: data
}
} catch (e) {
console.log(e);
}
},
Whenever I try to access another route from this page, for example:
#click="$router.push('/solution'); addTodo(question.keywords); addTodo(option.keywords)">
It redirects me to this page /solution, but the request to access API still goes from previous page (question/id)
Accessing localhost:3000/solution page:
CORS works in every other page, so I think the issue is here with redirections.
What would be possible solutions to fix this?
Also, this is what I see in Network tab:
I think referer should be: localhost:3000/solution
Adding 'paths' => ['api/*'] to Laravel back-end CORS config helped.

Express.js res.render not redirecting, just displayed in console

This time I want to use res.render to display html as success of DB update. I did it several times, but this time it doesn't work. It's not render html file, just displayed on chrome's console.
I think it caused because of async problem or duplicated response. I tried to many ways but I couldn't solve it, so pointers appreciated.
The code is related when the user paid service, increase user's level.
Get Access Token => Validate => res.render
app.post('/payment/validate', function(req, res, next){
// Get access token
request.post({
url : 'https://payment-company/get/token'
}, function(err, response, body) {
if(!err & response.statusCode == 200) {
var result = JSON.parse(body);
var accessToken = result.response.access_token;
// Validate payment (compare paid and would be paid)
request.get({
headers : { 'Authorization' : accessToken }
url : 'https://payment-company/find/paymentid'
}, function (err, response, body) {
if (!err && response.statusCode == 200){
var result = JSON.parse(body);
if (result.response.amount == req.body.price){
Members.findOne({id : req.user.id}, function(err, member){
// If no problem, update user level
member.level = 2;
member.save(function(err, result){
if (err) return next();
res.render('payment.view.result.ejs',
{
title : 'Success !',
description : 'level up.'
});
});
});
}
} else {
...
}
});
}
})
});
sorry to verbose code I tried to shorten code, No problem until res.render, res.render will work but it's not display page instead it just send html code to chrome's console.
Looks like there's a bit of a misunderstanding of how these requests work. What I think you intend:
Browser makes a GET request, server responds with an HTML document, the browser renders it
User takes an action
Browser makes a POST request, server responds with an HTML document, the browser renders it
What you've started coded on the frontend is an alternate method:
You make a POST request via AJAX, server responds with some JSON, you modify the current document with JavaScript to let the user know

Resources