Open knownasilya opened 7 years ago
@knownasilya what would the button do with the promise?
See modified example
I like that it is an addictive change.
Would it toggle the disabled
state?
Yes, it would do that.
I think https://github.com/machty/ember-concurrency can help with that
I think that's overkill for this. Here's a simple implementation I use:
import Ember from 'ember';
export default Ember.Component.extend({
tagName: 'button',
attributeBindings: ['type', 'disabled'],
type: 'submit',
disabled: false,
loading: false,
didReceiveAttrs() {
var promise = this.get('promise');
if (promise) {
this.handleAction(promise);
}
},
submit() {
var promise = this.get('action') ? this.get('action')() : this.get('promise');
this.handleAction(promise);
},
click() {
var promise = this.get('action') ? this.get('action')() : this.get('promise');
this.handleAction(promise);
},
handleAction(promise) {
if (promise && promise.then) {
this.setProperties({
loading: true,
disabled: true
});
promise.then(result => {
if (this.isDestroying || this.isDestroyed) {
return;
}
this.setProperties({
actionResult: result,
loading: false,
disabled: false
});
})
.catch(error => {
if (this.isDestroying || this.isDestroyed) {
return;
}
this.setProperties({
error: true,
disabled: false,
actionResult: error
});
});
} else {
if (this.isDestroying || this.isDestroyed) {
return;
}
this.setProperties({
loading: false,
errored: false,
actionResult: undefined
});
}
}
});
{{#if loading}}
{{yield to='inverse'}}
{{else}}
{{yield actionResult errored}}
{{/if}}
And usage:
{{#loading-button class='btn btn-default btn-block' action=(action 'search' hasResults)}}
Search
{{else}}
<i class="fa fa-circle-o-notch fa-pulse"></i> Looking..
{{/loading-button}}
I was more or less arguing that baking this into ember-paper is overkill when addons like ember-concurrency make it easy for the dev to mimic this behavior.
How would you use ember-concurrency with paper-button to get this effect?
Not the exact scenario you described but http://ember-concurrency.com/#/docs/examples/loading-ui is close
I had the same need that I resolved like this:
// loading-button/component.js
import Ember from 'ember';
export default Ember.Component.extend({
tagName: '', // no wrapper
didReceiveAttrs() {
this._super(...arguments);
this.set('promise', undefined);
},
actions: {
onClick() {
this.set('promise', this.attrs.onClick());
}
}
});
{{!-- loading-button/template.hbs --}}
{{#paper-button onClick=(action 'onClick') raised=raised warn=warn}}
{{#if promise}}
{{#if (is-pending promise)}}
{{loadingMessage}}
{{else if (is-fulfilled promise)}}
{{successMessage}}
{{else}}
Doh!
{{/if}}
{{else}}
{{paper-icon icon}} {{label}}
{{/if}}
{{/paper-button}}
{{loading-button
icon='add-box'
raised=true
label='Add stuff'
loadingMessage='Creating stuff...'
successMessage='Created stuff'
onClick=(route-action 'createStuff')
}}
is-pending
and is-fulfilled
are helpers from https://github.com/fivetanley/ember-promise-helpers
route-action
is a helper from https://github.com/dockyard/ember-route-action-helper
Would be nice if the paper-button could be async aware, that is accept a promise as a return value on the
onClick
action, mainly for the form usecase.Or if the form component handles the action, it could pass down the promise in the yields:
Where the form passed it down: