How to redirect to router.base URL in NuxtJS - vue.js

Let's say my nuxt app is running in a subfolder 'test'.
nuxt.config.js:
router: {
base: '/test/'
}
That means my application runs on localhost:3000/test
Now, when I go to localhost:3000/tes, all i get is a 404 Error with the contents Cannot GET /tes
However, I want to redirect to /test, or show my own 404 page. But I couldn't figure out a way to handle that case.
I tried using a middleware, but that only worked for links within the subfolder.
Thanks for your help!

I found what I needed in the nuxt documentation:
Using a Hook to router.base when not on root:
https://nuxtjs.org/docs/configuration-glossary/configuration-hooks#redirect-to-routerbase-when-not-on-root

You can create an error layout for the 404 page
Error page
Or you can use middle to check the incoming URL and redirect them somewhere.
Middleware
You can create your error layout (error.vue in layout folder) and when error it will show that page.
<template>
<div>
<h1 v-if="error.statusCode === 404">Page not found</h1>
<h1 v-else>An error occurred</h1>
<NuxtLink to="/">Home page</NuxtLink>
</div>
</template>
<script>
export default {
props: ['error'],
layout: 'error' // you can set a custom layout for the error page
}
</script>
Link showing practically how to do that: medium

Related

Nuxt3 useFetch only retrieving data occasionally

I'm a little bit confused with Nuxt 3 and the lifecycle of when it gets data. I understand that it's a universal rendering process, but I'm using Strapi 4 to manage content in my Nuxt 3 project and only occasionally do I retrieve the data via useFetch. The API route from Strapi never goes down so I'm probably just doing something wrong.
Here is my Vue file in Nuxt:
<script setup lang="ts">
const {data: works, pending, error} = await useFetch("http://localhost:1337/api/works", {
params: {
populate: "*"
}
});
</script>
<template>
<div>
<div v-for="work in works">
... do something
</div>
</div>
</template>
I'm not sure how to get the content when the page loads. When I log the error returned, it's just true. But it's only sometimes. The content will load once, and then as soon as I refresh the page, it goes back to having an error. So I'm thinking something is getting cached maybe client-side? I'm really not sure what to do next.
Try passing this option to useFetch: initialCache: false. See more

Vue.js - Embed Swagger UI inside a Vue component?

I have a form in my Vue component which uploads the api file. Now I want to render the contents of the file like this:
I have imported swagger client library: https://github.com/swagger-api/swagger-ui.
Now, here
is an example of how you do it in a static page. But I need to do it inside a Vue component (or Quasar, specifically), so I do it like that:
Register swagger-ui inside my register components file:
<link rel="stylesheet" type="text/css" href="swagger-ui.css">
Now it is available as:
this.swaggerUI({})
anywhere in my components. Inside my component I have a div in a template to render the api file:
<template>
<q-form>here lies q-file element, submit button and other stuff</q-form>
<div id="swagger-ui"></div>
</template>
In the mentioned question he had something like:
<script>
window.onload = function() {
const ui = SwaggerUIBundle({
url: "https://yourserver.com/path/to/swagger.json",
dom_id: '#swagger-ui',
presets: [
SwaggerUIBundle.presets.apis,
SwaggerUIStandalonePreset
]
})
window.ui = ui
}
</script>
Here's the difference: first of all, no window.onload, I must render it on submit button. Then, I deal with an uploaded file stored in my model, so no URL here. Now, I don't get how to make it work with locally stored file, when I try with the remote url, it gives me:
vue.esm.js?a026:628 [Vue warn]: Error in v-on handler: "Invariant Violation: _registerComponent(...): Target container is not a DOM element."
I was getting a similar error (Target container is not a DOM element) trying to use a static swagger spec. Instead of using window.onload, I found that Vue has the mounted() function, so this Vue 3 file worked for me:
<template>
<div class="swagger" id="swagger"></div>
</template>
<script>
import SwaggerUI from 'swagger-ui';
import 'swagger-ui/dist/swagger-ui.css';
export default {
name: "Swagger",
mounted() {
const spec = require('../path/to/my/spec.json');
SwaggerUI({
spec: spec,
dom_id: '#swagger'
})
}
}
</script>
This one appeared to be a simple yet very unobvious typo: in windows.onload function:
dom_id: '#swagger-ui',
must instead be
dom_id: 'swagger-ui',
without hash sign, that's it!

