Test multiple properties using _.every - angularjs

I was asked to change some code using lodash's _.every:
//for every item in collection, check if "someProp" is true,
//but only if "someProp2" isn't "-1". If "someProp" is true for
//every item in collection, return true.
$scope.areAllTrue = function() {
for(var i=0; i<$scope.collection.length; i++){
if($scope.collection[i].someProp2 === -1) {
continue;
}
if(!$scope.collection[i].someProp) {
return false;
}
}
return true;
};
So following the lodash example of:
_.every(users, 'active', false);
We get:
$scope.areAllTrue = function() {
return _.every($scope.collection, 'someProp', true)
};
This handles the "For every item in the collection, check if someProp is true, if all are true, return true." But can I do the "continue" check here somehow?
Edit: Can I use two predicates with "_.every" somehow? Like if someProp1 === true || someProp2 === -1 ?

_.every() can use a predicate function:
_.every(users, function(user) {
return user.someProp2 === -1 || user.someProp;
});
You can also skip lodash, and use Array.prototype.every:
users.every(function(user) {
return user.someProp2 === -1 || user.someProp;
});

Related

using lodash _find to return true or false

I'm trying to use lodash function to find if it satisfies the if statement. When the code has run the code which 'return false', it stills continue execute the _find function and did not return the result (boolean value) in the scope.onToggle.
$scope.onToggle = function(disposition) {
if (requiredFieldsEntered()===false){
// if return value from the function is false, alert user
}
}
function requiredFieldsEntered(){
var res = _.find($rootScope.CustomFields,
function(field){
if(field.enabled && field.required){
if(field.table_name === 'session'){
if(!$scope.session.external_id){
console.log(field.column_name);
return false;
}
else if (field.table_name === "session_extension"){
if(!$scope.session.extension|| ($scope.session.extension && !$scope.session.extension[field.column_name])){
console.log(field.column_name);
return false;
}
}
}
}});
if (res) return false;
else return true;
}
First let's stop and consider what _.find actually does. It loops over an array and returns the first element of the array that matches the condition.
_.find([1, 2, 3, 4], function(num) { return num % 2 === 0 });
// returns 2
In the case of your _.find function, then, you'll either get back one of the fields from $rootScope.CustomFields or undefined if none of the fields returns a truthy value from function(field)….
Here is where you have your problem. The anonymous function function(field)… only ever returns false. You need to return true if you find an error, or else return false otherwise.
Since your requiredFieldsEntered() function is ultimately trying to return either true or false, you can decide which of those to return based on whether or not your _.find function returns some object or undefined.
Something like this:
$scope.onToggle = function(disposition) {
if (requiredFieldsEntered()===false){
// if return value from the function is false, alert user
}
}
function requiredFieldsEntered(){
const fieldWithErrors = _.find($rootScope.CustomFields,
function(field){
let result = true;
if(field.enabled && field.required){
if(field.table_name === 'session'){
if(!$scope.session.external_id){
console.log(field.column_name);
result = false;
} else if (field.table_name === "session_extension"){
if(!$scope.session.extension|| ($scope.session.extension && !$scope.session.extension[field.column_name])){
console.log(field.column_name);
result = false;
}
}
}
}
return result;
});
if (fieldWithErrors) {
return false;
}
return true;
}
Quick note that a shorter but somewhat less-readable version at the end may replace this bit:
…
if (fieldWithErrors) {
return false;
}
return true;
}
With:
…
return !!!fieldWithErrors;
The first two exclamation points would be typecasting the result of your find function to either true if it comes up with something or false if it returns undefined, and then the third exclamation point would invert that boolean to match your current scheme of returning false if there are errors.
(Or you could change your function name to errorsArePresent and return true – !!fieldWithErrors).

equivalent of following code in angular 2

I'm having trouble updating this code from angularjs ad angular 2, thank you for any help
if (settings != null && settings.checkSubscriptionForVip === true) {
return this.user.hasVipAccess().then(function(hasVipAccess) {
hasVipAccess ? deferred.resolve() : deferred.reject("NO_VIP");
return;
});
} else {
deferred.resolve();
return;
}
You neeed to have a boolean variable defined in your component and assign the result in to that,
hasVipAccess : boolean = false;
if (settings != null && settings.checkSubscriptionForVip === true) {
this.user.hasVipAccess().then(function(access) {
this.hasVipAccess = access;
});
} else {
this.hasVipAccess = access;
}
However if you do not need to set boolean variable, just return the result

