Javascript function at key value assignment in Angular 7 - javascript

I am trying to find a solution for the next problem I encountered. I am trying to build a dynamic string by using Amchart3 in my project, and I need to do something like this:
return [{
id: 'Rate',
alphaField: 'alpha',
balloonText: function(graphDataItem, graph): String {
let stringNew = 'smth';
return stringNew;
},
}];
The problem I encountered is that the function written in the ballonText value isn't triggered (I put a breakpoint to check) and doesn't return anything when calling the function that uses the returned list.
My question is, how could I write a function like
key: function(a,b) {
return a + b;
}
in Angular 7, like it is done in Javascript?

Your problem is the way you assign the function 'value' to your key ballonText. If using es6, which lets you shorthand key/value names, you can assign the function like so:
const es6Assign = {
id: 'Rate',
myFunc(str) {
return str.toUpperCase();
}
}
// prints out HELLO
console.log('calling es6Assign func: ', es6Assign.myFunc('hello'));
If you want to do it the vanilla way, you should name the function even if its the value of a key:
const explicitAssign = {
id: 'Rate',
myFunc: function myFunc(str) {
return str.toLowerCase();
}
}
// prints out hello
console.log('calling explicitAssign func: ', explicitAssign.myFunc('HELLO'));
As to the why?; my guess is that even though to you the key is the 'name' of the function, to the code, a function that has no name doesn't exist, i.e. function() { ... } will return undefined. I added the case in the sample Fiddle so you can see what happens.

Related

Replacing a function deeply nested inside an object in javascript

I have an object containing functions that are nested potentially deeply (could be more levels than this so I need a solution that will work at any depth):
x = {
a: function() { console.log ("original function 1") },
b: {
c: {
d: function() { console.log ("original function 2") }
}
}
}
I want to be able to pass the function's keypath as an argument to another function and replace the original function with a new one:
g = function( functionAddress ) {
functionAddress = function() { console.log( "replacement function" )}
}
so that after executing:
g("x.b.c.d");
x.b.c.d() // replacement function
g("x.a");
x(a) // replacement function
I've been able to process the argument using split, shift and reduce so I can access the function at the specified address as in:
keypath = x["b"]["c"]["d"]
but if I try to use newFunc to replace the function at that location, it only replaces the value of keypath, not the function at that address.
Any help would be appreciated. Thanks!
There's no straightforward way to do that. Instead, you have to implement your function to do so.
Here's a more-or-less simple way, using Array#split() and Array#reduce():
const x = {
a: function() { console.log ("original function 1") },
b: {
c: {
d: function() { console.log ("original function 2") }
}
}
}
const setDeep = (object, path, value)=>{
const pathArray=path.split('.')
pathArray.slice(0,-1).reduce(Reflect.get,object)[pathArray[pathArray.length-1]]=value
}
setDeep(x, 'b.c.d', function(){console.log('replacement function')});
x.b.c.d() //replacement function

JavaScript: Write Function that take an object and an array of functions as input args and return an array

I want to take an object and an array of functions and return an array. I am trying to use the for loop here.
I have the following code below:
const fnArr = [
function firstName() {
return this.first;
},
function lastName() {
return this.last;
},
];
const obj = { first: 'Nimit', last: 'Maru' };
function callAll(obj, fnArr){
let newArray = [];
for (let i=0; i<fnArr.length; i++){
let eachFunc = fnArr[i];
return newArray.push(eachFunc.call(obj))
}
}
callAll(obj, fnArr)
My expected output is:
['Nimit', 'Maru']
But the output from my personal code is returning: 1
Question 1: What am I doing wrong here?
////////////////////////////////////////////////////////////////////////////////////////////////////////////
Additionally, the solution I was given is below:
const fnArr = [
function firstName() {
return this.first;
},
function lastName() {
return this.last;
},
];
const obj = { first: 'Nimit', last: 'Maru' };
const callAll = (obj, fnArr) => {
return fnArr.map(fn => {
return fn.call(obj);
});
};
It produces the right answer.
Question 2: In the solution code above, why do I need the call method in "return fn.call(obj)"?
A conceptual explanation of when you need or don't need call in these types of situations would be greatly appreciated.
You are returning in each loop. So after the first loop the the function ends and code doesn't execute further.
It returns 1 because push() method returns the length of the array after adding elements to it. Initally array was empty when 1 element is added it returns 1.
You don't need to necessarily use map() just push() the element(don't return). And return the newArray after loop.
const fnArr = [
function firstName() {
return this.first;
},
function lastName() {
return this.last;
},
];
const obj = { first: 'Nimit', last: 'Maru' };
function callAll(obj, fnArr){
let newArray = [];
for (let i=0; i<fnArr.length; i++){
let eachFunc = fnArr[i];
newArray.push(eachFunc.call(obj))
}
return newArray
}
console.log(callAll(obj, fnArr))
In the solution code above, why do I need the call method in "return fn.call(obj)"?
The this binding to the function depends upon how the function is called. If the function is called as the method of the object then the object will be binded to that method.
In the above code this inside your both functions will refer to window object if they are called normally. So we want this to refer the object so we use call
Why eachFunc(obj) returns [undefined, undefined]?
When you don't use call this will refer to window object. So there is not property named first and last on window object so it returns undefined

Convert function parameter in string into parameter in object

I am using node.js.
I have a function that can be called this way;
add_row({location:'L1', row_name:'r1', value:'18.4'});
I have a string like this;
var str_param = "location:'L1', row_name:'r1', value:'18.4'";
I tried to do something like this to keep my code simple;
add_row(str_param);
It did not work. What is a good way to use str_param to call add_row?
You could convert the string to an object that the function accepts.
function toObj(str) {
const a = str.split(/,.?/g);
return a.reduce((p, c) => {
const kv = c.replace(/'/g, '').split(':');
p[kv[0]] = kv[1];
return p;
}, {});
}
toObj(str); // { location: "L1", row_name: "r1", value: "18.4" }
DEMO
I think this may be your issue:
{location:'L1', row_name:'r1', value:'18.4'} // Object
var str_param = "location:'L1', row_name:'r1', value:'18.4'"; // Not object
var str_param = "{location:'L1', row_name:'r1', value:'18.4'}"; // Object String
I do not use Node JS but just taking a shot in dark. If not you could just make function like:
function addRow(pLocation, pRowName, pValue) {
var row = {
location: pLocation,
row_name: pRowName,
value: pValue
}
// Logic ....
}
If that does not work try using Object string and look at function ParseJSON I believe it's called.

Is it possible reuse function argument as an object?

Is it possible to do this?
function getVariable(elem) {
return $scope.elem;
}
or this;
function getField(field) {
return data[0].field;
}
getField('price') should return the equivalent of data[0].price and
getVariable('id') should return the value of $scope.id
Upon experimenting, I've found that for example getField('price') is looking for data[0].field as is in the function - not for data[0].price.
When using the dot notation for object property access in Javascript, it evaluates the name literally. As you discovered, it's always looking for a property named "field" or "elem".
When you want is bracket syntax, i.e.:
function getField(fieldName) {
return data[0][fieldName];
}
Same for your other function.
Try like this:
(function(){
var data = {
'id' : 123,
'name' : 'Toyata Camarry 2009',
'price' : 14500
},
fxArgObject = function(field) {
return data[field];
};
var price = fxArgObject('price');
console.log(price);
})();

could not get the property value of my object in angularJs

I get undefined whenever I get the value of a property of an object.
function run(id){
var report = services.getReportInfo(id);
var childReport = {
id: newGuid(),
parentId: report.id, // i get undefined
reportPath: report.path // i get undefined
};
...
}
services.js
angular.module('project.services').factory('services', function(){
var reports = [
{
....
},
{
....
}
];
function getReportInfo(id){
var report = reports.filter(function(element){
return element.id === id;
});
};
return{
getReportInfo: getReportInfo
};
}
Whenever I put breakpoint on my var report = services.getReportInfo(id) it could contains the correct values for each property of the my report object. However, when I get the report.id or report.path, I get undefined value.
--Edited--
Oh, I know now where I got wrong.
The getReportInfo function returns an array and I'm accessing the properties without telling from what index should it get the values for the said properties.
function run(id){
var report = services.getReportInfo(id);
var childReport = {
id: newGuid(),
parentId: report[0].id,
reportPath: report[0].path
};
...
}
I placed static index 0, since I know that the array will always have a length of 1.
You are not returning anything from the .factory method and the getReportInfo is also not returning anything. For what you are trying to do, try to use .service method:
angular.module('project.services').service('services', function(){
var reports = [
{
....
},
{
....
}
];
this.getReportInfo = function (id){
var report = reports.filter(function(element){
return element.id === id;
});
return report;
}
}
Here is a good explanation on how to use .factory and .service:
Confused about Service vs Factory
Two immediate issues with the code I can see:
1) Your factory function needs to return a value or constructor function. Right now your code is not initializing the factory to any value.
2) Your getReportInfo function also doesn't return a value, yet you are assigning the function result to a variable.
Read more here: http://docs.angularjs.org/guide/dev_guide.services.creating_services

Categories