Dynamic Routing in Aurelia - Alter Title - aurelia

{
route: 'content/:id',
name: 'Details',
title: 'Details',
viewPorts: { main: { moduleId: './admin/content/details' }, aside: { moduleId: './admin/content/aside' } },
settings: { menu:menuSection.content, access: { controller: 'content', action: 'get' } }
},
{
route: 'content/:id',
name: 'Add',
viewPorts: { main: { moduleId: './admin/content/details' }, aside: { moduleId: './admin/content/aside' } },
settings: { menu:menuSection.content, access: { controller: 'content', action: 'get' } }
title: 'Add',
href: 'content/0',
nav: true
}
import {Router} from 'aurelia-router';
activate(){
if (this.id === 0) {
this.router.title = "Add";
} else {
this.router.title = "Edit";
}
}
I am trying to alter the Title as its currently saying 'Add' for both new and updated content. I've tried routeConfig as well (which threw an error: Unhandled promise rejection TypeError: Cannot read property 'navModel' of undefined), just wondering if I am close, to finding the right code? Do I need to do some sort of push this.router.push?
I believe I may be required to do something with UpdateTitle:
class UpdateTitle {
run(routingContext, next, routeConfig) {
var instr = routingContext.nextInstructions.find(i => i.params.id !== undefined && i.params.id !== 0 && i.params.id !== '');
if(instr !== undefined) {
Unsure what to do here?//routeConfig.navModel.title("TEST");
debugger;
}
return next();
}
}

If you want to change the title from activate function, try
activate(params, routeConfig) {
routeConfig.navModel.title = 'Edit';
}

Related

Browser back button redirecting to home page in angular 8

Browser back button is not working. It redirects me to the home page instead of going to the previous page.
e.g
http://localhost:4200/#/component1/1
http://localhost:4200/#/component2/1
http://localhost:4200/#/component3/1
When I click back button when I am in component3 it has goes to component2 instead its going to the home page. Can anyone tell me the solution to this problem?
routing.ts
{
path: 'component1/:id',
component: Component1,
canActivate: [OAuthCallbackHandlerGuard],
data: { isId: true },
},
{
path: 'component2/:id',
component: Component2,
canActivate: [OAuthCallbackHandlerGuard],
data: { isId: true },
},
{
path: 'component3/:id',
component: Component3,
canActivate: [OAuthCallbackHandlerGuard],
data: { isId: true },
},
oauthcallbackhandlerguard.service.ts
canActivate(route: ActivatedRouteSnapshot, state: RouterStateSnapshot): Observable<boolean | UrlTree> {
this.adalService.handleWindowCallback();
let engId: number = 0;
let engagementDetailId: number = 0;
if(route.data.isEngagementDetailId == true)
{
let engDetailData =this.engagementService.$engagementDetailId.subscribe((data) => {
if (data !== undefined && data !== null) {
engagementDetailId = data;
}
});
}
else
{
let engData =this.engagementService.$engagementId.subscribe((data) => {
if (data !== undefined && data !== null) {
engId = data;
}
});
}
let groupIds = JSON.parse(sessionStorage.getItem('groupids'));
return this.validateUserAccess(engId, engagementDetailId, state,groupIds);
}
private validateUserAccess(engId: number, engagementDetailId: number, state: RouterStateSnapshot,groupIds:number[]): Observable<boolean | UrlTree> {
if (engId > 0 || engagementDetailId>0) {
return this.authGuardService.validateUserAccess(engagementDetailId, engId,groupIds).map(response => {
console.log(response);
return response ? true : this.router.parseUrl('/unauthorized');
if (response) {
this.router.navigate([state.url]);
}
else {
this.redictToUnAutherized();
}
},
(error) => {
console.log('auth failed. Error ', error);
// this.redictToUnAutherized();
return false;
});
}
else {
return Observable.of(true);
}
}
private redictToUnAutherized() {
this.router.navigate(['/unauthorized']);
}
1- Run your app in diffrent browser
2- Add default routes
const routes: Routes = [
{ path: '', pathMatch: 'full', component: HomeComponent },
{
path: 'component1/:id',
component: Component1,
canActivate: [OAuthCallbackHandlerGuard],
data: { isId: true },
},
{
path: 'component2/:id',
component: Component2,
canActivate: [OAuthCallbackHandlerGuard],
data: { isId: true },
},
{
path: 'component3/:id',
component: Component3,
canActivate: [OAuthCallbackHandlerGuard],
data: { isId: true },
},
{ path: '**', component: HomeComponent }
];
3- Try to check in OAuthCallbackHandlerGuard if it is going to navigate page back and allow it with Auth
constructor (private _location: Location)
this._location.back();

