Create Custom Components
As described in the topic Component Architecture, each of the ThingWorx Navigate components is made up of two sub-components, the user interface sub-component and the business logic sub-component. The business logic sub-component is also made up of two parts, the Base Business Logic and the Business Logic Implementation, which we’ll refer to in this topic as the base component and the implementation respectively.
Out-of-the-box, each base component comes with one or more implementations. Each implementation is designed to show specific information in the user interface. To show different information, you can customize your component by creating a custom implementation. For example, out of the box the Item List base component comes with six implementations: Activity, Affected Items, Attachments, Drawings, Part Structure, and Tasks. You can also create a custom implementation of the Item List base component, such as Parts List.
Creating a custom implementation for a component involves extending an existing base component or an existing implementation and then overriding the necessary services. The sections below contain detailed steps and an example.
* 
The versioning scheme for all out-of-the-box entities is nav.<version number>. For example, the version for all out-of-the-box component configurations in 9.3 is nav.1. Do not use this versioning scheme when you create custom component configurations; it is for internal ThingWorx Navigate use only.
Create a Custom Implementation by Extending a Base Component 
Follow these steps to create a custom implementation from an existing base component:
1. Choose an existing base component to use as a starting point for your custom implementation. Find the base component in the following table and note its Thing Template and Project. You’ll need this information later.
Base Component
Thing Template
Project
Attributes
PTC.Nav.AttributesBusinessLogicThingTemplate
PTC.Nav.AttributesBusinessLogicProject
Item Identity
PTC.Nav.ItemIdentityBusinessLogicThingTemplate
PTC.Nav.ItemIdentityBusinessLogicProject
Item List
PTC.Nav.ItemListBusinessLogicThingTemplate
PTC.Nav.ItemListBusinessLogicProject
Progress
PTC.Nav.ProgressBusinessLogicThingTemplate
PTC.Nav.ProgressBusinessLogicProject
Tiles
PTC.Nav.TilesBusinessLogicThingTemplate
PTC.Nav.TilesBusinessLogicProject
2. Create a project for your custom implementation. Under Project Dependencies, enter the project noted in Step 1. Save the project.
3. Create a Thing Template for your custom implementation. Under Project, enter the project created in Step 2. Under Base Thing Template, enter the Thing Template noted in Step 1.
4. Create a Thing for your custom implementation. Under Project, enter the project created in Step 2. Under Base Thing Template, enter the Thing Template created in Step 3.
5. In the Thing you created, click on the Services tab. Then click pencil icon to override the GetImplementationConfigurationVersion service and set a version for your implementation. For the version value, use user.version as a scheme, where version can have multiple levels delimited by dots and user cannot be nav. Save the Thing.
6. Identify which services you need to override for your custom implementation. For more information on services for out-of-the-box components, find the topic for the component you are extending under Available Components, and see the Customization Services table.
7. In the Thing Template you created, click on the Services tab. Then click pencil icon to override the necessary services. It’s recommended that you override the GetConfigurations service before overriding other services.
In the code for the GetConfigurations service, set the version for implementationConfigurationVersion to match the version set for GetImplementationConfigurationVersion in Step 5. Skipping this step may cause compatibility issues in future releases of ThingWorx Navigate.
8. Override the remaining necessary services. When overriding a service that receives the configuration as a parameter, first call the Migrate service in your code and pass the base and implementation versions.
To determine the value to use for targetBaseVersion in the Migrate service, execute the service GetBaseConfigurationVersion on the Thing you created in Step 4. Do not call the GetBaseConfigurationVersion service code and return its value.
When setting targetImplementationVersion in the Migrate service, use the version you set earlier in Step 5.
See the topic Versioning and Migration for more information on calling the Migrate service.
* 
When overriding services, do not override services with the category PTC.Nav.Private.
9. Save the Thing Template. Now your custom implementation is ready to use. To use the implementation, create a mashup. Add the base component for the implementation to the mashup, and click Gear icon. In the Configuration Type drop-down menu, select the configuration that belongs to your custom implementation.
Create a Custom Implementation by Extending an Implementation 
Follow these steps to create a custom implementation from an existing implementation:
1. Choose an existing implementation to use as a starting point for your custom implementation.
If you’re using an out-of-the-box implementation, find it in the following table and note its Thing Template and Project, according to your version of ThingWorx Navigate. You’ll need this information later.
If you’re using a custom implementation, note its Thing Template and Project. You’ll need this information later.
Implementation
Thing Template
Project
Activity
PTC.Nav.ActivityBusinessLogicThingTemplate
PTC.Nav.ActivityBusinessLogicProject
Affected Items
PTC.Nav.AffectedItemsBusinessLogicThingTemplate
PTC.Nav.AttachmentsBusinessLogicProject
Attachments
PTC.Nav.AttachmentsBusinessLogicThingTemplate
PTC.Nav.AffectedItemsBusinessLogicProject
Attributes Generic
PTC.Nav.AttributesGenericBusinessLogicThingTemplate
PTC.Nav.AttributesGenericBusinessLogicProject
Document Identity
PTC.Nav.DocumentIdentityBusinessLogicThingTemplate
PTC.Nav.DocumentIdentityBusinessLogicProject
Drawings
PTC.Nav.DrawingsListBusinessLogicThingTemplate
PTC.Nav.DrawingsListBusinessLogicProject
Part Identity
PTC.Nav.PartIdentityBusinessLogicThingTemplate
PTC.Nav.PartIdentityBusinessLogicProject
Part Structure
PTC.Nav.PartStructureBusinessLogicThingTemplate
PTC.Nav.PartStructureBusinessLogicProject
Task Identity
PTC.Nav.TaskIdentityBusinessLogicThingTemplate
PTC.Nav.TaskIdentityBusinessLogicProject
Task Progress
PTC.Nav.TaskProgressBusinessLogicThingTemplate
PTC.Nav.TaskProgressBusinessLogicProject
Tasks
PTC.Nav.TaskListBusinessLogicThingTemplate
PTC.Nav.TaskListBusinessLogicProject
Tiles Generic
PTC.Nav.TilesGenericBusinessLogicThingTemplate
PTC.Nav.TilesGenericBusinessLogicProject
2. Create a project for your custom implementation. Under Project Dependencies, enter the project noted in Step 1. Save the project.
3. Create a Thing Template for your custom implementation. Under Project, enter the project created in Step 2. Under Base Thing Template, enter the Thing Template noted in Step 1.
4. Create a Thing for your custom implementation. Under Project, enter the project created in Step 2. Under Base Thing Template, enter the Thing Template created in Step 3.
5. In the Thing you created, click on the Services tab.
Click pencil icon to override GetBaseMigrationVersion with your version convention for the configuration. Do not use the 'nav.<version number>' scheme.
Click pencil icon to override GetImplementationConfigurationVersion with your version convention for the configuration. For the version value, use user.version as a scheme, where version can have multiple levels delimited by dots and user cannot be nav.
6. Save the Thing.
7. Identify which services you need to override for your custom implementation. For more information on services for out-of-the-box components, find the topic for the component you are extending under Available Components, and see the Customization Services table.
8. In the Thing Template you created, click on the Services tab. Then click pencil icon to override the necessary services. It’s recommended that you override the GetConfigurations service before overriding other services.
* 
When overriding the GetConfigurations service, changing the configuration structure from its out-of-the-box structure is not supported. Only change values for individual JSON properties. For more information, see the topic Examples of Changes to Configuration Properties.
In the configuration, make sure to set the value of the implementationConfigurationVersion property to be the same as the value returned by the GetImplementationConfigurationVersion service.
9. Override the remaining necessary services. When overriding a service that receives the configuration as a parameter, first call the Migrate service in your code and pass the base and implementation versions.
To determine the base version to pass to the Migrate service, execute the service GetBaseConfigurationVersion on the Thing you created in Step 4. Do not call the GetBaseConfigurationVersion service and return its value.
To determine the implementation version to pass to the Migrate service, execute the service GetImplementationConfigurationVersion on the Thing you created in Step 4. Do not call the GetImplementationConfigurationVersion service and return its value.
See the topic Versioning and Migration for more information on calling the Migrate service.
* 
When overriding services, do not override services with the category PTC.Nav.Private.
10. Save the Thing Template. Now your custom implementation is ready to use. To use the implementation, create a mashup. Add the base component for the implementation to the mashup, and click Gear icon. In the Configuration Type drop-down menu, select the configuration that belongs to your custom implementation.
Example: Create a Parts List Implementation 
The following example shows how to create a custom implementation called Parts List, which is an implementation of the Item List base component. Parts List receives a part as input and returns the first level of parts that it contains.
* 
The versioning in this example is correct for ThingWorx Navigate. If you’re working with an earlier version of Navigate, make sure to set the version values according to the steps in the previous sections.
1. In ThingWorx Composer, create a new project named Demo.PartsListProject. Enter PTC.Nav.ItemListBusinessLogicProject under Project Dependencies. Enter PTC.Nav.ItemListBusinessLogicProject under Project Dependencies.
2. Create a new Thing Template named Demo.PartsListBusinessLogicThingTemplate. Set the Project to Demo.PartsListProject and set the Base Thing Template to PTC.Nav.ItemListBusinessLogicThingTemplate.
3. Create a Thing named Demo.PartsListBusinessLogicThing. Set the Project to Demo.PartsListProject and set the Base Thing Template to Demo.PartsListBusinessLogicThingTemplate.
4. Click on the Services tab and find the GetImplementationConfigurationVersion service. Click to override the service and set the version. Use the user.version scheme, for example, set the value to 1.0.0 as follows:
result = "1.0.0";
Click Done. Then click Save to save the Thing.
5. Check the Customization Services table for the Item List and identify the services that need to be overridden on the Thing Template. For this custom implementation, we need to override three services:
GetConfigurations– This service returns the configurations available for the implementation. We’ll edit it to define the configuration for Parts List.
GetImplementationLabel– This service returns the name of the implementation as it appears in the Mashup Builder. We’ll set it to show the name Parts List Demo.
GetItems– This service receives the input and configuration as parameters and returns a JSON in CCO format with the data to display in the Item List user interface. We’ll set it to return the first level parts for a given part, as well as attributes for the first level parts.
6. Open the Demo.ItemListBusinessLogicThingTemplate Thing Template. Click on the Services tab.
7. Click to override theGetConfigurations service. Paste the following code into the service. This code includes one configuration for Parts List which is labelled as Parts List in both the Mashup Builder and in the ThingWorx Navigate user interface.
result = {
"partsList": {
"label": "Parts List",
"configuration": {
"selectionType": {
"selectedKey": "single"
},
"waitForInput": {
"value": true
},
"actionBarConfiguration": {
"value": {
"actionBarConfigurationJSON": {
"value": ""
}
}
},
"baseConfigurationVersion": {
"value": "nav.1"
},
"implementationConfigurationVersion": {
"value": "1.0.0"
},
"defaultSortFields": {
"selectedValues": {
"data": [{
"itemListsData": [{
"items": [{
"additionalData": {
"itemListDefaultSortFieldDefinition": {
"defaultSortDirection": {
"selectedKey": "asc"
}
}
},
"id": "Name"
}
],
"objectType": "PTC.ProdMgmt.Part"
}
],
"adapter": {
"instanceName": "windchill",
"thingName": "PTC.WCAdapter"
}
}
]
}
},
"attributes": {
"selectedValues": {
"data": [{
"itemListsData": [{
"items": [{
"id": "Name",
"ordinal": 1
}, {
"id": "State#Display",
"ordinal": 2
}, {
"id": "Version",
"ordinal": 3
}, {
"id": "Number",
"ordinal": 0
}, {
"id": "ID",
"ordinal": 4
}
],
"objectType": "PTC.ProdMgmt.Part"
}
],
"adapter": {
"instanceName": "windchill",
"thingName": "PTC.WCAdapter"
}
}
]
},
"inTailoring": false
},
"label": {
"value": "Parts List"
},
"showExportAction": {
"value": true
},
"enableSearch": {
"additionalData": {
"itemListSearchDefinition": {
"searchHintText": {
"value": "Find"
}
}
},
"value": true
},
"maxNumberOfRowsInGrid": {
"inTailoring": false,
"value": 50
}
}

}
};
Here’s another sample code for GetConfigurations which contains two configurations instead of one. The first configuration is the same configuration as in the code above. The second configuration is for a mini version of the Parts List. It only shows three attributes and a maximum of five rows. It’s labelled as Parts List mini in the Mashup Builder and Parts List in the ThingWorx Navigate user interface.
result = {
"partsList": {
"label": "Parts List",
"configuration": {
"selectionType": {
"selectedKey": "single"
},
"waitForInput": {
"value": true
},
"actionBarConfiguration": {
"value": {
"actionBarConfigurationJSON": {
"value": ""
}
}
},
"baseConfigurationVersion": {
"value": "nav.1"
},
"implementationConfigurationVersion": {
"value": "nav.1"
},
"defaultSortFields": {
"selectedValues": {
"data": [{
"itemListsData": [{
"items": [{
"additionalData": {
"itemListDefaultSortFieldDefinition": {
"defaultSortDirection": {
"selectedKey": "asc"
}
}
},
"id": "Name"
}
],
"objectType": "PTC.ProdMgmt.Part"
}
],
"adapter": {
"instanceName": "windchill",
"thingName": "PTC.WCAdapter"
}
}
]
}
},
"attributes": {
"selectedValues": {
"data": [{
"itemListsData": [{
"items": [{
"id": "Name",
"ordinal": 1
}, {
"id": "State#Display",
"ordinal": 2
}, {
"id": "Version",
"ordinal": 3
}, {
"id": "Number",
"ordinal": 0
}, {
"id": "ID",
"ordinal": 4
}
],
"objectType": "PTC.ProdMgmt.Part"
}
],
"adapter": {
"instanceName": "windchill",
"thingName": "PTC.WCAdapter"
}
}
]
},
"inTailoring": false
},
"label": {
"value": "Parts List"
},
"showExportAction": {
"value": true
},
"enableSearch": {
"additionalData": {
"itemListSearchDefinition": {
"searchHintText": {
"value": "Find"
}
}
},
"value": true
},
"maxNumberOfRowsInGrid": {
"inTailoring": false,
"value": 50
}
}

},
"partsListMini": {
"label": "Parts List mini",
"configuration": {
"selectionType": {
"selectedKey": "single"
},
"waitForInput": {
"value": true
},
"actionBarConfiguration": {
"value": {
"actionBarConfigurationJSON": {
"value": ""
}
}
},
"baseConfigurationVersion": {
"value": "nav.1"
},
"implementationConfigurationVersion": {
"value": "1.0.0"
},
"defaultSortFields": {
"selectedValues": {
"data": [{
"itemListsData": [{
"items": [{
"additionalData": {
"itemListDefaultSortFieldDefinition": {
"defaultSortDirection": {
"selectedKey": "asc"
}
}
},
"id": "Name"
}
],
"objectType": "PTC.ProdMgmt.Part"
}
],
"adapter": {
"instanceName": "windchill",
"thingName": "PTC.WCAdapter"
}
}
]
}
},
"attributes": {
"selectedValues": {
"data": [{
"itemListsData": [{
"items": [{
"id": "Name",
"ordinal": 1
}, {
"id": "Version",
"ordinal": 2
}, {
"id": "Number",
"ordinal": 0
}
],
"objectType": "PTC.ProdMgmt.Part"
}
],
"adapter": {
"instanceName": "windchill",
"thingName": "PTC.WCAdapter"
}
}
]
},
"inTailoring": false
},
"label": {
"value": "Parts List"
},
"showExportAction": {
"value": true
},
"enableSearch": {
"additionalData": {
"itemListSearchDefinition": {
"searchHintText": {
"value": "Find"
}
}
},
"value": true
},
"maxNumberOfRowsInGrid": {
"inTailoring": false,
"value": 5
}
}

}
};
Click Done after adding the code.
8. Override the GetImplementationLabel service. Set the implementation label using the following code:
result = "Parts List Demo";
Click Done.
9. The GetItems service will retrieve the first level parts from Windchill using the following process:
a. Convert the attributes portion of the configuration to CCO structure using the service ConvertAttributesToCCO, which we’ll create.
b. Pass the resulting JSON in CCO format to the GetRelatedItems service on the PTC.WCAdapter. This service retrieves the data as UsageLink objects.
c. Convert the UsageLink objects to Part objects, using the ConvertUsageLinkToPart service, which we’ll create
Before overriding the GetItems service, it’s necessary to create the services ConvertAttributesToCCO and ConvertUsageLinkToPart.
10. Create a new service and name it ConvertAttributesToCCO. Under Inputs add the following inputs:
configuration, which has the Base Type of JSON
attributesPrefix, which has the Base Type of STRING
replaceObjectType, which has the Base Type of STRING
Under Output, select JSON from the drop-down menu.
11. Paste the following code into the ConvertAttributesToCCO service:
let attributesData = configuration.attributes.selectedValues;
attributesPrefix = attributesPrefix || "";
let objectType = replaceObjectType || attributesData.data[0].itemListsData[0].objectType;
attributesData.data[0].itemListsData[0].objectType = objectType;
let items = attributesData.data[0].itemListsData[0].items;
let newItems = [];
let newObj = {};
let hasID = false;

