How to get params from url in angular and express? - node.js

I have a URL which looks like http://www.example.com/idf34he8sf/9iad2hf7usnf. I want to get the params idf34he8sf and 9iad2hf7usnf
I have used below code
In angular
this.route.paramMap.subscribe(params => {
this.organizationId = params.get("organizationId");
this.embedId= params.get("embedId");
}
In Node
req.params
and
req.originalUrl
I want to get the params idf34he8sf and 9iad2hf7usnf

You have to define params in your api as-
example/:organizationId/:embedId
then fetch these params using-
constructor(private router: Router) {
this.organizationId = this.router.snapshots.params['organizationId']
this.embedId = this.router.snapshots.params['embedId']
}

Node knows nothing about Angular, you will need to design your API to take those paramaters and pass them when calling the API.

You can use #angular/router
import { Router } from '#angular/router';
Define a variable to hold URL
href:string;
params:string[];
Then in Constructor
constructor(private router: Router) {
}
In ngOnInit
this.href = this.router.url;
this.params = this.href.split('/');

In angular you can use ActivatedRoute to fetch params from the URL
import { Router, ActivatedRoute} from '#angular/router';
constructor(route: ActivatedRoute){}
/* Do Something*/
public someFunction(){
this.route.queryParams.subscribe(params => {
/* use Params*/
}
}
In NodeJS you will need to add while declaring your routes as shown below:
router.get('/:id', (req,res) =>{
let id = req.params; // for parameterised routes
// fetching query string use below:
// region = req.query.region;
return res.json(id);
});

//import the ActivatedRoute to use route.snapshot.params
import { ActivatedRoute} from '#angular/router';
//define a variable to store the param from url
public param:any;
//And in constructor create a instance of ActivatedRoute
constructor(private route:ActivatedRoute,) {}
//Then in ngOnInit
ngOnInit(): void {
this.param = this.route.snapshot.params["Your-params-name in url)"];
// params-name means (/:id/)
//this will store the params from your url to the variable param (public)
}
//in my url is I wanted to store specific id of a book
// from url localhost:4200/books/60ab539f678gfraep/
// I used
{path: 'books/:id',component: showBookComponent},
//in my ROUTING MODULE
//so I gave above code as
public Id:string;
ngOnInit():void {
// this.Id = route.snapshot.params['id'];
}

Related

How to get url params in NextJs like: userid/:this_is_a_param

i'm having trouble trying to get url params with nextJs.
so similar to i'd usually do with express i'd like to get a :param from the url
like so
users/:userid/
console.log(req.params.userid)
all i could do is get the "userid" from url like so ?userid=
i'm also using typescript
I assume that you want to get the "userid" path variable from the respective page.
If the path users/[userid].tsx is a page, then it would look like this:
/pages/users/[userid].tsx:
import { useRouter } from 'next/router'
import { NextPage } from 'next'
const UserPage: NextPage = () => {
const router = useRouter()
const { userid } = router.query
// TODO
return <></>
}
export default UserPage
However, if you want to use the route as an API route, then it looks like this:
/pages/users/[userid].ts:
import type { NextApiRequest, NextApiResponse } from 'next'
export default (req: NextApiRequest, res: NextApiResponse) => {
const { userid } = req.query
// TODO
res.status(200).json({ name: `User ID: ${userid}` })
}
It depends on the place that you need this parameters.
For Client side , you have to use useRouter hook.
For getStaticProps and getServerSideProps you have to use context object that is passed to this functions automatically.
For Api Routes , it's exactlly like express js and you can use req.params.userid

Accessing middleware injected data in Typescript

Here's a high level view of a controller in Typescript-Node :
As I'm storing details of user in product model, I have used a middleware to check if user if logged in before accessing the endpoint and also injecting user info to the req which can be further used in different controllers
exports.addProduct = async (req: Request, res: Response, next: NextFunction) => {
// images:
try {
// logic to handle data from req.body
// getting this user id from middleware isLoggedIn
// injecting user id into request in the isLoggedIn middleware
req.body.user = req.user._id;
const product = await Product.create(req.body);
return res.status(200).json({
success: true,
product,
});
} catch (error) {
logger.error(error);
}
};
Getting error : Property 'user' does not exist on type 'Request<ParamsDictionary, any, any, ParsedQs, Record<string, any>>' , on the line
req.body.user = req.user._id;
isLoggedIn is typical function to check Bearer token or header or cookies and then inject user info to the request
It worked Perfectly in Javascript, now trying same in Typescript as a part to learn Typescipt
There are two ways to achieve this:
Extending express Request locally
Extending express Request globally
Using the local way require to write lots of redundent code and that's why
the global way is much better. it can be done by creating file as follows:
index.d.ts
import { User } from "../../models/user";
// to make the file a module and avoid the TypeScript error
export {};
declare global {
namespace Express {
export interface Request {
user: User;
}
}
}
Then add this config to tsconfig.json file
"typeRoots": [
"src/#types",
"./node_modules/#types",
],
Then Request object will recognize user and user can be injected from any middleware to be used in any controller.
The problem is that according to the typing of req, there is no property named user. TypeScript is notifying you that req.user should be undefined, according to the available typings. There are some possible solutions to fix your problem.
You could explicitly type the variable as any. This is considered to be bad practice sometimes, because in general you should try to type everything correctly (nevertheless: it works).
// Option 1: Explicitly declare variable as any
req.body.user = (req as any).user._id;
You could also check if req.user is defined, like this:
// Option 2: Check req.user manually
if (req.user) req.body.user = req.user._id;
else throw new Error("Some Error");
You could also type the req correctly, according to the API specifications of your middleware. This is usually a lot of work if done manually. Some modules ship with correct TypeScript-typings already.
Maybe you want to also look into this question since it is very similar to your question.
first create a folder call types it should be at the root of your project
then at yow tsconfig.json in the compilerOptions section add a paths prop
{
"compilerOptions": {
...
"paths": {
"express": [
"./types/express/index.d.ts"
],
}
}
then at the types dir add a new dir call express inside add an index.d.ts go ahead a copy them express definitions
// Type definitions for Express 4.17
// Project: http://expressjs.com
// Definitions by: Boris Yankov <https://github.com/borisyankov>
// China Medical University Hospital <https://github.com/CMUH>
// Puneet Arora <https://github.com/puneetar>
// Dylan Frankland <https://github.com/dfrankland>
// Definitions: https://github.com/DefinitelyTyped/DefinitelyTyped
/* =================== USAGE ===================
import express = require("express");
var app = express();
=============================================== */
/// <reference types="express-serve-static-core" />
/// <reference types="serve-static" />
import * as bodyParser from 'body-parser';
import * as serveStatic from 'serve-static';
import * as core from 'express-serve-static-core';
import * as qs from 'qs';
/**
* Creates an Express application. The express() function is a top-level function exported by the express module.
*/
declare function e (): core.Express;
declare namespace e {
/**
* This is a built-in middleware function in Express. It parses incoming requests with JSON payloads and is based on body-parser.
* #since 4.16.0
*/
var json: typeof bodyParser.json;
/**
* This is a built-in middleware function in Express. It parses incoming requests with Buffer payloads and is based on body-parser.
* #since 4.17.0
*/
var raw: typeof bodyParser.raw;
/**
* This is a built-in middleware function in Express. It parses incoming requests with text payloads and is based on body-parser.
* #since 4.17.0
*/
var text: typeof bodyParser.text;
/**
* These are the exposed prototypes.
*/
var application: Application;
var request: Request;
var response: Response;
/**
* This is a built-in middleware function in Express. It serves static files and is based on serve-static.
*/
var static: serveStatic.RequestHandlerConstructor<Response>;
/**
* This is a built-in middleware function in Express. It parses incoming requests with urlencoded payloads and is based on body-parser.
* #since 4.16.0
*/
var urlencoded: typeof bodyParser.urlencoded;
/**
* This is a built-in middleware function in Express. It parses incoming request query parameters.
*/
export function query (options: qs.IParseOptions | typeof qs.parse): Handler;
export function Router (options?: RouterOptions): core.Router;
interface RouterOptions {
/**
* Enable case sensitivity.
*/
caseSensitive?: boolean | undefined;
/**
* Preserve the req.params values from the parent router.
* If the parent and the child have conflicting param names, the child’s value take precedence.
*
* #default false
* #since 4.5.0
*/
mergeParams?: boolean | undefined;
/**
* Enable strict routing.
*/
strict?: boolean | undefined;
}
interface SessionData {
userIp: string;
ipDetails: any;
publicKey: string;
session: string;
iv: string;
decrypted: any;
}
interface Application extends core.Application { }
interface CookieOptions extends core.CookieOptions { }
interface Errback extends core.Errback { }
interface ErrorRequestHandler<
P = core.ParamsDictionary,
ResBody = any,
ReqBody = any,
ReqQuery = core.Query,
Locals extends Record<string, any> = Record<string, any>
> extends core.ErrorRequestHandler<P, ResBody, ReqBody, ReqQuery, Locals> { }
interface Express extends core.Express { }
interface Handler extends core.Handler { }
interface IRoute extends core.IRoute { }
interface IRouter extends core.IRouter { }
interface IRouterHandler<T> extends core.IRouterHandler<T> { }
interface IRouterMatcher<T> extends core.IRouterMatcher<T> { }
interface MediaType extends core.MediaType { }
interface NextFunction extends core.NextFunction { }
interface Request<
P = core.ParamsDictionary,
ResBody = any,
ReqBody = any,
ReqQuery = core.Query,
Locals extends Record<string, any> = Record<string, any>
> extends core.Request<P, ResBody, ReqBody, ReqQuery, Locals> { }
interface RequestHandler<
P = core.ParamsDictionary,
ResBody = any,
ReqBody = any,
ReqQuery = core.Query,
Locals extends Record<string, SessionData> = Record<string, SessionData>
> extends core.RequestHandler<P, ResBody, ReqBody, ReqQuery, Locals> { }
interface RequestParamHandler extends core.RequestParamHandler { }
export interface Response<ResBody = any, Locals extends Record<string, SessionData> = Record<string, SessionData>>
extends core.Response<ResBody, Locals> { }
interface Router extends core.Router { }
interface Send extends core.Send { }
}
export = e;
if you notice from the above I added an interface call SessionData if you look almost at the end I set Locals to be equals to it. at the Response
now at yow endPoint you can apply it like this
import type e from "express";
export const endPoint: e.RequestHandler = (req, res, next) => {
//code
};
you can go beong that you can also add them params if there are any, the res body, the req body and stuff
const endPoint: e.RequestHandler<YowParamsObj,YowResBodyObj,YowReqBodyObj,ThemQueryParamsObj> = (req, res, next) => {
//code
};

Why can't I access `userService` variable after express instance running in Nodejs

I was trying to create an endpoint in node.js, more specifically in express
but I am not sure why I can't access userService variable when requesting from a client.
I've gotten Cannot read property 'userService' of undefined, but when i move ServicesFactory.getInstance().getUserService() inside the signUp function it works?!
I am guessing that node.js garbage collects it due to it's not being used until the user make a request.
export class UserApi implements WebEndpoint {
router: Router
userService = ServicesFactory.getInstance().getUserService()
constructor() {
this.router = Router()
this.router.post('/signup', this.signUp)
}
signUp(req: Request, res: Response): void {
const user: User = req.body
this.userService.signUp(user)
res.send("Successfully registered")
}
}
I found the problem, so basically I am a noob.
consider this example
class a {
constructor() {
this.a1 = 'hello';
}
greet(){
const greeting = `${this.a1} dude!`;
console.log(greeting);
};
}
class b {
b1 = new a();
constructor() {
this.b1.greet.call();
}
}
new b();
Now it wouldn't run, because b class called greet method with a new context, the same with express when you provide a function as a handler on an Express endpoint it will be called with a new set of context (read:this) that's why this.userService in my code above won't work because there is no userService property in the context provided by Express.
The solution is simple. Arrow function.
signUp = (req: Request, res: Response): void => {
const user: User = req.body
this.userService.signUp(user)
res.send("Successfully registered")
}
Now the function will inherit it's class's context.You can refer to this for more detail answer.

Using Service in Express Router

I am pretty new in the NodeJS but I would like to learn something new. I came from .NET fancy dependency injection, inversion of controll, microservice shiny world so I am trying write some service in TypeScript based on my previous experiences.
I am using express and express router to create some api. I have some methods in router which handles api calls and I want to use some kind of service object for data retrieving and manipulation.
I inject the service into the router using constructor injection but if I want to use my service it throws an error:
TypeError: Cannot read property 'layoutService' of undefined
I understood that the methods were called withouth context so I added .bind(this) to the each method regsitration and it works, but I dont know if it is the best way how to do it.
Does anyone have a better idea?
simplified server.ts
import express, { Router } from "express";
// inversion of controll
import container from "./ioc";
import { TYPE } from "./constants";
import IMyService from "./abstract/IMyService";
// import routers
import MyRouter from "./api/MyRouter";
app = express();
app.use(bodyParser.json());
app.use(bodyParser.urlencoded({ extended: true }));
const router: Router = express.Router();
const myRouter: MyRouter = new MyRouter(container.get<IMyService>(TYPE.IMyService));
app.use("/", router);
app.use("/api/v1/layouts", layoutRouter.router);
MyRouter.ts
import IMyService from "./abstract/IMyService";
import { Router, Request, Response } from "express";
import { inject } from "inversify";
import { TYPE } from "../constants";
export default class MyRouter {
public readonly router: Router;
private readonly myService: IMyService;
constructor(
#inject(TYPE.IMyService) myService: IMyService
) {
this.myService = myService;
this.router = Router();
this.routes();
}
public GetAll(req: Request, res: Response): void {
this.myService.getAll()
.then(data => {
const status: number = res.statusCode;
res.json({ status, data });
})
.catch(err => {
const status: number = res.statusCode;
res.json({ status, err });
});
}
public GetOne(req: Request, res: Response): void {
const id: string = req.params.id;
this.myService.getOne(new ObjectID(id))
.then(data => {
const status: number = res.statusCode;
res.json({ status, data });
})
.catch(err => {
const status: number = res.statusCode;
res.json({ status, err });
});
}
routes(): void {
this.router
.get("/", this.GetAll)
.get("/:id", this.GetOne);
}
}
If you define your function with the arrow syntax (ES6), it will "bind" the context to it automatically and you won't need to bind them. But it will depends on your use case (ou might need to bind a different context)

typescript: call public function

I'm new in typescript. In my node-express app, I want to call public function. But this is always undefined, so when I call public function, it throw always error. My code is given below:
app.ts
import * as express from 'express';
import User from './user/ctrl';
class App {
public express: express.Application;
constructor() {
this.express = express();
this.routes();
}
private routes():void {
let router = express.Router();
router.get('/', User.index);
this.express.use('/', router);
}
}
export default new App().express;
./user/ctrl.ts
class User {
public demo:string;
constructor() {
this.demo = "this is text";
}
public infox() {
console.log("demoo test : ", this.demo);
}
public index(req:any, res:any) {
console.log(this) // output: undefined
this.infox(); // throw an error.
}
}
const user = new User();
export default user;
Server run at port 3000.
Any suggestion??
When you passed a reference the User.index function, the this inside it will change based on how it is called. Or when strict mode is on this will be undefined.
Change router.get('/', User.index); to router.get('/', (req, res) => User.index(req, res));. Notice that User.index is wrapped inside an arrow function which captures the correct this when User.index is called.
See red flags for this in TypeScript

Resources