diff --git a/docs/de/nodes/widgets/ui-number-input.md b/docs/de/nodes/widgets/ui-number-input.md index cf939070f..88d315288 100644 --- a/docs/de/nodes/widgets/ui-number-input.md +++ b/docs/de/nodes/widgets/ui-number-input.md @@ -99,6 +99,18 @@ Fügt Ihrem Dashboard eine einzelne Zahleneingabezeile hinzu. +## Nachrichtenereignisse + +Sie können steuern, wann die Zahleneingabe Nachrichten sendet, indem Sie die folgenden Optionen im Knoteneditor unter "Nachricht senden bei:" konfigurieren: + +| Option | Beschreibung | +|--------|--------------| +| Bei Änderung | Sendet eine Nachricht, sobald sich der Wert im Eingabefeld ändert. | +| Fokus verlassen | Sendet eine Nachricht, wenn das Eingabefeld den Fokus verliert (Benutzer klickt weg). | +| Enter drücken | Sendet eine Nachricht, wenn der Benutzer die Enter-Taste drückt, während das Eingabefeld fokussiert ist. | + +Diese Optionen können unabhängig voneinander aktiviert oder deaktiviert werden, sodass Sie genau auswählen können, wann der Knoten Nachrichten senden soll. + ## Beispiel ![Beispiel von Zahleneingabetypen](/images/node-examples/ui-number-input.png "Beispiel von Zahleneingabetypen"){data-zoomable} diff --git a/docs/en/nodes/widgets/ui-number-input.md b/docs/en/nodes/widgets/ui-number-input.md index bf112cf4b..bb0f420b8 100644 --- a/docs/en/nodes/widgets/ui-number-input.md +++ b/docs/en/nodes/widgets/ui-number-input.md @@ -99,6 +99,18 @@ Adds a single number input row to your dashboard. +## Message Events + +You can control when the number input emits messages by configuring the following options in the node editor under "Send message on:": + +| Option | Description | +|--------|-------------| +| On Change | Sends a message each time the value changes in the input field. | +| Focus Leave | Sends a message when the input field loses focus (user clicks away). | +| Press Enter | Sends a message when the user presses the Enter key while the input is focused. | + +These options can be enabled or disabled independently, allowing you to choose exactly when the node should emit messages. + ## Example ![Example of Number Inputs Types](/images/node-examples/ui-number-input.png "Example of Number Inputs Types"){data-zoomable} diff --git a/nodes/config/ui_base.js b/nodes/config/ui_base.js index 028125d68..aeae52702 100644 --- a/nodes/config/ui_base.js +++ b/nodes/config/ui_base.js @@ -658,9 +658,10 @@ module.exports = function (RED) { * @param {Socket} conn - socket.io socket connecting to the server * @param {String} id - widget id sending the action * @param {*} value - The value to send to node-red. Typically this is the payload + * @param {String} event - The event type (onChange, focusLeave, pressEnter) * @returns void */ - async function onChange (conn, id, value) { + async function onChange (conn, id, value, event) { // console.log('conn:' + conn.id, 'on:widget-change:' + id, value) // get widget node and configuration @@ -684,13 +685,18 @@ module.exports = function (RED) { msg = addConnectionCredentials(RED, msg, conn, n) - async function defaultHandler (msg, value, conn, id) { + async function defaultHandler (msg, value, conn, id, event) { if (typeof (value) === 'object' && value !== null && hasProperty(value, 'payload')) { msg.payload = value.payload } else { msg.payload = value } + // Add event field if provided + if (event) { + msg.event = event + } + msg = await appendTopic(RED, widgetConfig, wNode, msg) if (widgetEvents?.beforeSend) { @@ -707,7 +713,7 @@ module.exports = function (RED) { // Most of the time, we can just use this default handler, // but sometimes a node needs to do something specific (e.g. ui-switch) const handler = typeof (widgetEvents.onChange) === 'function' ? widgetEvents.onChange : defaultHandler - await handler(msg, value, conn, id) + await handler(msg, value, conn, id, event) } catch (error) { console.log(error) let errorHandler = typeof (widgetEvents.onError) === 'function' ? widgetEvents.onError : null diff --git a/nodes/widgets/locales/de/ui_number_input.json b/nodes/widgets/locales/de/ui_number_input.json index 8f166c212..98d96e612 100644 --- a/nodes/widgets/locales/de/ui_number_input.json +++ b/nodes/widgets/locales/de/ui_number_input.json @@ -15,6 +15,7 @@ "passThrough": "Wenn msg am Eingang ankommt, an den Ausgang weiterleiten:", "clearable": "Zahleneingabe mit Schaltfläche löschen", "sendMessageOn": "Nachricht senden bei:", + "onChange": "Bei Änderung", "focusLeave": "Fokus verlassen", "pressEnter": "Enter drücken", "whenChanged": "Bei Änderung senden:", diff --git a/nodes/widgets/locales/en-US/ui_number_input.json b/nodes/widgets/locales/en-US/ui_number_input.json index 6d325f5a3..5000e8bad 100644 --- a/nodes/widgets/locales/en-US/ui_number_input.json +++ b/nodes/widgets/locales/en-US/ui_number_input.json @@ -15,6 +15,7 @@ "passThrough": "If msg arrives on input, pass through to output:", "clearable": "Clear number input with button", "sendMessageOn": "Send message on:", + "onChange": "On Change", "focusLeave": "Focus Leave", "pressEnter": "Press Enter", "whenChanged": "When changed, send:", diff --git a/nodes/widgets/ui_number_input.html b/nodes/widgets/ui_number_input.html index 9523b347b..c13b135fd 100644 --- a/nodes/widgets/ui_number_input.html +++ b/nodes/widgets/ui_number_input.html @@ -37,6 +37,7 @@ }, tooltip: { value: '' }, passthru: { value: true }, + sendOnChange: { value: true }, sendOnBlur: { value: true }, sendOnEnter: { value: true }, className: { value: '' }, @@ -101,6 +102,9 @@ if (this.sendOnClear === undefined) { $('#node-input-sendOnClear').prop('checked', false) } + if (this.sendOnChange === undefined) { + $('#node-input-sendOnChange').prop('checked', true) + } if (!this.iconPosition) { $('#node-input-iconPosition').val('left') @@ -217,6 +221,10 @@
+
+ + +
diff --git a/ui/src/widgets/ui-number-input/UINumberInput.vue b/ui/src/widgets/ui-number-input/UINumberInput.vue index c81170fd2..23ed2692d 100644 --- a/ui/src/widgets/ui-number-input/UINumberInput.vue +++ b/ui/src/widgets/ui-number-input/UINumberInput.vue @@ -150,7 +150,7 @@ export default { } else if (this.value > this.max) { this.value = this.max } - this.send() + this.send('onChange') this.previousValue = this.value } } @@ -175,26 +175,28 @@ export default { this.$dataTracker(this.id, null, null, this.onDynamicProperties, null) }, methods: { - send () { - this.$socket.emit('widget-change', this.id, this.value) + send (event) { + this.$socket.emit('widget-change', this.id, this.value, event) }, onChange () { - this.send() + if (this.props.sendOnChange) { + this.send('onChange') + } }, onBlur: function () { if (this.props.sendOnBlur) { // user has to click away (focus out / blur) they want it submitted - this.send() + this.send('focusLeave') } }, onEnter: function () { if (this.props.sendOnEnter) { // user has to press they want it submitted - this.send() + this.send('pressEnter') } }, onClear () { - this.send() + this.send('onChange') }, makeMdiIcon (icon) { return 'mdi-' + icon?.replace(/^mdi-/, '')