I need to return true or false based on some condition, I am not getting the cleaner code to do this:
I need to hide or show some elements on UI based on this condition which should return true or false:
scope.isDataEnabled =function(options){ //Here if supppose a comes,
// then i need to send true, otherwise false
if(!$rootScope.currentProduct.id ==
ProductConstants.BB_PRODUCT_ID){
return true;
}
else{
_.map( $rootScope.currentUser.permissions, permissionObj =>{
// permissions is an Array
return (permissionObj.module == "DATA" &&
permissionObj.values == "b" && options=="a") //need to send true
//if this condition satisfies
});
}
return false; //after returning true,
//it comes to this line and sets to false
}
Please help me guide, what i should use, to achieve it. I was thinking of using ternary operator, but not getting how to use it inside map.
Simplifying your code to a minimal test scenario that can be manipulated (and just use plain old ES20xx) may help. Something like:
let $rootScope = {
currentProduct: {
id: `x`
},
currentUser: {
permissions: [{
module: `BB_DATASET`,
values: `b`
}, {
module: `some`,
values: `a`
}]
}
};
const ProductConstants = {
BB_PRODUCT_ID: `y`
}
console.log(testMe(`a`)); // true (currentProduct.id not BB_PRODUCT_ID)
ProductConstants.BB_PRODUCT_ID = `x`;
console.log(testMe(`a`)); // true (module && values && options)
$rootScope.currentUser.permissions[0].module = `AA_DATASET`;
console.log(testMe(`a`)); // false (module not BB_DATASET)
$rootScope.currentUser.permissions[0].module = `BB_DATASET`;
console.log(testMe(`b`)); // false (options not `a`)
$rootScope.currentUser.permissions[0].values = `c`;
console.log(testMe(`a`)); // false (values not `b`)
function testMe(options) {
if ($rootScope.currentProduct.id !== ProductConstants.BB_PRODUCT_ID) {
return true;
}
const found = $rootScope.currentUser.permissions.find( v =>
v.module === `BB_DATASET` &&
v.values === `b` &&
options == `a`);
return found ? true : false;
}
.as-console-wrapper {
top: 0;
max-height: 100% !important;
}
Firstly, the return inside of the map function will not return the value to the outer function, you are only returning the result to the map function itself. The result of the map function is never being returned.
Also, I think you might want to use _.some instead of map. map is used for transforming data, while some is used to check if something matches a condition.
return _.some($rootScope.currentUser.permissions, permissionObj => {
return (permissionObj.module == "BB_DATASET"
&& permissionObj.values == "b"
&& options=="a")
});
This will check if any of the permissions match the given condition. Alternatively you can use _.all if you want everything to match the condition.
Related
Is it possible to have object extensions in JavaScript? For example
Extensions.js
function any.isNullOrEmpty() {
if (this == null || this == "") {
return true
}
return false
}
app.js
var x = ""
console.log(x.isNullOrEmpty()) //should log true
is this possible? How do I do it?
You could add a method to the Object prototype, and use the valueOf method to get the value of the string:
...but, because null is a primitive that cannot have a method, the only way I can think of to get the target to be null would be to use call, apply or bind.
But you would never do this in production code, because modifying the prototype of built-in objects is discouraged.
'use strict' // important for the use of `call` and `null`
Object.prototype.isNullOrEmpty = function() { return this === null || this.valueOf() === '' }
const s = ''
console.log(s.isNullOrEmpty())
const t = null
console.log(Object.prototype.isNullOrEmpty.call(t))
You could use Object.prototype to extend this type of functionality in JavaScript.
Object.prototype.isNullOrEmpty = function() {
if (this == null || this == "") {
return true
}
return false
}
var x = "";
x.isNullOrEmpty(); // returns true
you need to add your custom method into prop type of object or array or everything u want to use your method on it.
but in your case you need to this like code below:
Object.prototype.isNullOrEmpty = function(){
if (this === null || this == "") {
return true
}
return false
}
let a = {a:'10'}
console.log(a.isNullOrEmpty())
function validateValue(value){
function isNullEmpty(){
return (value === void (0) || value == null)
}
return { isNullOrEmpty }
}
}
I have a problem to solve using some data from an object. The data could take a few forms and may or may not exist in the first place. For example
things : {
oranges: true,
apples : false
}
but it could equally be:
things : {
oranges: false,
apples : false
}
or maybe things doesn't even exist
I need to:
1) Determine that things exists
2) Determine that things contains further keys
These two statements need to be verified in one callable function e.g thingsHasData()
3) If things does have data, is any of the data set to true?
This also needs to be a callable function e.g fruitsIsTrue()
4) Return the key for one of the true values
trueFruit() - this should only return one key, but it doesn't matter which (it shouldn't ever have two true values as per business rules but it's more of a fallback to just return one if for some reason it does)
So I've been able to get the key of a true key-value pair using the following:
var thingsList = {
things : {
oranges: false,
apples : true
}
}
var trueFruit = Object.keys(thingsList).filter(function(key) {
return thingsList[key];
});
return thingsList[0];
This correctly returns apples and only apples so it works for point 4 but not the others, and I feel like there is a better way to do this not having to rely on repeating the same .filter in a few different functions. Ideas?
You could take functions and for a true value, use Array#find.
function thingsHasData(object) {
return 'things' in object;
}
function fruitsIsTrue(object) {
return 'things' in object && Object.values(object.things).some(Boolean);
}
function trueFruit(object) {
return 'things' in object && Object.keys(object.things).find(k => object.things[k]);
}
var a = {},
b = { things: {} },
c = { things: { oranges: true, apples : false } },
d = { things: { oranges: false, apples : false } };
[a, b, c, d].forEach(o => console.log(
thingsHasData(o),
fruitsIsTrue(o),
trueFruit(o)
));
To check if the Object things exist, you can use the following code:
if (typeof things != "undefined") {
// It exists!
}
To check if an object has any children, check Object.keys(things).length > 0.
So the check for 1) and 2) would look like:
let things = {
oranges: true,
apples: false
}
if (typeof things != "undefined") {
// It exists!
if (Object.keys(things).length > 0) {
// It has children!
}
}
var thingsList = {
things : {
oranges: false,
apples : true
},
things2 : {
oranges: true,
apples : true
}
};
function validateThings(things) {
// (1) checks for a falsy value of things
if (!things) {
return false;
}
var keys = Object.keys(things);
// (2) checks if things has keys
if (!keys.length) {
return false;
}
// (3) then it checks for every single keys value if it is truthy
for (var i = 0, len = keys.length; i < len; i++ ) {
if (things[keys[i]]) {
// (4) return this value — all tests passed
return things[keys[i]];
}
}
return false;
}
console.log(validateThings(thingsList.notInList));
console.log(validateThings(thingsList.things));
console.log(validateThings(thingsList.things2));
const thingsHasData = arg => (arg.things && Object.keys(arg.things).length>0) ? true : false;
const trueFruit = arg => {
if (!arg.things) return;
let fruitIndex = null;
let fruitValues = Object.values(arg.things);
fruitValues.forEach((value, index) => {
if (value) fruitIndex = Object.keys(arg.things)[index];
});
return fruitIndex;
}
What's an explicit way that I can be sure that the only results for a boolean check will be "true" or "false"? In other words, I want to exclude "undefined" as a possibility as much as is possible. Two options would be:
FUNCTION ONE:
private canMove = (currentOptionSelected): boolean => {
if (this.client.services) {
for (const service of this.client.services) {
if (service === currentOptionSelected) {
if (service.currentStage === 'enrolling') {
return true;
}
}
}
}
}
FUNCTION TWO:
private canMove = (currentOptionSelected): boolean => {
if (this.client.services) {
for (const service of this.client.services) {
if (service === currentOptionSelected) {
return service.currentStage === 'enrolling';
}
}
}
}
EDIT: Upon a commenter's response, a more robust alternative is to explicitly return 'false', like this:
private canMove = (currentOptionSelected): boolean => {
if (this.client.services) {
for (const service of this.client.services) {
if (service === currentOptionSelected) {
//You should also rethink this return statement
return service.currentStage === 'enrolling';
}
}
}
return false;
}
I would follow that up by asking if adding an extra "return 'false'" for a case where "client.services" exists, but "currentStage !== 'enrolling" would be even better? Or would that second 'else' clause be redundant in this case?
Secondly, he writes I should rethink the return statement in terms of where it is in the function. What would the alternative be? In short, I'm trying to find the most robust yet terse way to write this function.
These are not equivalent. The second version returns false in some of the cases where the first one returns undefined. A caller that checks the value to be explicitly === false will observe different behavior.
Both can return undefined which is probably not great. It'd be best to always return with an actual value of true or false
Short answer is No, they aren't equivalent:
The first one won't return false in any case.
While the second can return false if service.currentStage !== 'enrolling'.
But as stated by Ryan both can return undefined which you should avoid, you need to explicitly return false whenever a condition isn't met.
This is how should be your code:
private canMove = (currentOptionSelected): boolean => {
if (this.client.services) {
for (const service of this.client.services) {
if (service === currentOptionSelected) {
//You should also rethink this return statement
return service.currentStage === 'enrolling';
}
}
}
return false;
}
Note:
The return false; here will make sure you return false when
this.client.services is undefined.
Using a return statement in a for loop this way is a very very bad idea, in fact you will only make one iteration.
I have a function that checks to see whether or not a request has any queries, and does different actions based off that. Currently, I have if(query) do this else something else. However, it seems that when there is no query data, I end up with a {} JSON object. As such, I need to replace if(query) with if(query.isEmpty()) or something of that sort. Can anybody explain how I could go about doing this in NodeJS? Does the V8 JSON object have any functionality of this sort?
You can use either of these functions:
// This should work in node.js and other ES5 compliant implementations.
function isEmptyObject(obj) {
return !Object.keys(obj).length;
}
// This should work both there and elsewhere.
function isEmptyObject(obj) {
for (var key in obj) {
if (Object.prototype.hasOwnProperty.call(obj, key)) {
return false;
}
}
return true;
}
Example usage:
if (isEmptyObject(query)) {
// There are no queries.
} else {
// There is at least one query,
// or at least the query object is not empty.
}
You can use this:
var isEmpty = function(obj) {
return Object.keys(obj).length === 0;
}
or this:
function isEmpty(obj) {
return !Object.keys(obj).length > 0;
}
You can also use this:
function isEmpty(obj) {
for(var prop in obj) {
if(obj.hasOwnProperty(prop))
return false;
}
return true;
}
If using underscore or jQuery, you can use their isEmpty or isEmptyObject calls.
Object.keys(myObj).length === 0;
As there is need to just check if Object is empty it will be better to directly call a native method Object.keys(myObj).length which returns the array of keys by internally iterating with for..in loop.As Object.hasOwnProperty returns a boolean result based on the property present in an object which itself iterates with for..in loop and will have time complexity O(N2).
On the other hand calling a UDF which itself has above two implementations or other will work fine for small object but will block the code which will have severe impact on overall perormance if Object size is large unless nothing else is waiting in the event loop.
If you have compatibility with Object.keys, and node does have compatibility, you should use that for sure.
However, if you do not have compatibility, and for any reason using a loop function is out of the question - like me, I used the following solution:
JSON.stringify(obj) === '{}'
Consider this solution a 'last resort' use only if must.
See in the comments "there are many ways in which this solution is not ideal".
I had a last resort scenario, and it worked perfectly.
My solution:
let isEmpty = (val) => {
let typeOfVal = typeof val;
switch(typeOfVal){
case 'object':
return (val.length == 0) || !Object.keys(val).length;
break;
case 'string':
let str = val.trim();
return str == '' || str == undefined;
break;
case 'number':
return val == '';
break;
default:
return val == '' || val == undefined;
}
};
console.log(isEmpty([1,2,4,5])); // false
console.log(isEmpty({id: 1, name: "Trung",age: 29})); // false
console.log(isEmpty('TrunvNV')); // false
console.log(isEmpty(8)); // false
console.log(isEmpty('')); // true
console.log(isEmpty(' ')); // true
console.log(isEmpty([])); // true
console.log(isEmpty({})); // true
const isEmpty = (value) => (
value === undefined ||
value === null ||
(typeof value === 'object' && Object.keys(value).length === 0) ||
(typeof value === 'string' && value.trim().length === 0)
)
module.exports = isEmpty;
I want to search two item (name=string and location=json). this search is (one input box and two columns for search).
at the moment with this code I can find 'name' but i need I need to find location also.
if(textToCheck !== '') {
if((searchArray[i]['location']).toLowerCase().search(textToCheck) === -1) {
display = false;
}
}
the code that I suggest and doesn't work is:
if(textToCheck !== '') {
if((searchArray[i]['name']).toLowerCase().search(textToCheck) === -1 || (searchArray[i]['location']).toLowerCase().search(textToCheck) === -1) {
display = false;
}
}
error is :
Uncaught TypeError: Object 123 Street,xxx,xx,Canada,123rd Street,xxx,xx,123 xxx,12345 xxx,France has no method 'toLowerCase' FilterController.showFilteredSet (anonymous function)
As you said location=json, actually searchArray[i]['location'] is a object but not string. You need to do search depend on the what the object like.
Or simply change the object to string format like below:
JSON.stringify(searchArray[i]['location']).toLowerCase().search(textToCheck) === -1
JSON.stringify() is fine. But that searches in the object keys also.
This means:
if your "JSON" object looks like this:
({
street: 'my street',
country: 'Texas'
})
JSON.stringify(obj).toLowerCase().search('country') will find a result, even if the "data" doesn't contain it.
instead:
use a generalized way to do a flat search on objects.
Object.prototype.search = function(subject) {
for(var k in this) {
if(this.hasOwnProperty(k) && this[k].toString().toLowerCase().search(subject) !== -1)
return true;
}
return false;
};
var myObj = ({ foo: 'bar', hello: 'world' });
console.log(myObj.search('ar')); //search for "ar", returns true
console.log(myObj.search('ponyo!')); //search for "ponyo!", returns false
console.log(myObj.search('hello')); //search for "hello", returns false
in your case that would decline to:
//somewhere above, run this only once:
Object.prototype.search = function(subject) {
for(var k in this) {
if(this[k].toString().toLowerCase().search(subject) !== -1)
return true;
}
return false;
};
/////
if(textToCheck !== '') {
if((searchArray[i]['name']).toLowerCase().search(textToCheck) === -1 &&
(searchArray[i]['location']).search(textToCheck) === false) {
display = false;
}
}
please be warned that this code modifies the Object prototype, adding a "search" function to all objects (this might conflict with other libraries, you may or may not be using, that want to do the same).