diff --git a/ui-ngx/src/app/modules/home/components/rule-node/external/mqtt-config.component.html b/ui-ngx/src/app/modules/home/components/rule-node/external/mqtt-config.component.html
index 1fb41b4548..60adadd6bb 100644
--- a/ui-ngx/src/app/modules/home/components/rule-node/external/mqtt-config.component.html
+++ b/ui-ngx/src/app/modules/home/components/rule-node/external/mqtt-config.component.html
@@ -72,16 +72,7 @@
{{ 'rule-node-config.parse-to-plain-text' | translate }}
{{ "rule-node-config.parse-to-plain-text-hint" | translate }}
-
- device-profile.mqtt-protocol-version
-
- @for (version of mqttVersions; track version) {
-
- {{ mqttVersionTranslation.get(version) }}
-
- }
-
-
+
{{ 'rule-node-config.clean-session' | translate }}
diff --git a/ui-ngx/src/app/modules/home/components/rule-node/external/mqtt-config.component.ts b/ui-ngx/src/app/modules/home/components/rule-node/external/mqtt-config.component.ts
index 3efeb3d61e..08c8e284a9 100644
--- a/ui-ngx/src/app/modules/home/components/rule-node/external/mqtt-config.component.ts
+++ b/ui-ngx/src/app/modules/home/components/rule-node/external/mqtt-config.component.ts
@@ -18,7 +18,6 @@ import { Component } from '@angular/core';
import { isNotEmptyStr } from '@core/public-api';
import { UntypedFormBuilder, UntypedFormGroup, Validators } from '@angular/forms';
import { RuleNodeConfiguration, RuleNodeConfigurationComponent } from '@shared/models/rule-node.models';
-import { MqttVersions, MqttVersionTranslation } from '@shared/models/device.models';
@Component({
selector: 'tb-external-node-mqtt-config',
@@ -29,9 +28,6 @@ export class MqttConfigComponent extends RuleNodeConfigurationComponent {
mqttConfigForm: UntypedFormGroup;
- mqttVersions = MqttVersions;
- mqttVersionTranslation = MqttVersionTranslation;
-
constructor(private fb: UntypedFormBuilder) {
super();
}
diff --git a/ui-ngx/src/app/shared/components/mqtt-version-select.component.html b/ui-ngx/src/app/shared/components/mqtt-version-select.component.html
new file mode 100644
index 0000000000..81029a3445
--- /dev/null
+++ b/ui-ngx/src/app/shared/components/mqtt-version-select.component.html
@@ -0,0 +1,30 @@
+
+
+ device-profile.mqtt-protocol-version
+
+ @for (version of mqttVersions; track version) {
+
+ {{ mqttVersionTranslation.get(version) }}
+
+ }
+
+
diff --git a/ui-ngx/src/app/shared/components/mqtt-version-select.component.ts b/ui-ngx/src/app/shared/components/mqtt-version-select.component.ts
new file mode 100644
index 0000000000..4003925e60
--- /dev/null
+++ b/ui-ngx/src/app/shared/components/mqtt-version-select.component.ts
@@ -0,0 +1,84 @@
+///
+/// Copyright © 2016-2025 The Thingsboard Authors
+///
+/// Licensed under the Apache License, Version 2.0 (the "License");
+/// you may not use this file except in compliance with the License.
+/// You may obtain a copy of the License at
+///
+/// http://www.apache.org/licenses/LICENSE-2.0
+///
+/// Unless required by applicable law or agreed to in writing, software
+/// distributed under the License is distributed on an "AS IS" BASIS,
+/// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+/// See the License for the specific language governing permissions and
+/// limitations under the License.
+///
+
+import { Component, forwardRef, Input } from '@angular/core';
+import { ControlValueAccessor, NG_VALUE_ACCESSOR } from '@angular/forms';
+import { coerceBooleanProperty } from '@angular/cdk/coercion';
+import { MqttVersion, MqttVersions, MqttVersionTranslation } from '@shared/models/device.models';
+import { SubscriptSizing, MatFormFieldAppearance } from '@angular/material/form-field';
+
+@Component({
+ selector: 'tb-mqtt-version-select',
+ templateUrl: './mqtt-version-select.component.html',
+ styleUrls: [],
+ providers: [{
+ provide: NG_VALUE_ACCESSOR,
+ useExisting: forwardRef(() => MqttVersionSelectComponent),
+ multi: true
+ }]
+})
+export class MqttVersionSelectComponent implements ControlValueAccessor {
+
+ @Input()
+ disabled: boolean;
+
+ @Input()
+ subscriptSizing: SubscriptSizing = 'dynamic';
+
+ @Input()
+ appearance: MatFormFieldAppearance = 'fill';
+
+ mqttVersions = MqttVersions;
+ mqttVersionTranslation = MqttVersionTranslation;
+ modelValue: MqttVersion;
+
+ private requiredValue: boolean;
+ get required(): boolean {
+ return this.requiredValue;
+ }
+ @Input()
+ set required(value: boolean) {
+ this.requiredValue = coerceBooleanProperty(value);
+ }
+
+ private propagateChange = (v: any) => { };
+
+ constructor() {
+ }
+
+ registerOnChange(fn: any): void {
+ this.propagateChange = fn;
+ }
+
+ registerOnTouched(fn: any): void {
+ }
+
+ setDisabledState(isDisabled: boolean): void {
+ this.disabled = isDisabled;
+ }
+
+ writeValue(value: MqttVersion | null): void {
+ this.modelValue = value;
+ }
+
+ mqttVersionChanged() {
+ this.updateView();
+ }
+
+ private updateView() {
+ this.propagateChange(this.modelValue);
+ }
+}
diff --git a/ui-ngx/src/app/shared/shared.module.ts b/ui-ngx/src/app/shared/shared.module.ts
index 8eec19379e..68786dca77 100644
--- a/ui-ngx/src/app/shared/shared.module.ts
+++ b/ui-ngx/src/app/shared/shared.module.ts
@@ -226,6 +226,7 @@ import { JsFuncModulesComponent } from '@shared/components/js-func-modules.compo
import { JsFuncModuleRowComponent } from '@shared/components/js-func-module-row.component';
import { EntityKeyAutocompleteComponent } from '@shared/components/entity/entity-key-autocomplete.component';
import { DurationLeftPipe } from '@shared/pipe/duration-left.pipe';
+import { MqttVersionSelectComponent } from '@shared/components/mqtt-version-select.component';
export function MarkedOptionsFactory(markedOptionsService: MarkedOptionsService) {
return markedOptionsService;
@@ -437,6 +438,7 @@ export function MarkedOptionsFactory(markedOptionsService: MarkedOptionsService)
HexInputComponent,
ScadaSymbolInputComponent,
EntityKeyAutocompleteComponent,
+ MqttVersionSelectComponent,
],
imports: [
CommonModule,
@@ -700,6 +702,7 @@ export function MarkedOptionsFactory(markedOptionsService: MarkedOptionsService)
WidgetButtonComponent,
ScadaSymbolInputComponent,
EntityKeyAutocompleteComponent,
+ MqttVersionSelectComponent,
]
})
export class SharedModule { }