Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to prevent double clicks with ember.js?

I'm trying to figure out the idiomatic way to prevent a button from being clicked multiple times.

Imagine I have a simple controller action like so ...

var FooController = Ember.ObjectController.extend({
  actions: {
    go: function() {
        console.log("done!");
    }
  }
});

and in my template I have a button defined like so ...

<button {{action go}}>Click Me Fast</button>

Does the action have an option to disable it immediately / making it so only once true event will be handled by the controller (until it's disabled for example)

Edit

I'm looking for a long term / multi use solution. One idea I'm thinking about is creating a special ember-component called "button-disable" that would allow me to create a custom button type that generally disables after a single click -but will still allow me to bubble up events to a parent controller. This feels a little heavier weight than I'd like so if another option exists, or if someone has created an addon for just this - let me know

like image 663
Toran Billups Avatar asked Nov 24 '14 19:11

Toran Billups


1 Answers

As a one-off, if you bind the disabled attribute on your button like so

<button {{action go}} {{bind-attr disabled=actionPerformed}}>

and then set up your controller like

var FooController = Ember.ObjectController.extend({
    actionPerformed: false,
    actions: {
      go: function() {
        this.set("actionPerformed", true);
        console.log("done!");
    }
  }
}); 

then the button will become disabled after you click it once

If you want a reusable component I'd borrow the spinner button from http://emberjs.com/guides/cookbook/helpers_and_components/spin_button_for_asynchronous_actions/ and tweak it as you need.

So your JS would be along the lines of

window.SpinEg = Ember.Application.create({});

SpinEg.ApplicationController = Ember.Controller.extend({
    isLoading:false,
  buttonText:"Submit",
    actions:{
        saveData:function(){
            var self = this;
            var saveTime = Ember.run.later(function(){
                self.set('isLoading', false);

            }, 1000);
        }
    }
});

SpinEg.SpinButtonComponent = Ember.Component.extend({
    classNames: ['button'],
  buttonText:"Save",
    isLoading:false,
    actions:{
        showLoading:function(){
            if(!this.get('isLoading')){
                this.set('isLoading', true);
                this.sendAction('action');
            }
        }
    }
});

The template for your component would be

<script type='text/x-handlebars' id='components/spin-button'>
    <button {{bind-attr id=id}} {{action 'showLoading'}}>
        {{#if isLoading}}
            <img src="http://i639.photobucket.com/albums/uu116/pksjce/spiffygif_18x18.gif"></img>
        {{else}}
            {{buttonText}}
        {{/if}}
    </button>
</script>

and you would then just include the following where you need the button to appear

<script type='text/x-handlebars' id='application'>
    {{spin-button id="forapplication" isLoading = isLoading buttonText=buttonText  action='saveData'}}
</script>
like image 181
Ruaidhrí Primrose Avatar answered Oct 06 '22 19:10

Ruaidhrí Primrose