Angular SSR, Dynamic Page Won't Load - Status 504 - javascript

Code: http://github.com/dbots-co/website
Directly connecting to a dynamic route (dashboard, bot page), seems to not work. However, directly connecting to docs does work.
This only happens when using Angular 10 Universal SSR.
Not Working: https://dbots.co/bots/774811448576573480
Working: https://dbots.co/docs/get-started
bot-page.component.ts:
async ngOnInit() {
await this.service.init();
this.user = this.service.getBot(this.id);
this.bot = this.service.getSavedBot(this.id);
if (!this.user || !this.bot)
return this.router.navigate(['']);
this.seo.setTags({
description: this.bot.listing.overview,
titlePrefix: this.user.username,
titleSuffix: 'DBots',
url: `bots/${this.id}`
});
this.analytics.botPageView({ botId: this.user.id });
this.themeService.setNavbarBackground('var(--background-secondary)');
document
.querySelector('.navbar')
.setAttribute('style', `margin-bottom: -5px;`);
}
app-routing.module.ts:
const routes: Routes = [
...
{ path: 'bots/:id', component: BotPageComponent },
...
];

Related

How to do routing with Electron and Vanilla Javascript

I have been looking for ways to find a way to make a single page application with vanilla javascript only but sadly I could not find one.
I found this code in a tutorial on how to make a SPAs, however the issue is location.pathname returns not the URL path but the file path instead with Electron. This bit of code is integral to make the routing work. And I don't wanna use any frameworks.
const router = async () => {
const routes = [
{ path: "/", view: console.log("Viewing /") },
{ path: "/login", view: console.log("Viewing login") },
{ path: "/dashboard", view: console.log("Viewing dashboard") },
];
const potentialMatches = routes.map((route) => {
return {
route: route,
isMatch: location.pathname === route.path,
};
});
};
window.addEventListener("load", () => {
router();
});
Is there a way I could retrieve the URL path and inject it to my index.js?

Ionic 4 Deeplink plugin return false route not matched

I am Implementing Deeplink in ionic 4 application. Application in getting launched but deeplink plugin always returns false;
app.routing.ts:
{
path: 'viewdiary/:id/public',
loadChildren: () => import('./pages/viewdiary/viewdiary.module').then( m => m.ViewdiaryPageModule)
},
app.compoent.ts:
setupDeepLink(){
this.deeplinks.route({
'/viewdiary/:id/public': 'viewdiary/:id/public'
}).subscribe((match)=>{
console.log('deeplink matched', match);
const internalPath = `${match.$route}/${match.$args['id']}/${match.$route}`;
console.log(internalPath);
this.zone.run(()=>{
this.general.goToPage(internalPath);
});
},
nomatch=>{
// nomatch.$link - the full link data
console.error("Got a deeplink that didn't match", nomatch);
})
};
My Public diary Page link is 'https://www.example.com/diary/12542/public';
it looks like a routing issue tried many thing changes names but nothing works. I am clueless what going wrong.
Figured out how to achieve it with the help of Another Answer on Stackoverflow
import { Platform, NavController } from '#ionic/angular';
constructor(public navCtrl: NavController){}
this.deeplinks.routeWithNavController(this.nav, {
'/viewdiary/:diary/:id/:public': 'viewdiary'
}).subscribe((match) => {
console.log('success' + JSON.stringify(match));
}, (noMatch) => {
console.log('error' + JSON.stringify(noMatch));
});
For me, this approach did not work either. So, in my application I handle deep links as follows:
const {App}: { App: AppPlugin } = Plugins;
...
export class AppComponent {
private setupDeepLinks(): void {
App.addListener('appUrlOpen', (data: any) => {
this.ngZone.run(() => {
// Example url: https://my-domain.com/tabs/tab2
// slug = /tabs/tab2
const slug = data.url.split('my-domain.com').pop();
if (slug) {
this.router.navigateByUrl(slug);
}
});
});
}
}
Or you can implement your own more complex logic inside the listener if needed

Next Js Custom Routes and SSR

