Angular load url when using a router - javascript

Im using Angular 7 + router. For example, my home page is localhost:4200, one of my router's url is localhost:4200/route and I have an API end point at localhost:4200/api/foo.
I'm trying to let the browser load the api end point from both locations. If I put an anchor with href pointing to the API end point, both anchor link works perfectly. However, I need to do it programmatically and I have tried all of the following methods
window.open("localhost:4200/api/foo","_self")
window.location.replace('localhost:4200/api/foo');
window.location.href = 'localhost:4200/api/foo';
They all works on the home page but if I'm in the router page, doing so will get me to the home page.
Any help is greatly appreciated!
To be specific, I have a spring boot server with url patterns like /api/*. All other urls are handled by angular. I want the browser to load localhost:4200/api/foo, which is directly handled by a get request defined in the server
Demo:
My nav bar is a component and it stays the same regardless of the router.
The code behind that button click is below. Note that the first time I click it under some Angular routed url, it loads the home page, not google.com
onLogIn() {
window.open('https://www.google.com',"_self");
}
Routing.ts file
import { NgModule } from '#angular/core';
import { Routes, RouterModule } from '#angular/router';
import { IndexComponent } from "./index/index.component";
import { MicroserviceComponent } from "./microservice/microservice.component";
const routes: Routes = [
{ path: '', component: IndexComponent},
{ path: 'microservice/:id', component: MicroserviceComponent}
];
#NgModule({
imports: [RouterModule.forRoot(routes)],
exports: [RouterModule]
})
export class AppRoutingModule { }

add pathMatch to your empty route, it's missing tht's why you're redirected to the home component
const routes: Routes = [
{ path: '', component: IndexComponent, pathMatch:'full'},
{ path: 'microservice/:id', component: MicroserviceComponent}
];

Related

Redirect to specific vue component from external website

I'm trying to get a link from one website, to a specific component in another external website. The external website is utilizing vue and vue-router.
Assume that the first site is running on localhost:3000, I want to redirect to localhost/#/payments.
When I try direct redirect using this snippet(in localhost:3000):
<script>
window.location.href = "http://localhost/#/payments";
</script>
Vue is opening the default component, which is not desired.
EDIT:
This is the router of localhost:
export default function paymentRoutes() {
return [
{
path: "/payment/",
name: "PaymentSuccess",
component: PaymentSuccess
}
]
}
then in separated file:
Vue.use(VueRouter)
const routes = [ ...paymentRoutes()]
const router = new VueRouter({
routes
})
export default router

What is a proper way to preserve parameters after navigating back?

In my Angular app, I have list and details pages and I want to lkeep the pageIndex value before navigating to details page. There is a Back button in the details page and I can return the list page by clicking on that button. However, I want to get the pageIndex value when navigating back to the list page and let the user open the page where he/she was before. For example I navigate 3rd page on the list and click details. At this stage I set the pageIndex to 3 and then navigate to details. Then by clicking the Back button I can navigate back to the list page, but I need to retrieve the pageIndex as 3.
So, what is an elegant way to fix this problem in Angular 10+?
list-componnet
details(id) {
this.router.navigate(['/details'], { state: { id: id } }); // I pass id value of the record
}
details-componnet
constructor(private router: Router) {
this.id = this.router.getCurrentNavigation().extras.state.id;
}
back() {
this._location.back();
}
Just write a simple example to make it work, I use the sessionStorage and router together, use router to show your the routing module, actually you can just use sessionStorage only, and wrapper it in a servive. Then you can retrieve the pageIndex anywhere.
And if you want to use router only, the pageIndex paramater will be place in both list and detail component, since this two component all need to use this value, in list component you will need pageIndex to set data-table, in detail component you need this value to pass to list component when redirect back triggered.
The routing module like below:
import { NgModule } from "#angular/core";
import { Routes, RouterModule } from "#angular/router";
import { ListComponent } from "./list/list.component";
import { DetailComponent } from "./detail/detail.component";
const routes: Routes = [
{ path: "", redirectTo: "list", pathMatch: "full" },
{
path: "list/:pageIndex=1",
component: ListComponent,
pathMatch: "full"
},
{
path: "detail/:id",
component: DetailComponent
}
];
#NgModule({
imports: [RouterModule.forRoot(routes)],
exports: [RouterModule]
})
export class AppRoutingModule {}
Here you can navigate to list page from detail page use:
this.router.navigate(["/list/" + pageIndex]);
And then in list page's ngOnInit method to set current pageIndex to your data-table. Here is the demo: https://stackblitz.com/edit/angular-ivy-5vmteg?file=src/app/list/list.component.ts
Use sessionStorage, a listService or router queryParams to keep track of the current pageIndex.
I´d advocate for queryParams as it seems most logical and you can also link directly to specific page.
constructor(
private route: ActivatedRoute,
) { }
// Access the queryParam in list component
// Ie /list?pageIndex=4
this.route.queryParams.subscribe(params => {
// Do something with params.pageIndex if it exists
}
);
I´d also consider to change the way you handle routing to the details. If the route to the list is /list then route to the details should be /list/<listid> so you can link directly to the details if needed.
You can access the listId parameter as below but note it must also be specified as parameter in the router definition.
// Router definition
{ path: 'list/', component: ListComponent},
{ path: 'list/:listId', component: ListIdComponent}
// Access the listId in the details component
this.route.params.subscribe(param=> {
// Do somthing with param.listId
});

Split main JS bundle of an angular app based on component

I have developed an angular 4 web application, which has 3 components and all are independent components.
LoginPage
FormPage
Dashboard
LoginPage and FormPage are small components but Dashboard is a very big module.
My problems is i don't want to download the entire main bundle(1.5mb) on the login page (on page load which takes more time to download entire content) . i want to download the dashboard component related JS file chunk on dashboard component loading.
I am using ng-build --prod for production build
Is it possible to split the main bundle js based on component? Can I do the same split in vendor JS too?
You can have lazyloaded modules using Angular router loadChildren. Based on user access URL, their corresponding module will be loaded on demand.
import { NgModule } from '#angular/core';
import { RouterModule, Routes } from '#angular/router';
const app_routes: Routes = [
{
path: 'login',
loadChildren: 'app/login/login.module#LoginModule'
},
{
path: 'dashboard',
loadChildren: 'app/dashboard/dashboard.module#DashboardModule'
},
{ path: '', pathMatch: 'full', redirectTo: '/login' },
{ path: '**', pathMatch: 'full', redirectTo: '/login' }
];
#NgModule({
imports: [RouterModule.forRoot(app_routes)],
exports: [RouterModule]
})
export class AppRoutingModule {}

Ionic 3 feature module with multiple pages

I am using Ionic 3 and angular 5. I have one feature module 'Settings':
import { NgModule } from '#angular/core';
import { IonicPageModule } from 'ionic-angular';
import { SettingsPage } from './test';
#NgModule({
declarations: [
SettingsPage,
],
imports: [
IonicPageModule.forChild(SettingsPage),
],
})
export class SettingsPageModule {}
Under Settings module I want to add 5 more pages.
I checked a lot of post and cannot found out how to do that. Is it even possible ?
The Ionic3 standard way, if you use lazy loading, is: one module per page.
If you use the CLI, ionic generate page command will do the job for you and create a folder with 4 files whenever you create a new page.
If you don't want pages to live each in a separate directory, one way could be to create the new page-related files in the same directory.
But, if you want multiple pages in one module, it's not going to work, at least in my experience - e.g. if you try to place two pages in the same directory and load them from the same module, you'll get this error message:
Error: /.../src/pages/pagegroup/pageX.ts has a #IonicPage decorator, but it does not have a corresponding "NgModule" at /.../src/pages/pagegroup/pageX.module.ts
Below I'm explaining a working solution to have multiple pages, each with its own module, in a single directory.
Let's assume you start from this:
src
settings
settings.html
settings.module.ts
settings.scss
settings.ts
...and you want to add a page named "CustomSettingsPage".
Depending on how complex this page is, you must add the following 2 to 4 files, in the same directory (src/settings) - the optional ones are between square braces:
[custom-settings.html]
custom-settings.module.ts
[custom-settings.scss]
custom-settings.ts
The module and page .ts files will have a similar structure:
custom-settings.module.ts
import { NgModule } from '#angular/core';
import { IonicPageModule } from 'ionic-angular';
import { CustomSettingsPage } from './custom-settings';
#NgModule({
declarations: [
CustomSettingsPage,
],
imports: [
IonicPageModule.forChild(CustomSettingsPage),
],
exports: [
CustomSettingsPage
]
})
export class CustomSettingsPageModule {}
custom-settings.ts
import { Component } from '#angular/core';
import { IonicPage } from 'ionic-angular';
#IonicPage()
#Component({
selector: 'page-custom-settings',
template: `<your html template here>`
})
export class CustomSettingsPage {
// your page code here
};
Instead of template: you could use templateURL: 'custom-settings.html' - in that case, you should create the corresponding custom-settings.html template file in the same directory.
If you want to add the CSS rules for this page, you can create an optional custom-settings.scss file like:
.page-custom-settings {
/* your rules here */
}
or, you can add those CSS rules to the existing settings.scss file: this is really up to you.
I believe what you want is "modals"
https://ionicframework.com/docs/components/#modals
You can add individual pages under your settings.
I'm late to this question but just in case someone needs it in the future!
I'm not sure if you are referring to this but you can have several pages into one module having a folder tree like, for example:
pages
settings
childPage 1
child1.page.(html|scss|ts)
childPage 1
child1.page.(html|scss|ts)
settings.module.ts
settings.page.(html|scss|ts)
then in your Setting Routing Module you do like
import ...
const routes: Routes = [{
path: '',
redirectTo: 'pathtoRedirect', // if you need it
pathMatch: 'full'
}, {
path: '',
component: SettingsPage
}, {
path: 'child-page-1',
component: ChildPage1
}, {
path: 'child-page-2',
component: ChildPage2
}]
#NgModule({
imports: [RouterModule.forChild(routes)],
exports: [RouterModule]
})
export class SettingsPageModule {}
Then in your App Routing Module you can do something like:
import ...
const routes: Routes = [{
...
}, {
path: 'settings',
loadChildren: () => import('./pages/settings/settings.module').then(m => m.SettingsPageModule),
}, {
...
}]
#NgModule({
...
})
export class AppRoutingModule{}
This should work. What a component needs is for it to be in ANY module. It's true "module per page strategy" is included as best practice, however, sometimes I simply don't want to have many files that actually can be deleted and managed under the same module.
From this point, you can have a different folder tree if you feel like it, or even create a deeper nested route like
/settings
/settings/children/:id
/settings/children/otherchildren/childrenpage
Now it would be up to you and your project needs!
Hope this is useful for somebody!

Unable to load second level routing page in vuejs after refreshing it

I have my VueJS app running. It is working fine but the only issue is that when I try to refresh the second or third level routing pages, it shows me an error message in the console, stating:
Failed to load resource: the server responded with a status of 404 ()
For eg.,
http://localhost:8080 renders me home page. No issue on refreshing.
http://localhost:8080/details renders details page. No issue on refreshing.
http://localhost:8080/details/users renders users page. On refreshing, it errors out.
I also have similar links defined for http://localhost:8080/details/assets and http://localhost:8080/details/groups which all errors out on page refresh.
Here is the code for main.js:
// The Vue build version to load with the `import` command
// (runtime-only or standalone) has been set in webpack.base.conf with an alias.
import Vue from 'vue'
import VueRouter from 'vue-router'
import App from './App.vue'
import { routes } from './routes';
Vue.use(VueRouter);
//Vue.config.productionTip = false
const router = new VueRouter({
mode: 'history',
routes
});
/* eslint-disable no-new */
new Vue({
el: '#app',
router,
components: { App },
template: '<App/>'
})
new Vue(Vue.util.extend({ router }, App)).$mount('#app');
and for routes.js:
import Home from './components/summary.vue'
import Details from './components/details/details.vue'
import Users from './components/details/users/users.vue'
import Assets from './components/details/assets/assets.vue'
import Groups from './components/details/groups/groups.vue'
export const routes = [
{ path: '/', component: Home},
{ path: '/details', component: Details},
{path: '/details/users', component: Users},
{path: '/details/groups', component: Groups},
{path: '/details/assets', component: Assets}
];
Any idea on how to fix this issue?
As is described in official document of vue-router
To get rid of the hash, we can use the router's history mode, which leverages the history.pushState API to achieve URL navigation without a page reload
So navigating only in front end will not send request to back end, which is your spring boot application (you can see this from network traffic)
However, when you refresh your page, the request is sent directly to back end, which results the 404 error.
To fix your problem, one option could be setting a default 404 page to index.html which is suggested here
#Component
public class WebConfiguration implements EmbeddedServletContainerCustomizer {
#Override
public void customize(ConfigurableEmbeddedServletContainer configurableEmbeddedServletContainer) {
configurableEmbeddedServletContainer.addErrorPages(new ErrorPage(HttpStatus.NOT_FOUND, "/index.html"));
}
}
Hope it works for you!

Categories