Is it possible to have children routes and route-views in vuepress? - nested

I'm trying to have a children route-view inside my main page, and can't find a way to accomplish this in vuepress.
This is how I would normally accomplish this in Vue, in router.js
routes: [
{
path: '/',
name: 'home',
component: Home,
children: [
{
path: '/work/:worktitle',
name: 'workpage',
// component: () => import(/* webpackChunkName: "about" */ './views/WorkView.vue'),
component: WorkView,
props: true
}
]
}
]
But I don't know where can I put such code in vuepress. (no router.js)
I am trying to accomplish this because I'm trying to have a collection of links in my homepage, and when clicked, I'd like to have the pages of those links rendered as a modal without going to a new page. But I'd like to retain the ability to link directly to these modals.

use .vuepress/enhanceApp.js with router.addRoutes
// async function is also supported, too
export default ({
Vue, // the version of Vue being used in the VuePress app
options, // the options for the root Vue instance
router, // the router instance for the app
siteData, // site metadata
isServer // is this enhancement applied in server-rendering or client
}) => {
// ...apply enhancements to the app
router.addRoutes([
// ...
])
}

Related

Why does my Next.js SSR api call Error: The default export is not a React Component in page:"/api/twilio" at Object.renderToHTML & how do I make work?

I have a Next.js application that has React components in the pages directory that render as expected. The application was built for a rails backend api and is using that backend every day properly. I am trying to add a twilio video chat to the app. I created an /api directory as instructed in all documentations. When I attempt to make a call to this api for literally a mock example to test the api I get the error in the terminal Error: The default export is not a React Component in page: "/api/twilio" at Object.renderToHTML (/home/application_in_question/node_modules/next-server/dist/server/render.js:117:19)
and I also get Failed to load resource: the server responded with a status of 500 (Internal Server Error) in the browser. I was not part of the team that built this application so I am unsure of why I cannot add this Next.js api. The api is the selling point of Next and it is supposedly built into the framework.
I get this error is I just put the route in the address bar of the browser but I also get it from a file api call.
pages/twilio/index.js
const handleFetchPosts = async () => {
debugger
const tokenResponse = await fetch("/api/twilio");
debugger
const tokenData = await tokenResponse.json();
debugger
setToken(tokenData);
};
section of package.json
"next": "^8.1.0",
"next-auth": "^1.8.5",
"next-compose-plugins": "^2.2.0",
"next-redux-wrapper": "^2.0.0",
"next-routes": "^1.4.2",
"next-seo": "^1.11.2",
"node-sass": "^4.12.0",
pages/api/twilio/index.js
console.log("running api")
const handler = (req, res) => {
return res.json({ hello: 'world!' });
};
export default handler;
next.config.js
const { withPlugins, optional } = require('next-compose-plugins')
// eslint-disable-next-line import/no-extraneous-dependencies
const { PHASE_PRODUCTION_BUILD } = require('next-server/constants')
const sass = require('#zeit/next-sass')
const { requireEnvVar } = require('./lib/utils')
Custom Next.js Configuration
#see https://nextjs.org/docs#custom-configuration
const nextConfig = {
Runtime configuration
#see https://nextjs.org/docs#exposing-configuration-to-the-server--client-side
publicRuntimeConfig: {
// Will be available on both server and client
apiUrl: requireEnvVar('API_SERVER'),
googleApiKey: requireEnvVar('GOOGLE_API_KEY'),
stripeApiKey: requireEnvVar('STRIPE_PUBLISHABLE_KEY'),
instantPayFee: requireEnvVar('INSTANT_PAY_FEE'),
},
Disable file-system routing
#see https://nextjs.org/docs#disabling-file-system-routing
**useFileSystemPublicRoutes: true,**
Custom webpack config
#see https://nextjs.org/docs#customizing-webpack-config
webpack(config, { webpack }) {
Only load specific locales for moment.js
#see https://stackoverflow.com/a/25426019/956688
config.plugins.push(
new webpack.ContextReplacementPlugin(/moment[/\\]locale$/, /en/)
)
return config
},
}
Load multiple plugins with next-compose-plugins
#see https://github.com/cyrilwanner/next-compose-plugins
module.exports = withPlugins(
[
[sass],
Analyzing the webpack bundle
#see https://github.com/zeit/next-plugins/tree/master/packages/next-bundle-analyzer
Load #zeit/next-bundle-analyzer as an optional plugin only during production build
#see https://github.com/cyrilwanner/next-compose-plugins#optional-plugins
#see https://github.com/cyrilwanner/next-compose-plugins#phases-array
[
// eslint-disable-next-line global-require,import/no-extraneous-dependencies
optional(() => require('#zeit/next-bundle-analyzer')),
{
analyzeServer: ['server', 'both'].includes(process.env.BUNDLE_ANALYZE),
analyzeBrowser: ['browser', 'both'].includes(
process.env.BUNDLE_ANALYZE
),
**bundleAnalyzerConfig: {
server: {
analyzerMode: 'static',
reportFilename: '../../bundles/server.html',
},
browser: {
analyzerMode: 'static',
reportFilename: '../bundles/client.html',
},
}**,
},
[PHASE_PRODUCTION_BUILD],
],
],
nextConfig
)`
As you can see above the team before me had useFileSystemPublicRoutes set to false. I have made this true.
When I attempt to fetch the api in the react page or use a get request in the browser for the api/index.js file I created with the code
`
console.log("running api")
const handler = (req, res) => {
return res.json({ hello: 'world!' });
};
export default handler;`
This gives the error above. This is a very simple example that I have seen work in numerous resources online so I do not understand why this is happening.
How can I get this api to work???
** I added the ** in an attempt to highlight the parts I think could help. I already set useFileSystemPublicRoutes to true.
You can read in the comment thread Next#8 was before API routes were added to the framework. I ended up using a workaround where I used the rails backend server. Next version 9+ has api routes where any file in a pages/api directory is treated as a server backend api file. Next 8 was treating pages/api/file as a front-end webpage file looking for react.

How can I get parameter from server when start vue page?

Hello I need to know how can I solve this issue.
What I want to know is how can I open a page with parameters from data.
Here is flow What I want to make.
several person receives email. there is a button to link to a page with their id.
When they push the button, server identifies them and send their name from database.
redirect them to main page. with their name data.
main page(vue) shows their name like “welcome home. Mr Smith”
I’m stuck between step 3 and 4. I’m sending their name data as query.
But don’t know how to receive them.
I thought it can be used as props. but it only shows ‘undefined’
here is my node js code.
res.redirect(url.format({
pathname:"/",
query: {
"name": rows[0].name,
"familyname": rows[0].familyname,
"gender":rows[0].gender
}
}));
and this is vue router part. (router.js)
routes: [
{
path: '',
props: true,
component: () => import('./layouts/main/Main.vue'),
children: [ ... ]
}]
and I’m making my main.vue code like this.
export default {
props: ['name','familyname','gender'],
methods: {
showprops() {
alert(this.$props.name);
}
},
created() {
this.showprops();
}
Current result is undefined when alert(this.$props.name) is called.
How can I solve this issue?
Thank you in advance.
$route.query
Looks like you are including your parameters as query parameter, e.g. /?name=xxx&familyname=xxx&gender=xxx . To get queryparameters from vue route you have to use this.$route.query .
$route.props
To have props like this.$route.props , this would require a url like /user/12345/bob and a vue router setup like
routes: [
{ path: '/user/:id/:name', component: User, props: true }
]
Converting query parameters to vue router props
In the official vue router docs you'll find a very nice example on how to use Function Mode to convert query parameters to props ( https://router.vuejs.org/guide/essentials/passing-props.html#function-mode ) .
const router = new VueRouter({
routes: [
{ path: '/search',
component: SearchUser,
props: (route) => ({ query: route.query.q })
}
]
})
From the example above the URL /search?q=vue would pass {query: 'vue'} as props to the SearchUser component.

How to implement clean Next.js URL in graphql-yoga

I am creating a GraphQL app using Next.js for server side rendering. As you might know, there is a recommended way to implement clean URL using Express. I am trying to achieve the same using graphql-yoga but it's not working.
I have tried server.express.get('/route', ...) and server.get('/route', ...) but nothing is working. In the documentation they have given server.express.get(server.options.endpoint, handler()) but it's not working for me.
Has anyone ever implemented clean Next.js URL in a GraphQL Yoga server, and how did you achieve it? Below is how I am creating the server.
function createServer() {
return new GraphQLServer({
typeDefs: "src/schema.graphql",
resolvers: {
Mutation,
Query
},
context: req => ({ ...req, db })
});
}
const server = createServer();
server.express.post('/product/name', (req,res,next) => {
//this is where i want to implement next clean url
//but it's not working
console.log('Am never reached..');
next();
})
With the new versions of Next.js, creating clean URL is straightforward.
Create a parameterised page (e.g. pages/post/[pid].js):
import { useRouter } from 'next/router'
const Post = () => {
const router = useRouter()
const { pid } = router.query
return <p>Post: {pid}</p>
}
export default Post
More info in the Next.js documentation regarding dynamic routes.
You can then link to it and show the desired URL:
<Link href="/post/[pid]" as="/post/abc">
<a>First Post</a>
</Link>

Angular routing acting strange when url is manually typed

I'm building a web app using Angular 7 for the frontend and NodeJS, MongoDB and ExpressJS for the backend. The application runs as intended as long as I interact with the application to navigate, but when I manually type the path, it seems like it doesn't hit the component for the route. It works all good locally, but not on Heroku.
Here's is my app-routing.module.ts:
const routes: Routes = [{
path: "login",
component : LoginComponent
},
{
path: "registration",
component : SignupComponent
},
{
path: "votes",
component : VotesComponent
},
{
path: "votes/:website",
component : VoteComponent
},
{
path: "**",
redirectTo: "votes"
}
];
#NgModule({
imports: [CommonModule, RouterModule.forRoot(routes, { enableTracing: false})],
exports: [RouterModule]
})
export class AppRoutingModule { }
All my routes in Express is prefixed with /api/, such as:
app.get('/api/votes', (req, res, next) => {
const limit = parseInt(req.query.limit)
db.getVotes(limit).then((votes) => {
res.json(votes);
});
});
I check the jwt like this:
app.use(
checkJwt({ secret: process.env.JWT_SECRET }).unless({ path: [
{ url: "/api/authenticate", methods: ['POST'] },
{ url: "/api/votes", methods: ["GET"]}]})
);
app.use((err, req, res, next) => {
if (err.name === 'UnauthorizedError') {
res.status(401).send({ error: 'Not authorized.' });
};
});
My call to votes is performed like this:
private baseUrl = environment.apiUrl;
this.http.get<any[]>(`${this.baseUrl}/votes`, this.httpOptions))).subscribe(data => {
this.data = data;
});
The baseUrl is defined as follows in the evironment.prod.ts:
export const environment = {
production: true,
apiUrl: '/api'
};
Here comes the problem. If I go to my deployment on Heroku and access https://myurl.com I'm redirected to https://myurl.com/votes and I can see the requested url is https://myurl.com/api/votes, so thats all fine and I get my angular application with all the data. But if I manually type in https://myurl.com/votes I get JSON back in the browser with error "Not authorized", and I can see that the requested URL is https://myurl.com/votes, instead of https://myurl.com/api/votes. Any ideas whats causing this? It seems like Angular is not routing it properly. When it's typed manually it doesn't hit any of my components.
For non-match route path, the router configuration should include below one.
{
path: "",
component: "404NotFoundComponent"
}

How to force Angular to send request to server on HTML5 mode?

I m tring to build and web using angular and nodejs. I'm loading Angular on /home path where / contains login and registration form. Here is my angular configuration:
window.app.config(['$routeProvider', '$locationProvider',
function($routeProvider,$locationProvider) {
$locationProvider.html5Mode(true);
$locationProvider.hashPrefix('!');
$routeProvider.
when('/profile', {
templateUrl: '/views/account.html',
}).
when('/edit', {
templateUrl: '/views/edit.html',
}).
when('/home', {
templateUrl: 'views/index.html'
}).
when('/signout', {
templateUrl: 'views/signout.html'
//on this view i load a controller which submits a form to /signout
}).
otherwise({
redirectTo: '/home'
});
}
]);
on server side routing:
app.get('/',function(){
res.render('index',{
user: req.user? req.user:'guest'
});
});
app.post('/login',function(){
//if success redirect to /home
//if fails redirect to /
});
app.get('/auth/facebook', passport.authenticate('facebook', { scope: [ 'email', 'user_about_me', 'read_stream', 'publish_actions'], failureRedirect: '/' }));
app.get('/auth/facebook/callback', passport.authenticate('facebook', { failureRedirect: '/' }), users.authCallback);
app.get('/signout',function(){
//signing out the user here...and redirects to /
});
app.get('/home',function(req,res){
res.render('users/home',{
user: req.user? req.user:'guest',
message: req.flash('error')
})
});
app.get('/profile',function(req,res){
res.render('users/home',{
user: req.user? req.user: 'guest',
message: req.flash('error')
})
});
app.get('/edit',function(req,res){
res.render('users/home',{
user: req.user? req.user:'guest',
message: req.flash('error')
})
});
How can I send request by clicking on a link on url /home to go /auth/facebook due to Angular routing if I click on facebook auth it sends me to /home. Angular preventing from sending request to server, it's just go to url /home, I tried removing otherwise /home by replacing /. The result is same just no view is loaded there.
From the Docs:
In cases like the following, links are not rewritten; instead, the
browser will perform a full page reload to the original link.
Links that contain target element. Example: <a href="/ext/link?a=b"
target="_self">link</a>
Absolute links that go to a different domain. Example: link
Links starting with '/' that lead to a different base path when base is defined. Example: link
So, as a simplest solution, just add target="_self" to your link.
If you'd rather change the route configuration in one place instead of changing all link elements, you can do this:
$routeProvider.when('/externalpath', { resolve: {
redirect: ['$location', function($location) {
window.location.replace($location.absUrl());
}]
}});
This basically invokes the inlined function whenever a link to that route is hit, and the function just redirects the browser to the target location (outside of angular). The 'resolve' configuration is processed regardless of whether a template or controller is configured for the route, and the 'redirect' name is basically just a dummy name - the important thing is that the function gets executed to get its value (which is unused in this case).
This is also useful when e.g. you have a /signout url that needs to reach the server. You can also use an otherwise() configuration instead of when() if you want all non-configured paths to be handled by the server.

Resources