ThingsBoard3.9.1自定义布局静态部件点击事件

        最近在整理thingsboard课程,基于最新thingsboard版本3.9.1/4.0,欢迎大家点赞,收藏、关注我,提问,在评论区留言,我争取把最新、最准、最好的课程,呈现在各位亦师亦友的csdn广大读者面前。

目录

自定义部件静态部件点击事件

1-自定义函数方式

2-静态部件动作触发方式


自定义部件静态部件点击事件

两种方式可以实现静态部件的点击事件触发动作。

静态部件不从设备、实体或其他数据源获取实时数据。这意味着它不会订阅任何遥测数据、属性更新或报警信息,这种设计使得静态部件加载速度快、资源消耗低。

静态部件在 ThingsBoard 中的典型工作流程:

1. 初始化阶段:onInit 函数
当小部件加载时,会调用self.onInit 方法,负责渲染HTML 内容并绑定事件。
HTML 渲染 :将用户提供的HTML 字符串插入到容器中。
CSS 注入 :动态生成 <style> 标签,防止样式冲突。
事件绑定 :为HTML 元素添加点击事件,触发预定义动作(如跳转、弹窗等)。
2. 生命周期管理
ThingsBoard 提供了多个生命周期钩子函数,静态部件也可以使用这些钩子来执行特定操作:
self.onInit():初始化内容。
self.onDestroy():清理资源(如移除全局变量、解绑事件监听器)。
self.onDataUpdated():虽然静态部件不使用数据更新,但该方法仍然存在,可留空或用于调试。
3. 交互支持
尽管是静态部件,但仍可通过JavaScript 实现基本的交互行为,比如点击事件、弹窗提示等。这通常通过在HTML中添加onclick属性,并绑定到window上的函数实现 。

1-自定义函数方式

新增加一个部件,名称htmlcode0609,如下:

选择"静态部件",如下:

静态部件的默认js代码如下:

// 初始化函数,当部件被创建或初始化时调用
self.onInit = function() {
    // 获取 AngularJS 的依赖注入器
    var $injector = self.ctx.$scope.$injector;
    // 通过服务映射获取 utils 服务
    var utils = $injector.get(self.ctx.servicesMap.get('utils'));
    
    // 创建 CSS 解析器实例
    var cssParser = new cssjs();
    cssParser.testMode = false;
    
    // 为部件生成唯一的命名空间,基于卡片 CSS 内容的哈希值
    var namespace = 'html-card-' + hashCode(self.ctx.settings.cardCss);
    cssParser.cssPreviewNamespace = namespace;
    
    // 创建样式元素并应用到部件
    cssParser.createStyleElement(namespace, self.ctx.settings.cardCss);
    self.ctx.$container.addClass(namespace);
    
    // 生成事件函数前缀,基于卡片 CSS、HTML 和部件 ID 的哈希值
    var evtFnPrefix = 'htmlCard_' + Math.abs(hashCode(self.ctx.settings.cardCss + self.ctx.settings.cardHtml + self.ctx.widget.id));
    
    // 构建卡片 HTML,添加点击事件处理
    cardHtml =  '<div style="height:100%" onclick="' + evtFnPrefix + '_onClickFn(event)">' +
                self.ctx.settings.cardHtml +
                '</div>';
    
    // 替换 HTML 中的自定义翻译标记
    cardHtml = replaceCustomTranslations(cardHtml);
    
    // 将生成的 HTML 设置到部件容器中
    self.ctx.$container.html(cardHtml);
    
    // 定义全局点击处理函数
    window[evtFnPrefix + '_onClickFn'] = function (event) {
        // 调用 ThingsBoard 的点击动作 API
        self.ctx.actionsApi.elementClick(event);
    }
 
    // 哈希生成函数
    function hashCode(str) {
        var hash = 0;
        var i, char;
        if (str.length === 0) return hash;
        for (i = 0; i < str.length; i++) {
            char = str.charCodeAt(i);
            hash = ((hash << 5) - hash) + char;
            hash = hash & hash; // 转换为 32 位整数
        }
        return hash;
    }
 
    // 替换自定义翻译标记的函数
    function replaceCustomTranslations (pattern) {
        // 匹配 {i18n:...} 格式的翻译标记
        var customTranslationRegex = new RegExp('{i18n:[^{}]+}', 'g');
        pattern = pattern.replace(customTranslationRegex, getTranslationText);
        return pattern;
    }
 
    // 获取翻译文本的函数
    function getTranslationText (variable) {
        // 使用 ThingsBoard 的 utils 服务进行翻译
        return utils.customTranslation(variable, variable);
    }
}

