Problem
You want a button component that spins to show asynchronous action till completion. Eg- Save Button.
Solution
Write an Ember Component to change to loading state when action is taking place.
For example a button to save data could be as
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 |
var App = Ember.Application.create({}); App.ApplicationController = Ember.Controller.extend({ isLoading:false, buttonText:"Submit", actions:{ saveData:function(){ var self = this; //Do Asynchronous action here. Set "isLoading = false" after a timeout. Ember.run.later(function(){ self.set('isLoading', false); }, 1000); } } }); App.SpinButtonComponent = Ember.Component.extend({ classNames: ['button'], buttonText:"Save", actions:{ isLoading:false, showLoading:function(){ if(!this.get('isLoading')){ this.set('isLoading', true); this.sendAction('action'); } } } }); |
Discussion
I have dumbed down the sample code to only change text within the button. One may add a loading image inside the button or change the button to a div styled like a button. The component is in charge of setting isLoading = true and the base controller performing asynchronous action decides when the 'isLoading' becomes false again. For safety and sanity of the component, one can add a settimeout of however much time and then set 'isLoading' back to false so that the components comes to initial state no matter the result of the asynchronous call. But I would prefer it was properly handled in the parent controller. Also note that the component does not let multiple clicks get in the way of loading status.