VUE nested route gives the empty page

My routine returns an empty page for the children's route. Checked on the web, but can't find anything useful. I have the following setup.
Vue routes in the same index.js file
{
path: "/admin",
name: "Admin",
component: Admin,
children:[
{
path: "/scheduler",
name: "Scheduler",
component: Scheduler,
meta: {
role: "user",
middleware: [auth],
requiresAuth: true,
},
},
],
meta: {
role: "user",
middleware: [auth],
requiresAuth: true,
},
},
my beforeEach :
router.beforeEach((to, from, next) => {
if (to.matched.some((record) => record.meta.requiresAuth)) {
if (window.localStorage.getItem("token") == null) {
next({
path: "/login",
query: {
redirect: to.fullPath,
},
});
} else {
const localData = JSON.parse(window.localStorage.getItem("user")).role;
const middleware = to.meta.middleware;
const context = { to, from, next };
//If there is no error from Auth, Unauthorized
if (store.getters.errorDetails == null) {
middleware[0]({ ...context }).then(() => {
if (localData == "user" && to.meta.role == "user") {
if (to.meta.role == "admin") {
next("/user");
}
next("/user");
} else if (localData == "admin" && to.meta.role == "admin") {
if (to.meta.role == "user") {
next("/admin");
} else {
next("/admin");
}
} else {
next("/login");
}
});
}
}
} else {
next();
}
});
and I can see the following screen. Not sure what I am doing wrong. Any help is appreciated.
enter image description here

Child element not updating props after change in data coming from apollo in nuxt/vue

UPDATE: the main issue seems to be that the props only get updated once. They should change when this.campaign.name becomes available.
I want to dynamically update the title and breadcrumb data fields and show them on the page. Currently page page shows undefined or null. How can I fix this?
I tried to create a computed value but it only seems to update once (after head and breadcrumb data is already showed). A method does not work since I don't have anything to trigger the method.
What is the correct way to fix this?
I am using nuxt generate to deploy the app.
export default {
components: { PageHeader },
middleware: 'authenticated',
data() {
return {
title: 'Campaigns' + this.campaignName,
breadcrumb: [
{
text: 'Campaigns',
href: '/'
},
{
text: this.campaignName,
href: '/'
}
],
campaign: ''
}
},
apollo: {
campaign: {
prefetch: true,
query: campaignQuery,
variables() {
return { id: this.$route.params.id }
}
}
},
computed: {
campaignName() {
return this.campaign && this.campaign.name
}
},
head() {
return {
title: this.title
}
}
}
</script>
Your computed property campaignName returns undefined cuz this.campaign.name is not defined
campaignName() {
if(this.campaign && this.campaign.name) return "Campaigns" + this.campaign.name;
return "default value";
}
Then you can use it directly in head
head() {
return {
title: this.campaignName
}
}
The solution was putting the data elements directly as a computer property. (so no recalculation)
export default {
components: { PageHeader },
middleware: 'authenticated',
data() {
return {}
},
apollo: {
campaign: {
prefetch: true,
query: campaignQuery,
variables() {
return { id: this.$route.params.id }
}
}
},
computed: {
title() {
return this.campaign && `Campaign: ${this.campaign.name}`
},
breadcrumb() {
return [
{
text: 'Campaign',
href: '/'
},
{
text: this.campaign && this.campaign.name,
href: '/'
}
]
}
},
head() {
return {
title: this.title
}
}
}
</script>

