Skip to content

Instantly share code, notes, and snippets.

@mblarsen
Last active August 8, 2016 14:41
Show Gist options
  • Star 1 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save mblarsen/b9cc9ae0086e8eb07c78f5745afc783f to your computer and use it in GitHub Desktop.
Save mblarsen/b9cc9ae0086e8eb07c78f5745afc783f to your computer and use it in GitHub Desktop.
Object predicates for ko.utils.arrayFirst and similar
// Override arrayFirst (but remain backward compatible)
ko.utils._arrayFirst = ko.utils.arrayFirst
ko.utils.arrayFirst = function (array, ...predicateParams) {
// In case used as regular arrayFirst
if (typeof predicateParams[0] === 'function') {
return ko.utils._arrayFirst(array, predicateParams[0])
}
// Otherwise wrap
return ko.utils._arrayFirst(array, ko.utils.objectPredicate(...predicateParams))
}
/*
* Returns a predicate function for use with ko.utils.arrayFirst
* and similar functions. When comparing the predicate object to
* the item it first unwraps the item value.
*
* Example usage:
*
* ko.utils.arrayFirst(users, objectPredicate({ id: 42 }))
*
* or:
*
* ko.utils.arrayFirst(users, objectPredicate('id', 42))
*
* When passing in a predicate object you can use multiple keys
* for comparison:
*
* ko.utils. arrayFirst(users, objectPredicate({ id: 42, email: 'trudy@example.com'}))
*
* the `strict` param is automatically shifted to where it makes sense:
*
* objectPredicate({ id: '42' }, true)
*
* @param {(string|Object)} predicate Can be either a key or a predicate object
* @param {mixed} value|strict=null Only used when {predicate} is a string
* @param {boolean} strict=false Compare using == or ===
*
* @return {function} Returns a matcher function
*/
ko.utils.objectPredicate = function (predicate, value = null, strict = false) {
if (typeof predicate === 'string') {
predicate = { [predicate]: value }
} else if (typeof predicate === 'object') {
// In case object syntax is used value becomes strict
strict = value !== null ? value : strict
} else {
throw Error('Invalid arguments')
}
return function (item) {
let allTrue = true
for (let key of Object.keys(predicate)) {
if (strict) {
allTrue = allTrue && predicate[key] === ko.unwrap(item[key])
} else {
allTrue = allTrue && predicate[key] == ko.unwrap(item[key])
}
if (!allTrue) break
}
return allTrue
}
}
@rasmusvhansen
Copy link

Couldn't the predicate checking function be written like:

return function (item) {
    return Object.keys(predicate).every(k => strict ? predicate[k] === ko.unwrap(item[k]) : predicate[k] == ko.unwrap(item[k]));
}

@mblarsen
Copy link
Author

mblarsen commented Aug 8, 2016

Much better 👍

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment