Angular service An argument for 'model' was not provided - javascript

I have a service and it accepts id as paramter and I am requesting the route with the id but I received the error above on my service . Any idea?
#service
const apiBaseUrl = `${environment.apiUrl}/api/userprofile`;
deactivateUserProfileStatus(id: number) {
return this.httpRequestService.put(`${apiBaseUrl}/inactive/${id}`);
}
#ts
DeactivateUserProfileStatus(id: number) {
this.isInProgress = true;
this._userService
.deactivateUserProfileStatus(id)
.pipe(
finalize(() => {
this.isInProgress = false;
})
)
.subscribe({
next: (res) => {
this._notificationService.showSuccess(
'User status has been updated successfully.'
);
// this.generalForm.disable();
this.getUserGeneralDetails();
// this._router.navigate(['transactions']);
},
error: (err) => {
this._notificationService.showError(
'Something went wrong, Try again later.'
);
this.isInProgress = false;
},
complete: () => {
this.isInProgress = false;
},
});
}
}

You should add the body (or atleast empty body) for your PUT request.
(method) HttpClient.put(url: string, body: any, options: {
headers?: HttpHeaders | {
[header: string]: string | string[];
};
observe?: "body";
params?: HttpParams | {
[param: string]: string | string[];
};
reportProgress?: boolean;
responseType: "arraybuffer";
withCredentials?: boolean;
}): Observable<...> (+14 overloads)
the only GET requests call without body just by URL.

Related

Having issue with typing a return type of fetching function

I made an async custom function wrapper that takes care of response returning 401 unauthorized.
How do i properly type return type of my fetching function to make my data from useQuery infer that type?
// ASYNC WRAPPER
type HandlerType = (args?: any) => Promise<any>;
export const asyncWrapper =
(handler: HandlerType) =>
async (args?: any): Promise<any> => {
try {
const result = await handler(args);
return result;
} catch (err: any) {
if (err.response.status === 401) {
// refresh token then again call handler
await sessionService.refreshToken();
const result = await handler(args);
return result;
}
}
};
//FETCHING REQUEST
export type QuestionsType = {
answerOptions: {
_id: string;
answerText: string;
isCorrect: boolean;
};
questionText: string;
};
const getQuestions = asyncWrapper(
async (difficulty: string): Promise<QuestionsType[]> //type not working => {
const token = localStorage.getItem("accessToken");
try {
const response = await axios.get("/questions", {
headers: {
Authorization: token,
},
});
return response.data;
} catch (e) {
throw new Error("Custom");
}
}
);
const { data } = useQuery(["quiz"], quizService.getQuestions); // data type is "any"
Use generics to type it, here is a playground
export const asyncWrapper =
<A, R>(handler: (args: A) => Promise<R>) =>
async (args: A): Promise<R> => {
try {
return handler(args);
} catch (err: any) {
if (err.response.status === 401) {
// refresh token then again call handler
return handler(args);
}
}
throw new Error("Handle this")
};
//FETCHING REQUEST
export type QuestionsType = {
answerOptions: {
_id: string;
answerText: string;
isCorrect: boolean;
};
questionText: string;
};
const getQuestions = asyncWrapper(
async (difficulty: string): Promise<QuestionsType[]> => {
const token = localStorage.getItem("accessToken");
try {
return [];
} catch (e) {
throw new Error("Custom");
}
}
);

Capture Angular API response from service to component

