This is pretty simple, I'm trying to insert a value that has a string as a parameter.
Let's give an example:
const stringName = "User".
and my goal is to activate a function that gonna be called like that
User.find();
I tried the follows without success: stringName.find() but didn't worked and also [stringName].find()
Why I want to do that: I receive a param that is a string, and I want to search with this param in my DB so the real query gonna be something like that: param.findAll({where....})
I'm sure that there is a simple solution like the examples above. hope for help.
You can store User in an object, and then access it with the string.
const myObjects = {
User: User,
// Post: Post, ...
}
const stringName = "User"
myObjects[stringName].find('foo')
You probably could do something like this:
let fncName(clsName) {
if(window[clsName]) {
let cls = new window[clsName]();
cls.find();
}
}
This however requires all classes that you are calling to have a function named find. Probably better to do a switch on the passed in string and go from there.
let fncName(clsName) {
switch(clsName) {
case 'User':
User.find();
default:
...
}
}
You can't simply execute .find() on a string unless you define the find() method in string prototype.
If your goal is to execute some methods of an object, and that object's name you are getting as a string.
If that object is available in your current context:
const param = "User";
this[param].find()
If object is not available in current context:
let objectMap = {
"user": USER
};
let param = "user";
objectMap[param].find();
Related
I do the following:
const blockOrField = new Block();
ev.dataTransfer.setData("data", blockOrField);
When I get data in another place:
cosnt data = e.dataTransfer.getData("data");
I get data as [object Object] instead real instrance.
Before passing to data I see that it is instance:
if (blockOrField instanceof FieldDefinition) {
alert("works");
}
ev.dataTransfer.setData("data", blockOrField);
I know it should be serialized to string JSON, but I have complicated instance with composition.
If you look at the documentation for setData() it specifically says "A DOMString representing the data to add to the drag object.". So you are out of luck trying to store an object reference there.
What I would do here is create a another object somewhere and store the needed reference there with an id.
const dataTransferCache = {};
function onDragStart(ev) {
const block = new Block();
const id = GetRandomId(); // Just get an id somehow
dataTransferCache[id] = block;
ev.dataTransfer.setData("data", id);
}
function onDragEnd(ev) {
const id = ev.dataTransfer.getData("data");
const block = dataTransferCache[id];
delete dataTransferCache[id]; // Remove the value again
}
This would even support multi touch dragging if that is somehow needed. If this needs to be shared between components you could simply put the dataTransferCache in a separate file and include a reference to in in both components.
i am using object literal as an alternative to if else/switch statements. In doing so not knowing how to assign same value to different keys.
What i am trying to do?
Based on variable named "user" should redirect to different links.
if value of "user" is admin or manager should redirect to say "www.exampledomain.com". If value of "user" is "purchaser" should redirect to "https://stackoverflow.com".
To do so i have used object literal instead of if-else which is clumsy.
Below is the code,
get user() {
return ( {
'admin': 'www.exampledomain.com',
'manager': 'www.exampledomain.com',
'purchaser': 'https://stackoverflow.com',
} )[user];}
As you see from above code, admin and manager keys point to same url "www.exampledomain.com". Is there a way to assign it something like below.
get user() {
return ( {
'admin': 'manager': www.exampledomain.com',
'purchaser': 'https://stackoverflow.com',
} )[user];}
Could somebody help me solving this. Thanks.
Personally, I don't see any reason to use the second idea, furthermoe it is not valid JS code.
If you are trying to reduce code duplication you can just extract your urls into a constant variable like that.
static get REDIRECT_URLS() {
return {
"PRIMARY_SITE" : "www.exampledomain.com",
"SECONDARY_SITE" : "stackoverflow.com",
};
}
get user() {
return ( {
'manager' : FooClass.REDIRECT_URLS.PRIMARY_SITE,
'admin': FooClass.REDIRECT_URLS.PRIMARY_SITE,
'purchaser': FooClass.REDIRECT_URLS.SECONDARY_SITE,
} )[user];}
Of course there are other possible solutions, like having keys like 'admin|manager' : "url", but that doesn't seem to be a good choice and you need to add extra logic to iterate over the object keys and check if a key matched the regex.
If the problem were to be viewed in isolation, I would solve this issue by simply flipping the data structure around
const linkToTypeMapping = {
'www.exampledomain.com': ['admin', 'manager'],
'https://stackoverflow.com': ['purchaser'],
}
But that doesn't really fix your issue.
The way I would solve the actual use-case is to simply add a link property to your user object and just populate and later access userObject.link.
However for completeness's sake, here's how you would extract a user's link from the data structure I posted above.
const get_link = (type) => {
for (let key in linkToTypeMapping) {
if(linkToTypeMapping.includes(type)) {
return key;
}
}
}
This is obviously very complicated as far as the code goes, but if your linkToTypeMapping object is expected to become fairly large, this might actually be the right solution for you.
You can make default route like that:
function user() {
const defaultRoute = "www.exampledomain.com"
return ({
'admin': defaultRoute,
'manager': defaultRoute,
'purchaser': 'https://stackoverflow.com'
})[user];
}
or that
function user2() {
const defaultRoute = "www.exampledomain.com"
return ({
'someoneElse': "www.google.com",
'purchaser': 'https://stackoverflow.com'
})[user] || defaultRoute;
}
or mix both styles, depending on how complex your statement is;
or even make it from the other side
function user3(user) {
const routes = {
"www.google.com": ["admin", "manager"],
"www.exampledomain.com": ["purchaser"]
};
return Object.keys(routes).find(k => routes[k].includes(user));
}
console.log(user3('manager')); //www.google.com
Here is my question: Instead of calling a smart contract function like this
//assuming the name of the contract function is called "balanceOf"
contract.methods.balanceOf("0x", "0x").call(err, balance) => {
console.log({err, balance});
})
i want to know if it is possible to call like this:
var funcName = "balanceOf";
var parameter = "0x, 0x";
contract.methods.funcName(parameter).call(err, balance) => {
console.log({err, balance}];
})
Thank You.
The objects in javascript can be accessed like an array by using the keys as indexes. So in your case it would be:
var funcName = "balanceOf";
var parameter = "0x, 0x";
contract.methods[funcName]("0x", "0x").call(err, balance) => {
console.log({err, balance}];
})
But the way you passing the parameter is not going to work like that. You are just passing a string as a parameter. Think of it like passing parameters to any other function.
Currently, I have a select element in my html which has a ngModel to the object details:
[ngModel]="details?.publicInformation?.firstname"
However, publicInformation may not exist in that object, or if it does, maybe firstname does not exist. No matter the case, in the end, I want to create the following:
[ngModel]="details?.publicInformation?.firstname" (ngModelChange)="details['publicInformation']['firstname'] = $event"
Basically, if the select is triggered, even if neither of publicInformation nor firstname exist, I would like to create them inside details and store the value from the select.
The issue is that I am getting
Cannot set property 'firstname' of undefined
Can someone explain what I am doing wrong here and how can I achieve the result I desire?
You need to initialize details and publicInformation to empty object
public details = {publicInformation : {}};
You should do that when you load the form data.
For example, you might have something like this:
ngOnInit() {
this._someService.loadForm().then((formData: FormData) => {
this.details = formData;
});
}
Then, you could modify that to fill in the missing empty properties you need:
ngOnInit() {
this._someService.loadForm().then((formData: FormData) => {
this.details = formData || {};
if (!this.details.publicInformation) {
this.details.publicInformation = { firstname: '' };
} else if (!this.details.publicInformation.firstname) {
this.details.publicInformation.firstname = '';
}
});
}
However, it would be better to place this logic in the services, so that they are responsible for adding all the necessary empty properties to the data they load, or if you are using Redux, then it should go into the reducers.
I have a Dto that I want to enable the service layer to filter:
The method selectFields takes an array of field names that should be returned, the other properties will be removed.
What is a short way to enumerate the properties on the class so I can loop through them and set the filtered ones to null?
In the BaseDto I take care of cleaning falsy values (well I need the same function here too as a matter of fact).
class UserServiceDto extends BaseDto {
constructor(userDto) {
super();
this.fbUserId = userDto.fbUserId;
this.fbFirstName = userDto.fbFirstName;
this.fbLastName = userDto.fbLastName;
this.gender = userDto.gender;
this.birthdate = userDto.birthdate;
this.aboutMe = userDto.aboutMe;
this.deviceToken = userDto.deviceToken;
this.refreshToken = userDto.refreshToken;
this.updatedAt = userDto.updatedAt;
this.createdAt = userDto.createdAt;
}
selectFields(fields) {
// --> what's your take?
}
toJson() {
return super.toJson();
}
}
Edit:
The service layer receives a dto from repository layer including all database fields. The ServiceLayerDto aims at filtering out fields that are not required by the web api (or should not be exposed as a security measure e.g. PK field, isDeleted, etc). So the result would I'm looking at the end of a service method for would look something like:
return new UserServiceDto(userDto)
.selectFields('fbUserId', 'fbFirstName', 'fbLastName', 'birthdate', 'aboutMe', 'updatedAt', 'createdAt')
.toJson();
The return value would be a plain json object that the web layer (controller) sends back to the http client.
If you are ok with spread operator, you may try following approach:
class UserServiceDto {
constructor() {
this.a = 1;
this.b = 2;
this.c = 3;
}
selectFields(...fields) {
const result = {};
fields.forEach(key => result[key] = this[key]);
return result;
}
}
new UserServiceDto().selectFields('a', 'c'); // {a: 1, c: 3}
Looking to super.toJson() call, I think that it would not work due to the result of my selectFields() call would not be an instance of UserServiceDto class. There are some possible ways from this point I see:
instantiate new UserServiceDto object inside selectFields() body, remove all fields that not listed in the ...fields array (javascript delete is okey) and return it;
play with UserServiceDto constructor params to save positive logic on selectFields(), and pass to constructor only that props that need to be set up; in this case instantiating a temporary object will not require properties removing;
change the signature of toJson method, or better add a new signature, which would allow to pass fields array and then put current selectFields logic inside toJson method (and remove selectFields method at all): new UserServiceDto().toJson('a', 'c')...
Purely for info, I ultimately changed my app architecture.
The repository returns a Dto to the service layer (dto being mapped directly from the sql queries).
The service builds a static View based on the Dto and returns it to the web layer (represented by a plain json object).
In my directory structure, I have:
- service
-- views
--- index.js
--- UserInfo.js
The view is a simple filter. E.g. UserInfoView:
exports.build = ({ fbUserId, fbFirstName, fbLastName, gender, birthdate, aboutMe, updatedAt, createdAt }) => {
return {
fbUserId,
fbFirstName,
fbLastName,
gender,
birthdate,
aboutMe,
updatedAt,
createdAt,
};
};
Using the view, e.g. UserInfoView in the service looks like this:
const Views = require('../service/views');
exports.findActiveByUserId = async (pUserId) => {
const userDto = await UserRepository.findActiveByUserId(pUserId);
if (!userDto) {
throw new ServiceError(Err.USER_NOT_FOUND, Err.USER_NOT_FOUND_MSG);
}
return Views.UserInfo.build(userDto.toJson());
};
I think that this is much more descriptive compared to my initial take on the problem. Also, it keeps the data objects plain (no additional methods required).
It is unfortunate that I can't require receiving an type (View) in the web layer, I might be able to solve that problem with Typescript later on.