I am using apollo with next and recently I noticed that custom routes breaks SSR. Usually if you navigate through pages apollo caches the query and when you are on the page the next time, it serves everything from cache. However with custom routes, the cache is never used.
I also noticed that when I click on these pages, an error flashes in the console. But it goes away very fast and I wasn't able to copy it here.
Server.js
//
server.get('/about-us', (req, res) => app.render(req, res, '/about'));
server.get('/about', (req, res) => res.redirect(301, '/about-us'));
Menu Click Handler
const navigate = link => () => {
Router.push(link);
};
Menu Items
export const menu = [
{
name: 'Home',
url: '/',
},
{
name: 'Catalogs',
url: '/catalogs',
},
{
name: 'Shop',
url: '/shop',
},
{
name: 'Wholesale',
url: '/wholesale',
},
{
name: 'About Us',
url: '/about-us',
prefetch: true,
},
{
name: 'Contact Us',
url: '/contact-us',
prefetch: true,
},
];
Based on a suggestion from nextjs spectrum I tried prefetching custom pages in the TopNav Component but it didn't work.
const prefetch = url => {
if (process.browser) {
console.log('prefetching these urls', url);
Router.prefetch(url);
}
};
useEffect(() => {
menu.forEach(menuItem => {
if (menuItem.prefetch) {
prefetch(menuItem.url);
}
});
}, []);
I was able to figure out the problem. This is not really well documented but you need to prefetch the component. So for my case instead of prefetching /about-us I should have prefetched /about.
That's why there is as prop in the link component. Nextjs 9 just got released which fixes this issue.
https://nextjs.org/blog/next-9#dynamic-route-segments
For nextjs 9 you can save your file as [pid].js and it will catch all paths in a specific route. i.e for /products/test-product you have to create folder products and inside that add [pid].js.
I needed to query for product based on slug so I added this and voila, I have access to the slug inside my component.
Product.getInitialProps = async ({ query }) => {
return { slug: query.pid };
};
These issues were pretty frustrating before next 9 but it's heavily simplified and it helped me fully remove server.js.

Axios returns undefined in nested Vue JS (Laravel API)

I'm having a lot of trouble with Axios when using nested routes in Vue JS.
I have found that if my component is at the root ("/"), as with the "Accounts" component below, then Axios loads the data correctly, no problems here.
But if I went to the "Campaigns" component, which is nested at "/accounts/:account_id" then Axios stops working. In fact, it doesn't return any data at all. However, the API is valid, as Postman correctly returns the data.
So whenever I move a component into a nested URL, Axios stops working. I have no idea why this is happening, and I cannot find any solutions online. I'm sure it must be simple, but I can't see it.
app.js (Includes routes)
const router = new VueRouter({
mode: 'history',
routes: [
{
path: '/',
name: 'accounts',
component: Accounts
},
{
path: '/accounts/:account_id',
name: 'campaigns',
component: Campaigns
},
],
});
Campaigns Component
<script>
import axios from 'axios'
export default {
data() {
return {
accountID: null,
campaigns: [],
campaignsMeta: {},
};
},
mounted() {
this.accountID = this.$route.params.account_id;
this.fetchCampaigns();
},
methods : {
fetchCampaigns(page = 1) {
const AuthStr = 'Bearer '. concat(this.apitoken);
axios.get("api/account/" + this.accountID + "?page=" + page)
.then(({data}) => {
this.campaigns = data.data;
this.campaignsMeta = data.meta;
});
}
},
}
</script>
For anyone who is experiencing a similar problem in the future, I made the error of using a relative URL and not an absolute URL for the Axios Get request.
Original Code
axios.get("api/account/" + this.accountID + "?page=" + page)
.then(({data}) => {
this.campaigns = data.data;
this.campaignsMeta = data.meta;
});
Correct Code
axios.get("/api/account/" + this.accountID + "?page=" + page)
.then(({data}) => {
this.campaigns = data.data;
this.campaignsMeta = data.meta;
});
Note the "/" at the start of "/api/account" indicating an absolute path, not relative.
The reason this is important is because:
For relative URLs, the API request would be appended to the end of the current page URL, so the API request on the Accounts component would have been: /accounts/:account_id/api/account (which is wrong!)
For absolute URLs, the API request is made from the domain name, so the API request on the Accounts component is: domain.com/api/account (correct!)
Thanks!

Vue-router 2 changes route but does not update the view?

