How to write a custom event handler so that the message sent includes the event object? - event-handling

If writing a custom event handler, how do I write it so that the message sent includes the event object? Or, can I read the event object before sending the message?

If you need access to something on click, just add it to the Msg Type, and pass it in your view.
IE:
type Msg = ButtonClicked MyObject | ...
and in your view:
button [ onClick (ButtonClicked model.myObject) ] [ text "button text" ]

Related

Formio:- Custom Error Message when the submit button is pressed without filling the required fields

I would like to change the error message that is displayed in situations where we click the submit button, but some compulsory fields are empty. The message that I receive by default is "Please check the form and correct all errors before submitting the form". I want to use instead a custom message. Is there a way to achieve this ?
You can override the error message by adding to the options when creating a form:
var options = {
i18n: {
en: {
submitError: 'My custom submission error',
}
}
}
And then later you're probably doing a call to
Formio.createForm(Formio.createForm(document.getElementById(settings.id), formDefinitionUrl, options)
which is where the options object you need is found.
Here's a list of the strings you can override this way: https://github.com/formio/formio.js/blob/master/src/translations/en.js

Can't get changed property from attachPropertyChange

I would like to know which property in the JSON model has changed when modified by a view.
For a test I took OpenUI5 walkthrough example and added the following lines in the application controller
oProductModel.attachPropertyChange( function(oEvent){
console.log("event: ", oEvent);
}, this);
When I change a property in the text input, the function in the attachPropertyChange is called but oEvent object is empty as I print it in console.
I know I could connect to text input change event, but I would like to use attachPropertyChange in case there would be multiple views of the same model.
As far as I understood, you'd like to avoid using the change event of the Input control because there is no information about which property in the model has changed. However, you can still get all the relevant information within the change handler via:
oControl.getBinding(/*controlPropertyName*/).getPath() to get the name of the bound property, or
oControl.getBindingContext(/*modelName*/).getPath(/*suffix*/) to get the path of the bound context. The getPath here awaits an optional suffix that will be appended to the context path with a "/" in between.
Combine those two APIs to get an absolute path in case the property binding was relative. E.g.:
onInputChange: function (event) {
const inputControl = event.getSource();
const property = inputControl.getBinding("value").getPath(); // "myProperty"
const absolutePath = inputControl.getBindingContext(/*modelName*/).getPath(property) // "/0/myProperty"
// ...
},
You can use change event for all input field in UI, and write event handling method in the controller. You will get the property as well as value in the oEvent of the event handling method easily. I hope you understood.

Event parameter overwritten after another event?

In view:
<List selectionChange=".onSelectionChange">
In controller:
onSelectionChange: function (oEvent) {
console.log(oEvent.sId); // log 1, output "selectionChange"
MessageBox.warning(Utils.i18n("CHANGE_CONFIRM"), {
actions: [ Utils.i18n("LEAVE_BTN"), MessageBox.Action.CANCEL ],
onClose: function (sAction) {
console.log(oEvent.sId); // log 2, output "closed"
if (sAction === Utils.i18n("LEAVE_BTN")) {
this._showDetail(oEvent.getParameter("listItem") || oEvent.getSource(), oEvent.getSource().data("target"));
}
}.bind(this)
});
}
Hi, may I ask why oEvent changed when onClose is triggered? Why can't I store oEvent in my scope?
Event is a module that implements Poolable, meaning that Event has to implement init and reset which will then be leveraged by its corresponding ObjectPool instance ("oEventPool" internally) to reuse the existing Event instance for the next event.
The "next event", in our case, is the "close" event which was fired by the dialog. As you could already observe, oEvent suddenly doesn't have the ID "selectionChange" but "close". This is because the Event instance was reset and reused again. And since oEvent is just a reference (not a copy), and because JS applies Call by Object-Sharing, it's "changed".
The API Reference of ObjectPool explains what it's doing with the Event instance:
(ObjectPool) maintains a list of free objects of the given type. If sap.ui.base.ObjectPool.prototype.borrowObject is called, an existing free object is taken from the pool and the init method is called on this object.
When no longer needed, any borrowed object should be returned to the pool by calling #returnObject. At that point in time, the reset method is called on the object and the object is added to the list of free objects.
Currently, the (oEvent) object is considered "no longer needed" when its handler is called. So the object is already reset right after onSelectionChange, and initialized again right before onClose is triggered.
UI5 does this so that it doesn't have to create and destroy multiple Event instances to improve performance. This is a practice borrowed from the Object Pool Design Pattern (which is also often used in game development).
So, what does it mean for us as application developers? Just don't rely on the event object that is inside a closure. Instead, assign primitive values from the object to separate variables so that we can use them later. E.g.:
onSelectionChange: function(oEvent) {
const eventId = oEvent.getId(); // === "selectionChange"
MessageBox.warning(/*...*/, {
onClose: function() {
/* oEvent.getId() === suddenly "close" but
eventId === still "selectionChange" 👍 */
},
});
},

event callback argument is empty

I've got event listeners defined as <AgGridReact> properties and then also just added this to my onGridReady callback:
grid.api.addEventListener('sortChanged',
evt => {
console.log(evt);
debugger;
});
Either way, the evt object is empty (an empty object, not undefined). Is this expected behavior or am I doing something wrong? The documentation (https://www.ag-grid.com/javascript-grid-events/) doesn't say anything about what to expect.
What you have is fine, but all 3 of the "sort" events:
sortChanged
beforeSortChanged
afterSortChanged
are notification only events - no event object are passed into the event itself

Prototype | keyup Event.stopObserving() not working when handler is bound to class

Here's my beef: I'm observing the document for a keyup and then calling a handler. The handler is calling a function of a class and is bound to the class's context. When the function is called and my conditionals are met, it's supposed to stop observing the handler. But its not.
Created a class, this is the function I'm calling on page:
look_for: function(key_combo) {
this.keys_array = key_combo.split("+");
this.match_key_handler = this.match_keys.bind(this);
document.observe('keyup', this.match_key_handler);
},
This calls the document to observe keyup and calls this.match_keys(). As you can see, it's assigned to a handler because the function needs to be bound. Below is the match_keys functions:
match_keys: function() {
// matching the keys here, blah blah
if(this.keys_matched) {
document.stopObserving('keyup',this.match_key_handler);
}
}
However, when the conditional is met, it doesn't stop observing! If I stopObserving all keyups on the document, it will unregister this function but I want it to only unregister the match_key_handler.
StackOverflow, help me out! Below is another post thats similar. Followed what was on the page but still no dice.
Stop Observing Events with JS Prototype not working with .bind(this)