angular 2 lazy loading - routes from server - ajax

I have been working on an Angular 2 project using lazy loading. It's working well, but what I need is to get the module name from the server and then create a route, but it's not working.
Here is what I have:
import { Routes, RouterModule } from '#angular/router';
function getRoutes(): Routes{
let x: any = [
{path: '', redirectTo: 'welcome', pathMatch: 'full'},
{path: 'backend', loadChildren: 'app/backend/backend.module'}
]
return x;
}
export const routes: Routes = routess();
export const routing = RouterModule.forRoot(routes);
And here is, what do i need:
import { Routes, RouterModule } from '#angular/router';
function getRoutes(): Routes{
let x: any;
$.get( "api/getRoutes", function( data ) {
x = data; //object array from server
});
return x;
}
export const routes: Routes = routess();
export const routing = RouterModule.forRoot(routes);
The problem is, that the function getRoutes is not waiting for the server result and returns empty data.
Is there any way to wait for the server data and then add data to the routes?

Use NgModule just for basic routing setup (/welcome, etc.), then somewhere else in your app load routes and update router configuration. You can then use resetConfig():
this.http.get('/api/getRoutes')
.subscribe(config => this.router.resetConfig(config))

Related

Making multiple socket instances in React with socket.io, each in a namespace

I have a nestjs application which has Websockets integrated with socket.io. Some of the gateways need authentication. So connecting to them without authenticating logs you out. The problem is, I need some of them without authentication, so I managed to figure out that I could use "namespaces" to connect only to specific Gateways.
I specified in the gateways the namespaces like this:
#WebSocketGateway({
namespace: 'tourneys',
...ConfigConstants.WsConfig,
})
export class AuxiliaryGateway
and in gateways that need authentication, I made it like this:
#UseGuards(SocketSessionGuard)
#WebSocketGateway({
namespace: 'matches',
...ConfigConstants.WsConfig,
})
The problem doesn't seem to be on the back-end however. In the front-end, I tried connecting the websockets like this:
import React, { useEffect, useMemo } from "react";
import { io, ManagerOptions, Socket, SocketOptions } from "socket.io-client";
import { SocketContext } from "#lib/context/SocketContext";
import {
ServerToClientEvents,
ClientToServerEvents,
} from "#lib/types/socket/instance";
import { getAuthToken } from "#lib/services/storage/authToken";
export const SocketProvider: React.FC = ({ children }) => {
const options = {
auth: {
token: getAuthToken(),
},
transports: ["websocket"],
timeout: 20000,
reconnectionAttempts: 10,
reconnectionDelay: 1500,
reconnectionDelayMax: 5000,
} as Partial<ManagerOptions & SocketOptions>;
const tourneysSocket: Socket<ServerToClientEvents, ClientToServerEvents> = io(
`${process.env.NEXT_PUBLIC_WSS_HOST}/tourneys `,
options
);
const matchesSocket: Socket<ServerToClientEvents, ClientToServerEvents> = io(
`${process.env.NEXT_PUBLIC_WSS_HOST}/matches `,
options
);
useEffect(() => {
tourneysSocket.on("connect", () => {
console.log("conectado");
});
tourneysSocket.on("disconnect", e => {
console.warn(`- desconectado "disconnect", ${e}`);
});
tourneysSocket.on("exception", e => {
console.error(e);
});
matchesSocket.on("connect", () => {
console.log("conectado");
});
matchesSocket.on("disconnect", e => {
console.warn(`- desconectado "disconnect", ${e}`);
});
matchesSocket.on("exception", e => {
console.error(e);
});
}, [tourneysSocket, matchesSocket]);
const value = useMemo(
() => ({
tourneysSocket,
matchesSocket,
}),
[tourneysSocket, matchesSocket]
);
return (
<SocketContext.Provider value={value}>{children}</SocketContext.Provider>
);
};
I make two instances, one for each namespace. However, these instances they stop emitting to the correct subscribes after some testing. What might be causing this issue? I can't figure out and I believe it's happening in the front-end. React somehow seems to not use the sockets I'm instatiating after some emits.

Vue.component vs import to load a component

Why when I use Vue.component to load the two commented components below, I get the following error in the javascript console while it works with import ?
Uncaught ReferenceError: dashboard is not defined
app.js:
Vue.component('left-menu', require('./components/LeftMenu.vue').default);
// Vue.component('dashboard', require('./components/foo/dashboard.vue').default);
// Vue.component('members', require('./components/foo/members.vue').default);
import dashboard from './components/foo/dashboard.vue';
import members from './components/foo/members.vue';
const routes = [
{
path: '/dashboard',
component: dashboard
},
// {
// path: '/members',
// component: members
// }
];
Because you use dashboard variable in your routes, this variable exists in "import way" but not in "Vue component way"
In the example that generates errors the components are not recognized as variables, so you should do something like :
const dashboard = {
template: `<div>Dashboard</div>` ,
}
const routes = [
{
path: '/dashboard',
component: dashboard
},
// {
// path: '/members',
// component: members
// }
];

Vue.js router view no components?

I am trying to make a vue SPA using vuex, vue-router & laravel for backend. I was separating our data on our app.js to try to reduce clutter and keep our code neat. When everything on one page it works as intended, loading the routes in the router. But when we separate the code to make it more modular into: app.js, boostrap.js, routes.js, and store.js
The components aren't loading in our router-view and we are able to see our RouterLink
app.js
// Require the bootstrapper
require('./bootstrap');
// Grab imports
import Store from './store';
import Router from './routes';
// Views
import App from './views/App';
// Create the application
const app = new Vue({
el: '#heroic',
components: { App },
store: Store,
router: Router
});
boostrap.js
// Imports
import Vue from 'vue';
import Axios from 'axios';
import Swal from 'sweetalert2';
// Add to window
window.Vue = Vue;
window.Axios = Axios;
// Add Axios headers
window.Axios.defaults.headers.common['X-Requested-With'] = 'XMLHttpRequest';
window.Axios.defaults.headers.common['Authorization'] = 'Bearer ' + 'token';
window.Axios.defaults.headers.common['X-CSRF-TOKEN'] = document.querySelector('meta[name="csrf-token"]').getAttribute('content');
routes.js
// Imports
import Vue from 'vue';
import VueRouter from 'vue-router';
import Store from './store';
// Set to use
Vue.use(VueRouter);
// Views
import Hello from './views/Hello';
import Home from './views/Home/';
import UserIndex from './views/UserIndex';
// Create our routes
const routes = [
{
path: '/',
name: 'home',
component: Home,
},
{
path: '/hello',
name: 'hello',
component: Hello,
},
{
path: '/users',
name: 'users.index',
component: UserIndex,
}
];
// Create the router
const router = new VueRouter({
mode: 'history',
routes: routes,
scrollBehavior (to, from, saved) {
if (saved) {
return saved;
}
return { x: 0, y: 0};
}
});
// Before every request
router.beforeEach((to, from, next) => {
});
// After every request
router.afterEach((to, from, next) => {
});
// Export
export default router;
hello.vue
<template>
<div class="row row-cards row-deck">
<div class="col-lg-4 col-md-6">
<p>Hello World!</p>
</div>
</div>
</template>
store.js
// Imports
import Vue from 'vue';
import Vuex from 'vuex';
import PersistedState from 'vuex-persistedstate';
import Cookie from 'js-cookie';
// Set use
Vue.use(Vuex);
// Create our store
const store = new Vuex.Store({
state: {
auth: [{
id: 1,
username: '',
motto: '',
rank: 1,
permissions: [],
token: ''
}],
users: [],
},
mutations:{
},
actions: {
},
getters: {
}
});
// Export
export default store;
The expected result is that when I visit the "/hello" route it would show the information that says "Hello world!" that is within the Vue file specified as the component in the routes section of the router. Instead using my Vue DevTools I get the following with no Hello world on the page.
https://i.pathetic.site/chrome_99Mbxf7f0c.png
My guess is the router is stuck waiting for the beforeEach (and also possibly afterEach) hook to be resolved. You need to call next().
Also unrelated, but if you’re using modules then you shouldn’t need to assign stuff on window.

laravel + vue router cannot get parameters from url

I try to get parameters from url
let's say url contains:
localhost:8000/blog?q=hello
I want to grab hello to trigger function call
What I had declare in app.js in laravel webpack:
import VueRouter from 'vue-router';
Vue.use(VueRouter);
const router = new VueRouter({
mode: 'history',
routes: []
})
const app = new Vue({
router
});
export default app;
In blog page, I try to extract the parameter from url
new Vue ({
el: "#blog-content",
},
mounted: function() {
q = this.$route.query.q
console.log(q)
}
)
I npm run dev to compile and run the blog page it show error:
TypeError: Cannot read property 'query' of undefined
what is wrong? I am sure that Vue Router is properly installed in the application.
I think that the blog page that you use is not correct.
You recreate another Vue instance and in that case that new instance doesn't have a router passed to it. So I think that's why this.$router is undefined.
Also you don't pass the view Component to your router so it doesn't know what to look for with the specific url.
Here's your app.js file corrected
import VueRouter from 'vue-router';
Vue.use(VueRouter);
import Blog from './views/Blog';
const router = new VueRouter({
mode: 'history',
routes: [
{
path: '/blog',
name: 'blog',
component: Blog
},
]
});
The blog view page template : views/Blog.vue
<template>
<div class="wrapper">
My blog page
</div>
</template>
<script>
export default {
data() {
return {
myvariable : ''
}
},
mounted() {
let q = this.$route.query.q;
console.log(q);
},
};
</script>
Now it should works correctly :)
Edit : Also you don't need to export the app variable in your app.js
Remove the following line export default app; at the end of the file

How do I use HTML5 URLS with SpringBoot and VueJS

I have the following setup to my Vue project...
import UploadComponent from './Upload.vue'
import MainPageComponent from './MainPage.vue'
...
const router = new VueRouter({
routes: [
{ path: '/', component: MainPageComponent },
{ path: '/upload', component: UploadComponent }
]
});
...
let App = { router };
new Vue(App).$mount('#km-viewport');
Then in my html I have...
<div id="km-viewport">
<jg-app> </jg-app>
</div>
and inside the jg-app I have the following template...
<md-app-content>
<router-view></router-view>
</md-app-content>
Then in order to make this work with Spring Boot I add the following...
#Controller
public class MainEndpoint {
#GetMapping("")
public String rootRedirect(){return "redirect:/ui";}
#RequestMapping("/ui")
public String root(){
return "splash";
}
#RequestMapping("/ui/upload")
public String upload() { return "forward:/ui"; }
}
The problem is whether I got to <address>/ui or <address>/ui/upload they both show the same MainPageComponent. I can't figure out how to get the upload to show the upload component.
How do I use HTML5 urls with VueJS and Spring Boot?
It is possibly a difference in how Vue is handlings the URLs.
Try activating the history mode for vue-router:
const router = new VueRouter({
mode: 'history', // <=================== added this line
routes: [
{ path: '/', component: MainPageComponent },
{ path: '/upload', component: UploadComponent }
]
});

Resources