Change URI directly for a Vue app and caused error

In my Vue app, I can click a link generated by <router-link>...</router-link> and visit a page like: /site/books/00666.html.
The routing config for this is:
{
path: '/books/:id.html',
name: 'BookDetail',
component: BookDetail,
props: true,
}
So I changed the URI in the browser (Fx57) to: /site/books/00777.html to try to display the detail information of another book. It failed with this:
Cannot get /books/00777.html
and the debugger told me something like:
Content security policy is preventing from accessing a resource from 'self'`.
I searched on CSP but can't figure out how to make this working.
Update: To reproduce the issue, I use vue init webpack test and scafolded a blank Vue app with router support.
One new router is added:
{
path: '/book/:id.html',
name: 'BookDetail',
component: BookDetail,
props: true,
}
In the default HelloWorld.vue, just add a few lines with <router-link>:
<ul>
<li><router-link :to="{name: 'BookDetail', params: {id: 12345} }">Book 1</router-link></li>
<li><router-link :to="{name: 'BookDetail', params: {id: 23456} }">Book 2</router-link></li>
</ul>
In the HelloWorld page, clicking the link above will take you to "localhost:8080/book/12345.html". Good.
Change the URI to "localhost:8080/book/23456.html". The browser prompts the same error as before.
Update 2: per hint below, I modified the URI pattern to '/books/:id' and it is working.
Further question: What shall I do if I want to add the .html suffix?

anchor is not redirecting to display inside ng-view, rather reloading with new page

I wrote a simple angular application in a learning purpose. However the controllers are working in my system but not in plunker. But, that is not my concern. My concern is I am unable to see the linked pages inside ng-view. They are rather opening as a new page replacing the home page. Secondly, the expressions are not reflecting their values. Kindly help me out. I have uploaded the codes in plunker.
Link to Plunker
<div ng-controller="RamFirstCtrl">{{name}}</div>
<div ng-include="'navbar-top.html'"></div>
<div style="border:1px solid green; position:relative;" ng-view></div>
Noticed couple thing:
http to https, there is error in console, it might be the reason it doesn't work in plunker
<script src = "https://ajax.googleapis.com/ajax/libs/angularjs/1.6.4/angular.js"></script>
you have to use the url define in your router:
ng-href="aboutUS.html" to ng-href="#!/aboutUS"
.when("/aboutUS", {
templateUrl : "aboutUS.html"
})
<div>
<a ng-href="#!/aboutUS">
AboutUs
</a>
</div>
Note:#! will be added to url by angular router by default

DRY for displaying meteor templates for different urls

I am having trouble setting up a simple website with different webpages and staying DRY.
I have everything set up so I the last fragment of the url is the name of the template that needs to be loaded in the content part of the webpage. All I want to do now is load that template in a specific location based on the url.
In any examples, they do this:
{{#if showCreateDialog}}
{{> createDialog}}
{{/if}}
{{#if showInviteDialog}}
{{> inviteDialog}}
{{/if}}
I'd like to do something along the lines of
{{> {{template_name}} }}
Sadly, that doesnt work. I tried this as well:
{{{content}}}
Template.content.content = function () {
var url_frag = Session.get("url_frag");
return Template[url_frag]();
}
This didnt work either. Please help!
Edit:
hmm. perhaps, my error is not in loading the template but in capturing the url:
var TodosRouter = Backbone.Router.extend({
routes: {
"*url": "main"
},
main: function (url) {
Session.set("url", url.split('/'))
}
});
The error I am getting arises when url_frag is undefined...
var url_frag = Session.get("url_frag");
initially, this works, but upon changing webpages, it fails...
Solved. I just left backbone out of it
Template.content.content = function () {
var url = window.location.pathname.split('/');
var url_frag = url.pop()
return Template[url_frag]();
Then in the html:
<template name="content">
{{{content}}}
</template>
You could also try the router smart package at atmosphere, which also supports complex routes and filters.
https://atmosphere.meteor.com/package/router
Install meteorite using npm install -g meteorite
Install router using mrt add router
Add {{renderPage}} to body
Tada! /login now renders {{> login}}
Read the document here: https://github.com/tmeasday/meteor-router