Events / Native vs Custom events

Sometimes you want an event to only be handled once and ignore all the subsequent events. For instance, when a user clicks the submit button on a form, you want it to handle the first click, but ignore the subsequent ones, because that could trigger the form to be submitted twice. Event locks are designed specifically for this purpose. Let's look at our previous example with FormButtonComponent:

 export class FormButtonComponent extends extend_as("FormButtonComponent").mix(Component).with() {
  constructor() {
    super();

    this.native_events = ["!submit.click", "!cancel.click"];
    this.event_lock    = ["submit.click"];

    this.event_handlers.addForEvent("click", {
      "self.submit" : (self,event) => {
        console.log("Button clicked");
        self.publishEvent('submit');
      },
      "self.cancel" : (self,event) => self.publishEvent('cancel')
    }); 
  }
}

Now if the user clicks this button twice, we'll only handle the first click and only one "Button clicked" message will be printed to the console. This however implies that all buttons behave the same way - that is, ignore all subsequent clicks. Perhaps that's not what you want. Perhaps what you really want is for forms to not be submitted twice. In this case, we could write the following code in the UserFormComponent:

 export class UserFormComponent extends extend_as("UserFormComponent").mix(Component).with() {
  constructor() {

    super();
    // This is moved here from FormButtonComponent
    this.event_lock = ["submitter.click"];

    this.event_handlers.addForRole("submitter", {
      "submit" : (self,event) => {
        console.log("Button clicked");
        self.publishEvent('submit');
      },
      cancel: (self,event) => console.log("Form submission cancelled")
    }); 
  }
}


And now you will be able to click buttons as many times as you want in other places, but if this button belongs to a form, the form will ignore all subsequent clicks (of course, we no longer need the event_lock_for statement in ButtonComponent). To once again enable the form to start handling click events you can remove the event from the event_locks list:

user_form.event_locks.remove('submitter.click');

You can also set event locks manually using either addEventLock() method or event_locks property directly. The difference is that the first one will additionally check whether the property for which the lock is being added is in the event_lock_for list - and if not, the lock won't be added. If you want to add the lock anyway, you can just use event_locks property and its .add method (because it's a Javascript Set object!). Let's see an example:

export class FormButtonComponent extends extend_as("FormButtonComponent").mix(Component).with() {
  constructor() {
    super();
    this.native_events = ["!submit.click", "!cancel.click"];
    this.event_lock    = ["submit.click"];
    ...
  }
}

var button = new FormButtonComponent();
button.addEventLock("click");        // <-- event lock for click added, button will not be clicked twice
button.addEventLock("mouseover");    // <-- lock NOT added, because "mouseover" is not in `event_lock_for`
button.event_locks.add("mouseover"); // <-- event lock for mouseover event added
button.event_locks.remove("button"); // <-- button can be clicked again!