XState.js How to send context to a machine?

I am new to XState.js.
I want to use a simple ID in my context. How do I update the context using machine.send()?
const fetchMachine = Machine(
{
id: 'test',
initial: 'init',
context: {
id: '',
},
states: {
init: {
on: {
LOGIN: 'fetch',
},
},
fetch: {
on: {
LOGOUT: 'init',
},
},
}
})
const machine = interpret(fetchMachine).start()
How do I pass an ID to the context?
This does NOT do the trick:
machine.send({ type: 'LOGIN', id })
You have to use the assign action to update the context. I've updated your example to the following:
import { Machine, assign } from 'xstate';
// Action to assign the context id
const assignId = assign({
id: (context, event) => event.id
});
export const testMachine = Machine(
{
id: 'test',
initial: 'init',
context: {
id: '',
},
states: {
init: {
on: {
LOGIN: {
target: 'fetch',
actions: [
assignId
]
}
},
},
fetch: {
on: {
LOGOUT: 'init',
},
},
}
},
{
actions: { assignId }
}
);
Now once you call the following:
import { testMachine } from './machines';
const testService = interpret(testMachine).start();
testService.send({type: 'LOGIN', id: 'test' });
//or testService.send('LOGIN', { id: 'test'});
the action assignId will assign data from the event to your context

aurelia redirect line gives error "ERROR [app-router] Error: Unable to find module with ID: not-found"

