ember-truth-helpers
ember-truth-helpers copied to clipboard
Does not handle aysnc conditions
We recently had a scenario where we were using the and
helper like this:
{{#if (and (is-permitted 'deleteFile') showDelete)}}
<button>Delete</button>
{{/if}}
The is-permitted
helper returned a DS.PromiseObject
, which is handled correctly by the if
component.
The and
helper evaluates this code with the DS.PromiseObject
if (truthConvert(params[i]) === false) {
return params[i];
}
The truthConvert(<DS.PromiseObject>)
=== false, so the condition passes and returns the Promise object to the if
component. When the promise evaluates to true, the Delete button is shown, regardless of the value for showDelete
- that param is never evaluated by the truth helper.
I started to mock up a replacement, before I found that ember-promise-helpers
could be used.
{{#if (and (await (is-permitted 'deleteFile')) showDelete)}}
<button>Delete</button>
{{/if}}
So... I wonder if it's worth updating the docs to cover this scenario?
If you are interested, the code for the async and
helper is below:
import { helper } from '@ember/component/helper'
import RSVP from 'rsvp'
import DS from 'ember-data'
export function asyncAnd (params) {
if (!params || !params.length) return DS.PromiseObject.create({promise: RSVP.resolve(true)})
// Need to wait for all params to be complete
const promises = params.map(param => {
if (typeof param.then === 'function') return param
return RSVP.resolve(param)
})
// Look to see if any of the results returned a 'false'. If they did, then the whole check fails
const result = RSVP.all(promises)
.then(results => {
for (let i = 0; i < results.length; i++) {
if (!result) return result
}
return results[results.length - 1]
})
return DS.PromiseObject.create({promise: result})
}
export default helper(asyncAnd)
It's a bit crude, and might not actually work, but I think it gets the idea across.
FWIW, I think you can do something a bit simpler in the helper:
export default helper(function asyncAnd (params) {
let promise = RSVP.all(params)
.then(results => {
for (let i = 0; i < results.length; i++) {
if (!result) return result
}
return results[results.length - 1]
})
return DS.PromiseObject.create({promise: result})
})
Closing as stale. I see mentions of PromiseObject
which is not a recommended API nowaday.