Easily removing tags/attributes from your custom symbol

Blog Post created by goliveira on Jul 20, 2018



This post is for everyone new to PI Vision Extensibility development and that want a simple way to delete some traces from a custom multiple data source symbol.

I'll explain briefly the essential parts and I'll also give the codes I've come to write (do not expect much from my JS skills) after taking a good look at standard symbols and Anna Perry's manual data entry.


Data Source list


To remove one tag/attribute one needs simply to take it out from scope.symbol.DataSources. This array contains all traces by their paths (strings):

If you look closely you will notice that the first part indicates whether it comes from a tag (pi) or an attribute (af), the second is the path, including IDs after question marks for tags:




Getting tags/attributes names from Data Source list


In order to be able to select and remove the unwanted traces you need to show strings on config panel that match respectives data sources.

You can just use orignal strings from DataSources which are not much user friendly or, instead, have another array with tag names and end of attribute's path (Element|Attribute). For the second I created an array at runtimeData to store traces' names:

scope.runtimeData.Traces = [];
function updateDataSourceList(){ // Maps Data Sources on runtimeData.Traces with Label (tag/attribute names) and Path (PI/AF, server, database, ID)
     if (scope.symbol.DataSources.length != scope.runtimeData.Traces.length) {
          var tracesS = [];
          scope.symbol.DataSources.forEach(function (item) {
                    item = item ? item.toString() : '';
                    var path = item;
                    item = item.substr(item.lastIndexOf('\\') + 1) || item;
                    item = item.substr(0, item.indexOf('?')) || item;
                    tracesS.push({ Label: item, Path: path });
          scope.runtimeData.Traces = tracesS;

This code goes inside symbolVis.prototype.init function.

Note that indexes from both Traces and DataSources match, but you need to call this function on dataUpdate() to ensure it.


Enabling trace removal from symbol configuration panel


With a presentable data source list (Traces) we can show it to users on configuration panel (...config.html).

<!-- Trace list -->
<div class="trend-config-trace-list" tabindex="0" style="padding: 4px">
     <div ng-repeat="trace in runtimeData.Traces"
               ng-init="runtimeData.selectedStream = 0"
               ng-click="runtimeData.selectedStream = $index"
               ng-style="runtimeData.Traces.length > 1 && runtimeData.selectedStream === $index && { 'background-color' : '#d5d5d5' }"

<!-- Remove trace button -->
<div class="c-button-default-container" style="padding: 4px 4px 0 4px; margin-top: 0; margin-bottom: 0" ng-if="runtimeData.Traces.length > 1">
     <button type="button" class="c-primary-button trend-config-trace-arrange-button"
          <span class="k-icon k-delete"></span>

This code will replicate trace configuration from standard trend as in this post's first image.

First part of the code prints the list from runtimeData.Traces while tracking trace selected (runtimeData.selectedStream).

Second part displays the button for removal whenever there are more than one data source on symbol. Also the removal is attached to a function on JS file that actively removes the selected data source, although traceConfig.deleteTrace (on symbol definition, def) is another reference:

var def = {
     /* definition example
     visObjectType: symbolVis,
     typeName: 'pieChartLabeled',
     displayName: 'Pie Chart Labeled',
     datasourceBehavior: PV.Extensibility.Enums.DatasourceBehaviors.Multiple,
     supportsCollections: true,
     configOptions: function (symbol) {
          return [{
               title: 'Format Pie Chart',
               mode: 'formatPieChartLabeled'
     traceConfig: {  
          deleteTrace: configDeleteTrace


Core code - Removing data sources


Last part! This code goes on function (PV):

function configDeleteTrace(scope) {
     var index = scope.runtimeData.selectedStream;
     var datasources = scope.symbol.DataSources;
     var traces = scope.runtimeData.Traces;

     if (datasources.length > 1) {
          datasources.splice(index, 1);
          traces.splice(index, 1);

It removes the selected data source from DataSources and Traces based on its index saved from configuration panel and forces new data in for your custom symbol.