I have been implementing an authorization step which I modeled on THIS question's answer by fragsalat.
Everything works until it reaches the line
return new Redirect('login');
upon which I get the error:
aurelia-logging-console.js:47 ERROR [app-router] Error: Expected router pipeline to return a navigation result, but got [{"url":"login","options":{"trigger":true,"replace":true},"shouldContinueProcessing":false}] instead.
at processResult (aurelia-router.js:1761)
at aurelia-router.js:1725
at <anonymous>
I am not sure why this has not just redirected?
This is the full app.ts file so you might see the context:
import { Aurelia, PLATFORM, autoinject } from "aurelia-framework";
import {
Redirect,
NavigationInstruction,
Router,
RouterConfiguration,
Next
} from "aurelia-router";
import { AuthService } from "../../auth/auth-service";
//import { Clients } from '../../public/components/login/login'
#autoinject
export class App {
public router: Router;
private TOKEN_KEY = "session";
configureRouter(config: RouterConfiguration, router: Router): void {
this.router = router;
config.title = "Aurelia";
config.addAuthorizeStep(AuthorizeStep);
config.map([
{
route: ["", "scheduler"],
name: "scheduler",
settings: {
icon: "scheduler",
auth: true,
roles: ["Employee", "Admin"]
},
moduleId: PLATFORM.moduleName("../components/scheduler/scheduler"),
nav: true,
title: "scheduler"
},
{
route: "clients",
name: "clients",
moduleId: PLATFORM.moduleName(
"../components/clients/clientList/clientList"
),
title: "Clients",
nav: true,
settings: {
nav: [
{ href: "#clients/clientsList", title: "Client List" },
{ href: "#clients/Create", title: "Create Client" }
],
auth: true,
roles: ["Employee", "Admin"],
pos: "left"
}
},
{
route: "clients/ClientsList",
name: "clientList",
moduleId: PLATFORM.moduleName(
"../components/clients/clientList/clientList"
),
settings: {
auth: true,
roles: ["Employee", "Admin"]
}
},
{
route: "clients/create",
name: "aboutTeam",
moduleId: PLATFORM.moduleName(
"../components/clients/clientCreate/clientCreate"
),
settings: {
auth: true,
roles: ["Employee", "Admin"]
}
},
{
route: "logout",
name: "logout",
settings: {
icon: "user",
auth: true,
roles: ["Employee", "Admin"],
pos: "right"
},
moduleId: PLATFORM.moduleName("../components/auth/logout/logout"),
nav: true,
title: "Logout"
},
{
route: "not-found",
name: "not-found",
settings: {
auth: true,
roles: ["Employee", "Admin"]
},
moduleId: PLATFORM.moduleName("../components/notFound/notFound"),
nav: false,
title: "Not Found"
},
{
route: "login",
name: "login",
settings: {
icon: "user",
auth: true,
roles: ["Employee", "Admin"],
pos: "right"
},
moduleId: PLATFORM.moduleName("../../public/components/login/login"),
nav: true,
title: "login"
}
]);
config.mapUnknownRoutes("not-found");
}
}
#autoinject
class AuthorizeStep {
private endDate: any;
static loginFragment = '../../public/components/login/login';
constructor(
private authService: AuthService,
private router: Router,
private aurelia: Aurelia
) { }
run(navigationInstruction: NavigationInstruction, next: Next): Promise<any> {
return Promise.resolve()
.then(() => this.checkAuthentication(navigationInstruction, next))
.then(result => result || this.checkAuthorization(navigationInstruction, next))
.then(result => result || this.checkOrigin(navigationInstruction, next))
.then(result => result || next());
}
checkAuthentication(navigationInstruction, next) {
// Do we have a JWT?
const session = this.authService.getIdentity();
if (!session) {
this.forceReturnToPublic(next); // No JWT - back to the public root.
}
console.log("CHECKaUTHENTICATION: ", navigationInstruction.getAllInstructions().some(i => i.config.settings.auth) )
if (navigationInstruction.getAllInstructions().some(i => i.config.settings.auth)) {
// Is the token valid?
if (this.authService.hasTokenExpired(session)) {
const currentUrl = navigationInstruction.fragment + (navigationInstruction.queryString ? `?${navigationInstruction.queryString}` : '');
console.log("FRAGMENT: ", navigationInstruction.fragment);
console.log("NAVIGATE INSTRUCTION: ", navigationInstruction)
console.log('currentURL: ', currentUrl);
localStorage.setItem('origin', currentUrl);
console.log("AuthorizeStep.loginFragment", AuthorizeStep.loginFragment)
next.cancel();
console.log("and it gets here!");
return new Redirect('login');
}
}
}
checkAuthorization(navigationInstruction, next) {
var usersRole = this.authService.getUserRole();
let requiredRoles = navigationInstruction.getAllInstructions()
.map(i => i.config.settings.roles)[0];
console.log("route Roles: ", requiredRoles);
let isUserPermited = requiredRoles ? requiredRoles.some(r => r === usersRole) : true;
console.log("isUserPermited: ", isUserPermited);
if (!isUserPermited) {
this.forceReturnToPublic(next);
}
}
checkOrigin(instruction, next) {
const origin = localStorage.getItem('origin');
// Check if we were not redirected to login page and have an origin
if (instruction.fragment !== AuthorizeStep.loginFragment && origin) {
localStorage.removeItem('origin');
return next.cancel(new Redirect(origin));
}
}
forceReturnToPublic(next) {
if (localStorage.getItem('origin')) {
localStorage.removeItem('origin') // Just in case we had origin set.
}
next.cancel();
this.authService.clearIdentity();
this.router.navigate("/", { replace: true, trigger: false });
this.router.reset();
this.aurelia.setRoot("public/public/public");
}
}
In all other pipeline steps you're using return next.cancel(new Redirect()), it should be the same case, as the pipeline step expects a Next as a return value, but you return a Redirect here.
Try changing it to
return next.cancel(new Redirect('login'));