Multiple optional filters in angular

I am very new to angular and, I am not sure how to control the behavior of my filters.
In the app, I have two different single-select drop down controls that filter the results of my data set and fill a table. However, even though these filters work, the results are dependent of both controls and if both are not being used , the empty set is returned. So, my question is: How can I use these filters optionally? So, the app returns every result when the filters are not used or returns the filtered results by one of the controls or both?
Thank you
Here is the code:
AngularJS
The filters for each control. They look very similar:
.filter('byField', function () {
return function (results, options) {
var items = { options: options, out: [] };
angular.forEach(results, function (value, key) {
for (var i in this.options) {
if ((options[i].value === value.fieldId &&
options[i].name === "Field" &&
options[i].ticked === true)) {
this.out.push(value);
}
}
}, items);
return items.out;
};
})
.filter('byClass', function () {
return function (results, options) {
var items = { options: options, out: [] };
angular.forEach(results, function (value, key) {
for (var i in this.options) {
if ((options[i].value === value.documentClass &&
options[i].name === "Class" &&
options[i].ticked === true)) {
this.out.push(value);
}
}
}, items);
return items.out;
};
})
HTML
This is what I am doing to populate the rows of the table:
<tr ng-repeat="result in results | byField:outputFields | byClass:outputClasses">
<td>{{result.documentId}}</td>
...
</tr>
Dorado7.1 in all event listeners provides a view implicit variable pointing to the current event host's view, the variable can completely replace the use of this scenario.
Well, as I imagined the answer was more related to set theory than to angular.
I just made an union between the empty set and every result, and it worked.
.filter('byField', function () {
return function (results, options) {
var items = { options: options, out: [] };
angular.forEach(results, function (value, key) {
if (options.length) {
for (var i in this.options) {
if ((options[i].value === value.fieldId &&
options[i].name === "Field" &&
options[i].ticked === true)) {
this.out.push(value);
}
}
} else {
this.out = results.slice();
}
}, items);
return items.out;
};
})

Filter with multiple values

I have items which should have multiple (e.g. categories). Now I want to filter my items to these categories.
I think the task is not possible with the filter-directive without using a custom filter, right?
I came up with a solution, but it looks dirty and wrong to me:
$scope.filterList = function (item) {
var found = false;
var allFalse = true;
angular.forEach(item.attributes, function (value, key) {
if ($scope.activeAttributes[value.name] === true) {
found = true;
}
});
angular.forEach($scope.activeAttributes, function (value, key) {
if (value === true) {
allFalse = false;
}
});
$log.log("length: " + Object.keys($scope.activeAttributes).length);
if (found === true || Object.keys($scope.activeAttributes).length === 0 || allFalse === true) {
return true;
}
};
Demo JSFiddle of my code
I thought with Angular, that the code should be simple and most of the work should be done by Angular. What if I need to filter more attributes?

find updated field in object - scope.$watch - angularjs

If i do:
scope.$watch('obj', function(newObj, oldObj) {
//...
}, true);
How do I find the key-value pair in the object that changed?
.
Only to understand what I try to do:
I have an object of the form:
scope.actions = {
action1: false,
action2: false
}
When the boolean changes, I want to assign function calls to it. Something like, DO-action - UNDO-action.
So I watch it the following way:
scope.$watch('actions', function(newObj, oldObj) {
/*PSEUDO CODE START*/
IF (action1 changed && action1 true) {
do-func1();
}
IF (action1 changed && action1 false) {
undo-func1();
}
...
/*PSEUDO CODE END*/
}, true);
My problem here is, that if I check the values for their boolean, all the functions get called. So the point here is, how do I find the changed key-value pair in the object?
scope.$watch('actions', function(newActions, oldActions) {
for(var i in newActions) {
if(newActions.hasOwnProperty(i)) {
var newAction = newActions[i];
var oldAction = oldActions[i];
if(newAction !== oldAction) {
if(newAction === true) {
doActions[i](); // do-func-i();
} else if (newAction === false) {
undoActions[i](); // undo-func-i();
}
}
}
}
}, true);
doActions here is a conventional map of actions
doActions = {
action1 : function() {
console.log('action1');
},
action2 : function() {
console.log('action2');
}
}
doActions['action1'] will reference first function
You may have an array as well, but then you'll need to introduce an index to fetch proper function doActions[0]

Resources