In my Angular 12 application, I am making an API call in the service file and want to capture the response of the API in my component.
But since the API response is async, the console below always returns undefined. I have tried async await as well. Here is what I have tried:
INSIDE SERVICE:
public checkEmail(emailToVerify: any) {
this.myService.emailValidate({ email: emailToVerify }).subscribe({
next: (data: { result: any) => {
console.log('updateEmail-res', data);
return data;
},
error: (err: any) => {
console.log('updateEmail-err', err);
}
});
}
INSIDE COMPONENT:
this.apiResponse = await this.myService.checkEmail(customerEmail);
console.log("this.apiResponse", this.apiResponse)
In Component
validateEmail = async () => {
const params = {
emailAddress: 'test#gmail.com',
};
const apiResponse: boolean = await this.emailService.validateEmail(params);
console.log(`apiResponse===`, apiResponse);
};
In Service
export class EmailService {
constructor() {}
validateEmail = async (params: {
emailAddress: string;
}): Promise<boolean> => {
return new Promise((resolve) => {
const isValid = /^\w+([\.-]?\w+)*#\w+([\.-]?\w+)*(\.\w{2,3})+$/.test(
params.emailAddress
);
resolve(isValid);
});
};
}
The checkemail method does nothing. If you already have emailValidate, why put it in another method?
just one emailValidate instead of checkEmail
this.apiResponse = await this.myService.emailValidate({ email: customerEmail});
console.log("this.apiResponse", this.apiResponse)
o
in you component:
this.myService.emailValidate({ email: customerEmail}).subscribe({
next: (data: { result: any) => {
console.log('updateEmail-res', data);
this.apiResponse = data;
},
error: (err: any) => {
console.log('updateEmail-err', err);
}
});

Type not being checked in custom response structure in Express

I am starting of with typescript and have hit a roadblock where I can't figure out why types are not being validated.
Route
app.use((req: Request, res: Response) => {
// here 404 is a string but should be a number according to type defined but no error is shown
return res.error({ status: '404', message: 'The API route does not exist' })
})
Middleware
interface APIResponse {
status: number,
message?: string | null,
data?: any
}
const responseHelper = (req: Request, res: Response, next: NextFunction) => {
res.showDefaultErrorPage = (status: number = 500) => {
//...
}
res.success = (options: APIResponse) => {
const {
status = 200,
message = null,
data
} = options
//...
}
res.error = (options: APIResponse) => {
const {
status = 500,
message = null
} = options
//...
}
next()
}
export default responseHelper
Custom type definition for express response
/* eslint-disable no-unused-vars */
declare namespace Express {
interface Response {
showDefaultErrorPage?: any
showErrorPage?: any
success?: any
error?: any
}
}
You could change your type definiton to this:
import express from "express"
const app = express()
interface APIResponse {
status: number,
message?: string | null,
data?: any
}
// add "declare global" here
declare global {
namespace Express {
interface Response<
ResBody = any,
Locals extends Record<string, any> = Record<string, any>,
StatusCode extends number = number
> {
showDefaultErrorPage?: any
showErrorPage?: any
success: (options: APIResponse) => Response<any, Record<string, any>, number>
error: (options: APIResponse) => Response<any, Record<string, any>, number>
}
}
}
// Dont give explicit types here. Let TypeScript infer them
app.use((req, res, next) => {
res.showDefaultErrorPage = (status: number = 500) => {
//...
}
res.success = (options: APIResponse) => {
const {
status = 200,
message = null,
data
} = options
return res.status(0).json({})
}
res.error = (options: APIResponse) => {
const {
status = 500,
message = null
} = options
return res.status(0).json({})
}
next()
})
// Dont give explicit types here
app.use((req, res) => {
return res.error({ status: '404', message: 'The API route does not exist' })
// ^^^^^^ Expected error
})

How to type this middleware function on aws lambda?

I have this middleware that gets the aws lambda function event:
export function hasuraActionHandler<Input, Output>(
allowedRoles: string[],
handler: (
input: Input,
hasuraRole: string,
hasuraUserId?: string,
ipAddress?: string,
// #ts-ignore
context: Context,
) => Promise<typeof formatJSONResponse<Output>>
) :any {
return async (event, context, callback) => {
const { hasuraRole, hasuraUserId, input, ipAddress } =
getHasuraActionParams<Input>(event);
if (!allowedRoles.includes(hasuraRole)) {
return callback(null, {
statusCode: 403,
body: JSON.stringify({
message: 'Forbidden',
}),
});
}
try {
callback(null, {
statusCode: 200,
body: await handler(input, hasuraRole, hasuraUserId, ipAddress, context),
});
} catch (e) {
console.error(e);
return callback(null, {
statusCode: 400,
body: JSON.stringify({
message: e
}),
});
}
};
}
getHasuraActionParams function:
export function getHasuraEventParams<T>(event: APIGatewayEvent): {
data: T;
hasuraRole: string;
hasuraAllowedRoles?: string[];
hasuraUserId?: string;
} {
const data = parse(event.body).event.data
const {
"x-hasura-allowed-roles": hasuraAllowedRoles,
"x-hasura-role": hasuraRole,
"x-hasura-user-id": hasuraUserId
} = parse(event.body).event.session_variables;
return { data, hasuraRole, hasuraAllowedRoles, hasuraUserId };
}
the aws function:
const ban_account = hasuraActionHandler<ban_accountArgs, ban_account_output>(
["admin"],
async (input, hasuraRole, hasuraUserId, context) => {
....
return formatJSONResponse({
id: "1"
});
}
);
ban_account_output type:
type ban_account_output = {
id: string;
};
the formatJSONResponse function:
export const formatJSONResponse = (response: Record<string, unknown>) => {
return {
statusCode: 200,
body: JSON.stringify(response)
};
};
Question is, how to type the Promise<typeof formatJSONResponse<Output> in the middleware? As is it throws this: TS2635: Type '(response: Record ) => { statusCode: number; body: string; }' has no signatures for which the type argument list is applicable.
Is it also possible to type the :any on the middleware?
codesandbox: https://codesandbox.io/s/lingering-pond-wcu8go?file=/src/index.ts

Error during add AsyncValidator in angular

I'm trying to add a new AsyncValidator to check whether user's email already exist in database.
Below is may validator:
export class UniqueEmailValidator implements AsyncValidator {
constructor(private webService: WebWrapperService) {}
validate(ctrl: AbstractControl): Promise < ValidationErrors | null > | Observable < ValidationErrors | null > {
return this.webService.isEmailExistEx(ctrl.value)
.pipe(
map(res => {
console.log("get response" + res);
if (res) {
return { 'uniqueEmail': true};
}
return null;
})
);
}
}
The function isEmailExistEx in service will send a post request to server.
isEmailExistEx(email: string): Observable<boolean> {
this.http.post(this.baseUrl + "auth/verify",
{
"email": email
})
.subscribe(
(val: any) => {
if (!val.result) {
return of(false);
} else {
return of(true);
}
},
response => {
return of(false);
},
() => {
return of(false);
});
}
It reports following error:
A function whose declared type is neither 'void' nor 'any' must return a value.
How should I modify this function?
You're subscribeing to the Observable which will consume the value wrapped in it.
Use map instead of subscribeing and return a boolean value from it::
isEmailExistEx(email: string): Observable<boolean> {
return this.http.post(this.baseUrl + "auth/verify", { email })
.pipe(
map((val: any) => val.result ? true : false)
);
}

Categories