//convert to CCO
for(var i = 0; i < items.length; i++) {
let item = items[i];
if (item.id === 'ID') {
hasID = true;
}
newObj[attributesPrefix + item.id] = {"value":""};
}
//add ID if needed
if (!hasID) {
newObj[attributesPrefix + 'ID'] = {"value":""};
}
newItems.push (newObj);
attributesData.data[0].itemListsData[0].items = newItems;

//create date
var dateValue = new Date();
var y = dateValue.getFullYear();
var mo = dateValue.getMonth()+1;
if(mo<10) {mo='0'+mo;}
var d = dateValue.getDate();
if(d<10) {d='0'+d;}
//create time
var h = dateValue.getHours();
if(h<10) {h='0'+h;}
var mi = dateValue.getMinutes();
if(mi<10) {mi='0'+mi;}
var s = dateValue.getSeconds();
if(s<10) {s='0'+s;}
var ms = dateValue.getMilliseconds();
if(ms<10) {ms='00'+ms;} else {if(ms>=10 && ms<100) {ms='0'+ms;}}
attributesData.timeStamp = y + "-" + mo + "-" + d + " " + h + ":" + mi + ":" + s + "." + ms;

attributesData.version = "";
attributesData.statusMessage = "OK";
attributesData.status = "200";

result = attributesData;
Click Done.
12. Create a new service and name it ConvertUsageLinkToPart. Under Inputs add the following inputs:
usageLinkCCO, which has the Base Type of JSON
Under Output, select JSON from the drop-down menu.
13. Paste the following code into the ConvertUsageLinkToPart service:
let itemListsData = usageLinkCCO.data[0].itemListsData[0];
let tempMetadata = itemListsData.metadata;
let items = itemListsData.items;