I have a login issue with website that uses:
Vue.js v2.0.3
vue-router v2.0.1
vuex v0.8.2
In routes.js I have a simple interceptor setup
router.beforeEach((to, from, next) => {
if (to.matched.some(record => record.meta.requiresAuth)) {
// this route requires auth, check if logged in
// if not, redirect to login page.
if (!router.app.auth.isUserLoggedIn) {
next({
path: '/login',
query: { redirect: to.fullPath }
})
} else {
next()
}
} else {
next() // make sure to always call next()!
}
})
And in login.vue,which handles the login page logic after using Google API only for login succeeds I call this:
this.login(userData).then(
() => this.$router.push(this.redirectToAfterLogin), // Login success
() => {} // Login failed
)
mounted: function(){
if (this.auth.isUserLoggedIn){
// Let's just redirect to the main page
this.$router.push(this.redirectToAfterLogins)
}else{
Vue.nextTick(() => {
this.loadGooglePlatform()
})}}
computed: {
redirectToAfterLogin: function() {
if (this.$route.query.redirect){
return this.$route.query.redirect
}else{
return '/'
}
}
}
router.js
var VueRouter = require('vue-router')
// Router setup
export const router = new VueRouter({
linkActiveClass: "is-active",
mode: 'history',
saveScrollPosition: true,
routes: [
{ path: '', name: 'root', redirect: '/home' },
{ path: '/login', name: 'login', meta: { loadingNotRequired: true }, component: require('./pages/login.vue') },
{ path: '/logout', name: 'logout', meta: { loadingNotRequired: true }, component: require('./pages/logout.vue') },
{ path: '/home', name: 'home', title: 'Home', redirect: '/home/random', component: require('./pages/home.vue'),
children: [
{ path: 'random', name: 'random', meta: { requiresAuth: true }, title: 'Random', component: require('./pages/random.vue') }
]
}
]
})
// Redirect to login page if not logged In
router.beforeEach((to, from, next) => {
if (to.matched.some(record => record.meta.requiresAuth)) {
// this route requires auth, check if logged in
// if not, redirect to login page.
if (!router.app.auth.isUserLoggedIn) {
next({
path: '/login',
query: { redirect: to.fullPath }
})
} else {
next()
}
} else {
next() // make sure to always call next()!
}
})
Now here this.login is just the call to vuex, to update the logged in user.
What happens is that after login, URL changes to /home, but the DOM does not update!
Only way that successfully changed the DOM was forcing location.reload() and that is not what I want to do, as it loses my dynamically loaded G scripts in Head.
Any idea on what to do to force the view to update DOM?
NOTE: it happens only on the first login of user, if he logs out and back-in, the redirecting is fine
Not a perfect solution may be, as it is going to recreate the component but it will work for every case when having same route & needs to update the component.
Just update the <router-view/> or <router-view></router-view> with
<router-view :key="$route.fullPath"></router-view>
Vue re-uses components where possible. You should use beforeRouteUpdate to react to a route switch that uses the same component.
I have the same problem "URL changes to /home, but the DOM does not update".
In my project, the tag "transition" maked the problem.
Hope it is helpful!
Maybe you should set the redirectToAfterLogin function into methods, like this it will be recalculated each times. The computed will be modified only if used v-model changed. To stick to the meaning of the function name, I would set the router push inside.
login.vue :
mounted: function(){
if (this.auth.isUserLoggedIn){
// Let's just redirect to the main page
// this.$router.push(this.redirectToAfterLogins)
this.redirectToAfterLogins()
}else{
Vue.nextTick(() => {
this.loadGooglePlatform()
})
}
},
// computed: {
methods: {
this.login(userData).then(
// () => this.$router.push(this.redirectToAfterLogin), // Login success
() => this.redirectToAfterLogin(), // Login success
() => {} // Login failed
),
redirectToAfterLogin: function() {
if (this.$route.query.redirect){
// return this.$route.query.redirect
this.$router.push(this.$route.query.redirect)
}else{
// return '/'
this.$router.push('/')
}
}
}
https://v2.vuejs.org/v2/guide/computed.html#Computed-Properties
https://v2.vuejs.org/v2/guide/computed.html#Computed-Caching-vs-Methods
"However, the difference is that computed properties are cached based on their dependencies. A computed property will only re-evaluate when some of its dependencies have changed. This means as long as message has not changed, multiple access to the reversedMessage computed property will immediately return the previously computed result without having to run the function again."
methods vs computed and filters :
Access vue instance/data inside filter method

Categories

Resources