In a Vue component, I have a method like as below
methods: {
submitMethod() {
let objA = {
id: this.id,
this.anObject
}
}
}
It gives, Syntax Error: this is a reserved word.
how to use the object, which is defined in somewhere like data() or computed, in the object of the method in Vue.js?
One workaround is that, this.anObject can be assigned to local variable and use that variable inside objA as below
submitMethod() {
let anObject = this.anObject
let objA = {
id: this.id,
anObject
}
}
But, is there a way to use this.anObject directly inside objA?
If you can use the object restSpread operator, you can use it:
methods: {
submitMethod() {
let objA = {
id: this.id,
...this.anObject
}
}
}
Otherwise, you can use Object.assign:
methods: {
submitMethod() {
let objA = Object.assign(this.anObject, {
id: this.id,
})
}
}
thats because your JSON is invalid. it should be like
let objA = {
id: this.id,
anObject: this.anObject
}
We can use this keyword with the help of copy this keyword as a local variable.
methods: {
submitMethod() {
let _this = this;
let objA = Object.assign(this.anObject, {
id: _this.id,
})
}
}
Related
We have many different games and while I could write a function that uses a bunch of if statements to get the proper model I would like to solve it bit cleaner.
I currently have the following code:
const { game, id } = request.params as { game: string; id: string }
const gameMap = {
'd3' : prisma.d3Profile
}
if (!Object.keys(gameMap).includes(game)) {
return { error: 'unknown game' }
}
// #ts-ignore
const profile = gameMap[game].findUnique({
where: {
id: parseInt(id)
}
})
if (profile) {
return profile
}
return { error: 'profile not found'}
Everything works but I would love to solve this problem without resorting to using ts-ignore. Does anyone have an idea how to solve this?
Explicitly define type of request.params
const gameMap = {
'd3' : prisma.d3Profile
}
const { game, id } = request.params as { game: keyof typeof gameMap; id: string }
This way typescript has a way to infer it correctly
I have this:
LocationController.ts
import {GenericController} from './_genericController';
interface Response {
id : number,
code: string,
name: string,
type: string,
long: number,
lat: number
}
const fields = ['code','name','type','long','lat'];
class LocationController extends GenericController{
tableName:string = 'location';
fields:Array<any> = fields;
}
const locationController = new LocationController();
const get = async (req, res) => {
await locationController._get(req, res);
}
export {get};
GenericController.ts
interface Response {
id : number
}
export class GenericController{
tableName:string = '';
fields:Array<any> = [];
_get = async (req, res) => {
try{
const id = req.body['id'];
const send = async () => {
const resp : Array<Response> = await db(this.tableName).select(this.fields).where('id', id)
if (resp[0] === undefined) {
// some error handling
}
res.status(status.success).json(resp[0]);
}
await send();
}catch (error){
// some error handling
}
}
}
What I want to do is to pass the Response interface from LocationController to the GenericController parent, so that the response is typed accurately depending on how the child class has defined it. Clearly it doesn't work like this since the interface is defined outside of the class so the parent has no idea about the Response interface in the LocationController.ts file.
I've tried passing interface as an argument in the constructor, that doesn't work. So is there a way I can make this happen? I feel like I'm missing something really simple.
Typically, generics are used in a situation like this. Here's how I'd do it:
interface Response {
id: number;
}
// Note the generic parameter <R extends Response>
export class GenericController<R extends Response> {
tableName: string = "";
fields: Array<any> = [];
_get = async (req, res) => {
try {
const id = req.body["id"];
const send = async () => {
// The array is now properly typed. You don't know the exact type,
// but you do know the constraint - R is some type of `Response`
let resp: Array<R> = await db(this.tableName).select(this.fields).where("id", id);
if (resp[0] === undefined) {
// some error handling
}
res.status(status.success).json(resp[0]);
};
await send();
} catch (error) {
// some error handling
}
};
}
import { GenericController } from "./_genericController";
interface Response {
id: number;
code: string;
name: string;
type: string;
long: number;
lat: number;
}
const fields = ["code", "name", "type", "long", "lat"];
// Here we tell the GenericController exactly what type of Response it's going to get
class LocationController extends GenericController<Response> {
tableName: string = "location";
fields: Array<any> = fields;
}
const locationController = new LocationController();
const get = async (req, res) => {
await locationController._get(req, res);
};
export { get };
If this is not enough and you wish to somehow know the exact response type you're going to get, I believe the only way is a manual check. For example:
import { LocationResponse } from './locationController';
// ... stuff
// Manual runtime type check
if (this.tableName === 'location') {
// Manual cast
resp = resp as Array<LocationResponse>
}
// ...
You could also check the form of resp[0] (if (resp[0].hasOwnProperty('code')) { ... }) and cast accordingly. There are also nicer ways to write this, but the basic idea remains the same.
Generally, a properly written class should be unaware of any classes that inherit from it. Putting child-class-specific logic into your generic controller is a code smell. Though as always, it all depends on a particular situation.
I have a middleware that exports context.isMobile. I can access it from layout like this:
layout (ctx) {
if(ctx.isMobile) {
return 'mobile'
} else if (ctx.isDesktop) {
return 'default'
}
},
...but I can't access the context from data or computed. How do I get the context there?
You can access the context via this.$nuxt.context like this:
export default {
data() {
console.log(this.$nuxt.context)
return { /*...*/ }
},
computed: {
myProp() {
console.log(this.$nuxt.context)
return 'foo'
}
}
}
I am trying ES6 object destructuring inside a constructor hoping to assign value to a member variable. It is not working. Its showing undefined when I am
printing the value inside a member function. Its printing correctly if I print inside the constructor.Is this valid?
class Environment {
constructor(env) {
const { name, version } = env
console.log(name)
}
printName() {
console.log(this.name)
}
}
var obj = { "name": "inst1", "version": "12.2.7" };
var envObj = new Environment(obj);
envObj.printName();
You can assign destructured properties directly to object props using aliases and a wrapping the expression in parentheses:
class Environment {
constructor(env) {
({ name: this.name, version: this.version } = env);
}
printName() {
console.log(this.name)
}
}
var obj = { "name": "inst1", "version": "12.2.7" };
var envObj = new Environment(obj);
envObj.printName();
If env contains only the properties that you want (name, version), you can Object#assign directly to this:
class Environment {
constructor(env) {
Object.assign(this, env);
}
printName() {
console.log(this.name)
}
}
var obj = { "name": "inst1", "version": "12.2.7" };
var envObj = new Environment(obj);
envObj.printName();
I think I might be missing something obvious here, but if I have an object with a couple of functions, such as:
myFunctions = {
getLastName: function() { return " Bloggs"; },
getName: function(prefix) { return prefix + this.getLastName(); }
};
... how can I ensure 'this' is referencing the object in getName() when I call it with promise syntax, i.e:
q.fapply(myFunctions.getName, ['Mr.'])
.then(function(fullName) {
...
});
Currently, 'this' is just global scope when called via q.fapply()
Use Q.post instead,
var myFunctions = {
getLastName: function() { return " Bloggs"; },
getName: function(prefix) { return prefix + this.getLastName(); }
};
Q.post(myFunctions, 'getName', ['Mr.'])
.then(function(fullName) {
alert(fullName);
});