//convert metadata
delete tempMetadata.ID;
let newMetadata = {};
for (var key in tempMetadata) {
let newKey = key.replace(/^(Uses\|)/,"");
newMetadata[newKey] = tempMetadata[key];
}
newMetadata['id'] = newMetadata.ID;
itemListsData['metadata'] = newMetadata;

//convert Items
let newItems = [];
for (var i=0 ; i<items.length ; i++) {
let item = items[i];
let newItem = {};
for (key in item) {
let newKey = key.replace(/^(Uses\|)/,"");
newItem[newKey] = item[key];
}
newItem['id'] = newItem.ID;
newItems.push(newItem);
}
itemListsData['items'] = newItems;
itemListsData['objectType'] = 'PTC.ProdMgmt.Part';

//update CCO
let partsListCCO = usageLinkCCO;
partsListCCO.data[0].itemListsData = [itemListsData];

result = partsListCCO;
Click Done.
14. Click to override the GetItems service. Paste the following code into the GetItems service:
var migratedConfig = me.Migrate({
targetImplementationVersion: "nav.1" /* STRING */,
data: configuration /* JSON */,
migrationType: "Configuration" /* STRING */,
targetBaseVersion: "nav.1" /* STRING */
});

var attributesConfigurationCCO = me.ConvertAttributesToCCO({
configuration:migratedConfig /* JSON */,
attributesPrefix: "Uses|" /* STRING */,
replaceObjectType: "PTC.ProdMgmt.PartUse" /* STRING */
});

// result: JSON
var tempResult = Things["PTC.WCAdapter"].GetRelatedItems({
item: input /* JSON */,
relation: {path:"Uses"} /* JSON */,
attributes: attributesConfigurationCCO /* JSON */
});


var convertedResults = me.ConvertUsageLinkToPart({
usageLinkCCO:tempResult /* JSON */
});

var result = convertedResults;
Click Done. Then click Save to save the Thing Template.
Now the Parts List custom implementation and its configuration are created and ready for use in the Mashup Builder. To use the implementation, add the Item List base component to a mashup and click Gear icon. In the Configuration Type drop-down menu, select the Parts List configuration which is labelled Parts Lists Demo - Parts List.
If you’re using Parts List to create the mashup shown in the video below, here is some additional code:
Code used to configure the Attributes component:
{
"layout": {
"selectedKey": "horizontal",
"additionalData": {
"dimensionDefinition": {
"maxHeight": {
"value": 200,
"version": "1.0.0"
},
"maxWidth": {
"value": 200,
"version": "1.0.0"
}
}
},
"version": "1.0.0"
},
"attributes": {
"sets": [{
"data": {
"selectedValues": {
"data": [{
"itemListsData": [{
"items": [{
"id": "ModifiedBy",
"ordinal": 0
}, {
"id": "GatheringPart",
"ordinal": 1
}, {
"id": "Latest",
"ordinal": 2
}, {
"id": "FolderName",
"ordinal": 3
}
],
"objectType": "PTC.ProdMgmt.Part"
}
],
"adapter": {
"instanceName": "windchill",
"thingName": "PTC.WCAdapter"
}
}
]
}
},
"name": ""
}
],
"inTailoring": true,
"filteredValues": {
"data": [{
"itemListsData": [{
"objectType": ""
}
],
"adapter": {
"instanceName": "",
"thingName": ""
}
}
]
},
"version": "1.0.0"
}
}
Code used for the mashup’s input parameter. Make sure to add a valid part ID:
{
"version": "1.0.0",
"data": [{
"adapter": {
"thingName": "PTC.WCAdapter",
"instanceName": "windchill"
},
"itemListsData": [{
"objectType": "PTC.ProdMgmt.Part",
"items": [{
"id": {
"value": ""
}
}
]
}
]
}
]
}
Video Tutorial: Create a Parts List Implementation
The following two video tutorials show how to create and use the custom implementation Parts List. The first video shows how to create Parts List, following the steps in the example above. The second video shows how to use Parts List in a mashup. You can find all of the code used in the videos in the example above.
* 
Note that these tutorials were created in an earlier version of ThingWorx Navigate, and as a result, you may need to use different version values than those shown. Follow the versioning as shown in this topic to ensure that everything works properly.
Also, in the second tutorial, Item List is added to the mashup from the Mashups tab in the left dock, which is how it existed in earlier versions of Navigate. Starting in Navigate 9.4, the Item List is a widget, so to add an Item List, go to the Widgets tab instead.
To view a video in a larger window, click on the title in the player. This opens the video in YouTube in a new tab.
Was this helpful?