// 定义部件的动作源
self.actionSources = function() {
    return {
        'elementClick': {  // 元素点击动作
            name: 'widget-action.element-click',  // 动作名称
            multiple: true  // 是否允许多个动作
        }
    };
}
 
// 部件销毁时的清理函数
self.onDestroy = function() {
    // 当前为空,可以在这里添加清理逻辑
    // 例如移除全局事件处理函数等
}

代码解析说明:

访问部件设置:

通过self.ctx.settings访问部件配置,例如:self.ctx.settings.cardHtml获取HTML内容

DOM操作:

使用self.ctx.$container访问部件容器,例如:self.ctx.$container.html(content)设置HTML内容

样式处理:

推荐使用唯一命名空间避免样式冲突,可以使用类似示例中的cssjs库或直接创建style元素

事件处理:

定义动作源(actionSources)使部件可交互,通过self.ctx.actionsApi触发动作

点击“保存”按钮,

在widget_type表中,存储了这个部件的信息。

编辑部件,修改html部分和js部分,改为自定义部件,

在html和js代码中,实现点击事件处理,如下:

点击保存。

点击事件完成。点击clickme,触发alert告警对话框,点击HtmlButton,触发alert告警对话框。

如上增加的静态部件,可以在部件列表中可查询到,如下:

2-静态部件动作触发方式

再新增一个静态部件,名称html0601,如下:

配置静态部件的动作和行为,如下:

触发alert告警对话框,如下:

代码如下:

自定义部件背景颜色
在self.onInit = function() {}方法中,加入如下代码:
self.ctx.$container[0].style.backgroundColor = "#ff4500";

根据数据值变换部件背景颜色:
self.onDataUpdated = function() {
    
    function isNumber(n) {
        return !isNaN(parseFloat(n)) && isFinite(n);
    }

    if (self.ctx.valueCell && self.ctx.data.length > 0) {
        var cellData = self.ctx.data[0];
        if (cellData.data.length > 0) {
            var tvPair = cellData.data[cellData.data.length -
                1];
            var value = tvPair[1];
            var txtValue;
            if (isNumber(value)) {
                var decimals = self.ctx.decimals;
                var units = self.ctx.units;
                if (self.ctx.datasources.length > 0 && self.ctx.datasources[0].dataKeys.length > 0) {
                    dataKey = self.ctx.datasources[0].dataKeys[0];
                    if (dataKey.decimals || dataKey.decimals === 0) {
                        decimals = dataKey.decimals;
                    }
                    if (dataKey.units) {
                        units = dataKey.units;
                    }
                }

                // Change background color to red (v<0) or green (v>=0)
                self.ctx.$container[0].style.backgroundColor = value > 0 ? "#00ff00" : "#ff0000";
                
                txtValue = self.ctx.utils.formatValue(value, decimals, units, true);
            } else {
                txtValue = value;
            }
            self.ctx.valueCell.html(txtValue);
            var targetWidth;
            var minDelta;
            if (self.ctx.labelPosition === 'left') {
                targetWidth = self.ctx.datasourceContainer.width() - self.ctx.labelCell.width();
                minDelta = self.ctx.width/16 + self.ctx.padding;
            } else {
                targetWidth = self.ctx.datasourceContainer.width();
                minDelta = self.ctx.padding;
            }
            var delta = targetWidth - self.ctx.valueCell.textWidth();
            var fontSize = self.ctx.valueFontSize;
            if (targetWidth > minDelta) {
                while (delta < minDelta && fontSize > 6) {
                    fontSize--;
                    self.ctx.valueCell.css('font-size', fontSize+'px');
                    delta = targetWidth - self.ctx.valueCell.textWidth();
                }
            }
        }
    }    
    
};

结束。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值