Community Tip - Want the oppurtunity to discuss enhancements to PTC products? Join a working group! X
Dear community, I've added to Studio some custom widgets from here https://github.com/steveghee/OCTO_Studio_extensions .
In particular, I find very interesting the 3D-List
We configured a Thing in hingworx to send to this widget the list of models that are saved in the server.
i can then load a specific model on fly.
My issue is that I want to also change the path where I look for different models. To do this there's a custom parameter to be filled.
What I can do is change this parameter during the experience, but the widget is loaded only at the start at the experience so it'll look only in the path defined when the experience is launched.
What I'm looking for is a way to reload the whole widget sending again the request to thingworx for new data.
I tried the "Reset" and "Refresh" services but it doesn't seem to work
Solved! Go to Solution.
to point 2.)
the usage is according to picture:
path parameter is linked to app parameter CustomListPath - when we change it then we will change the path service parameter.
We need also to call the service e.g. here getDataForHololensList. The one possible way is to click on button where the click event is linked do the service (explicit call)
or we can use the select event (implicit call) because the 3DList is linked to all Items - the results of the service getDataForHololensList(). and in the configuration of this service we will set that it should be called on entity change-
I think the mechanism is that both settings will update the service with the current path when we click on Item in the 3dlist /item selection in the 3D list.
Hi @AndreaT ,
possibly you can clarify this points of your quesiton
We configured a Thing in hingworx to send to this widget the list of models that are saved in the server.
i can then load a specific model on fly.
For me is unfortunately not clear how was this (above) implemented. So the question is about the OCTO 3D List widget which has properties relevant for DATA : "Data" and "Display Field"
Are these properties pointing to models paths? Could you please, clarify or possibly provide more details about the values of these properties.
My issue is that I want to also change the path where I look for different models.
Is the list containing the path to Thingworx CAD repositories?
Thanks
So according an update on load - think some widget will update when you load the view and not the project. So possibly you can try to navigate to dummy view and then reload again the View with the 3D List element e.g.
//======================= twxViewCtrl.goTest(); does not work any more
$scope.goTest=function() {
console.warn("goTest");
$scope.app.fn.navigate("TEST");
//or $scope.navigate()
$scope.$applyAsync();
};
$scope.$on('app-fn-navigate', function(evt, arg) {
console.log("app-fn-navigate :"+arg);
});
and then in the TEST.js view
//=======================
$scope.goHome=function() {
$scope.navigate('Home');
$scope.$applyAsync();
console.warn("goHome"); };
$scope.$on('app-fn-navigate', function(evt, arg) {
console.log("app-fn-navigate :"+arg);
});
////// go back to home
$timeout($scope.goHome,600);
I did test this construct for other widgets and was working but not sure if this will work in your case for the 3DList Octo extensions
Hi @RolandRaytchev and thanks for the suggestion.
The view change method, althought, doesn't seem to work.
I'll answer your questions:
1- In the Data field, as you can see in the associations picture, I get the data from the twx service.
Basically a list of model paths is passed to the 3d-list and in the view I see as many buttons as list items (cad models saved in twx in that path),
Display field isn't used.
2- In thingworx we loaded some models into a specific path.
So what happens when I click on an element of the list is that it calls the model and loads that model and I can keep changing 3D models just by selecting each one from that list widget.
All the associations in the experience
This is the code in the Thing created in thingworx. Once the request is sent to the Service "SIT.VuforiaHelper.thing" I ask for the data
var params = {
infoTableName : "InfoTable",
dataShapeName : "SIT_HololensList.dataShape"
};
// CreateInfoTableFromDataShape(infoTableName:STRING("InfoTable"), dataShapeName:STRING):INFOTABLE(SIT_HololensList.dataShape)
var result = Resources["InfoTableFunctions"].CreateInfoTableFromDataShape(params);
//
//result.AddRow({src: "/Thingworx/MediaEntities/SIT.testImage.media", ID: "id", Name: "Name", Number: 0, srcnotpressed: "/Thingworx/MediaEntities/SIT.imagetest2.media", text: "text", value: "value", view: "Manut001"});
//result.AddRow({src: "/Thingworx/MediaEntities/SIT.imagetest2.media", ID: "id1", Name: "Name1", view: "Manut001"});
//result.AddRow({src: "src2", ID: "id2", Name: "Name2", view: "Manut002"});
//
//
var repositoryName = "SystemRepository";
try{
// result: INFOTABLE dataShape: "FileSystemFile"
var files = Things[repositoryName].GetFileListing({
path: "/SIT" + folderName /* STRING */,
nameMask: undefined /* STRING */
});
var order = 0;
var tableLength = files.rows.length;
for (var x = 0; x < tableLength; x++) {
var row = files.rows[x];
result.AddRow({src: "/Thingworx/MediaEntities/SIT.testImage.media3",
ID: order++,
Name: row.name,
Number: 0,
srcnotpressed: "/Thingworx/MediaEntities/SIT.imagetest2.media",
text: "text",
value: "/Thingworx/FileRepositories/" + repositoryName + row.path,
view: "Manut001"});
}
}catch(err){
logger.error(err);
var newEntry = {
text: undefined, // STRING
ID: 0, // STRING [Primary Key]
Name: "ERROR in TW: " + err // STRING
};
result.AddRow(newEntry);
}
I also created an App parameter because at the time I didn't know how to change directly the variable "folderName" so I used this workaround to change the "customPath" value that then changes "folderName" value and also is displayed in a label.
Does this makes it a bit more clear?
Thank you very much
Hi @AndreaT ,
thanks for the feedback and the clarification. So far I understand here your usage is of service "getDataForHoloLensList" which returns a InfoTable with dataList containing some folders/paths of the Systemrepository- and this returned InfoTable which should update the 3DList when you use different folder parameters . Right?
So the problem in your case is that with this service ( according to the shown bindings in the provided picture) will fill the list only on starttime of the project when the project is loaded and the display will not update any more the Octo 3Dlist widget when we call the service later? Right?
Is this problem specific for the usage of 3Dlist element only - means the data is updated properly but the 3Dlist does not update the display or is in this case the problem with the returned data - means the data is not changed? This could be checked - if the returned data will update when the data is printed to the console log or to default 3d label (not part of the OCTO) - (e.g. with filter which will stringily it e.g. "return JSON.stringify(value); " or "return JSON.stringify(value.rows[0]" etc.
Thanks
Thank you so much @RolandRaytchev for helping me on this!
Following your questions and starting to write answers I've done plenty of tests to give you the best answers I could and, as a result, I went again into trying all different settings and I ened up here:
Actually with the auto-refresh setting ON and with those 5 seconds it "magically" works! But I wouldn't like to set it to 1s, I'm just worried about "continued exchange of data to keep it updated".
And now the big question is, do you think we can call the refresh just after I click on a button to change the path?
How can I understand which is the right line of code?
For example if I write console.log("full path test: " + $scope.app.mdl['SIT.VuforiaHelper.thing'].svc['getDataForHololensList'].folderName); I always get undefined in the log.
I suspect I must add something like param['folderName'] because it's under parameters, but how can I know the correct one? Like for services I've seen in the associations they're called only svc['..something..'].
Might it be possible in your opinion to use the same logic to refresh the widget just when we choose?
@RolandRaytchev I must add a correction. Unfortunately I can't edit my post anymore.
There's a setback with the auto refresh of the widget. Yes it updates the list but:
- it loads 3D models only after switching the path once
- it also reloads one of the 3D models of the newly reloaded list
- when I have the path with the 3 models, I click the first in the list but when it's time for the refresh the last model is loaded, even if it's the same list
I've tried that "Invoke on entity change" but I don't understand what it does.
So it got confusing, it seemed to be the solution but not anymore
Many thanks
Hi @AndreaT ,
so far I see on the current status - issue is in Preview mode so tested the problem in Studio with HoloLens project but only in preview mode.
So I did not use the system repository but a FileRepository "CADRepository1_test" with 2 folders /cad and /pvz where I did load different pvz files.
In the repository I defined the same service - a little modified "getDataForHololensList" with paramater path (instead of folder)
var params = {
infoTableName : "InfoTable",
dataShapeName : "HoloLens3DTestList"
};
var result = Resources["InfoTableFunctions"].CreateInfoTableFromDataShape(params);
//
var repositoryName = "CADRepository1_test";
try{
// result: INFOTABLE dataShape: "FileSystemFile"
var files = Things[repositoryName].GetFileListing({
//path: "/SIT" + folderName /* STRING */,
path: path,
nameMask: undefined /* STRING */
});
var order = 0;
var tableLength = files.rows.length;
for (var x = 0; x < tableLength; x++) {
var row = files.rows[x];
// let myVal= "https://pp-2209201219uz.portal.ptc.io/Thingworx/FileRepositories/" + repositoryName + row.path
let myVal= "/Thingworx/FileRepositories/" + repositoryName + row.path
result.AddRow({src: myVal,
ID: order++,
Name: row.name,
Number: 0,
srcnotpressed: myVal,
text: "text",
value: "/Thingworx/FileRepositories/" + repositoryName + row.path,
//valueLink: myVal,
valueLink: myVal,
view: "CAD-PVZ"});
}
}catch(err){
logger.error(err);
var newEntry = {
text: undefined, // STRING
ID: 0, // STRING [Primary Key]
Name: "ERROR in TW: " + err // STRING
};
result.AddRow(newEntry);
}
but for the principle of work it should be the same. So the result returned by the service is an infotable :
So means in this case we have 2 option as path arg input /cad or /pvz and using them we will return different list of pvz's files
So now tested in Studio and 3d list /OCTO. I never used this widget before therefore I did test only the related functionality and the display is not 100% ok.
So here the data of the 3D List has a binding to the service "getDataForHololensList" . The update button will restart the server which cause that 3Dlist updates. There is also a modelwidget where the src received the value of app.mdl['CADRepository1_test'].svc['getDataForHololensList'].data.current['value']
the effect is that when we select a listelement it will set the model widget resource property
We can see that then the model in the list are also updated on run time. I did not use auto refresh - but refreshed with the click event of the button
Attached the test project but to be used for testing you need to adapt the TWX -> create a file repository with the specified name and folder . Also loading some pvz to the folders etc.
Thanks @RolandRaytchev !
I still have to test this out but let me ask you a question. The FileRepository you mention is something that I have to setup in Thingworx? Is this related to the same repository that should be setup in order to use the Advanced target feature?
Because in that case it's not ready in my system, and in the other case I wouldn't know how to setup a FileRepository by myself, I'm a complete newbie to Twx.
Thank you 😁
Hi @AndreaT ,
the file repository is TWX standard functionality and it is a thing which is created using the template FileRepository. From the FileRepository template it inherit services allowing to upload , to list or download data (e.g. pvz files ) to this Thing into specified directories
So using the SaveBinary, SaveJSON etc. filerepository services you can save data to a specific folder in this repository but you can also use the FileUpload widget to upload the files to the file repository manually (in a TWX mashup)
Hi @RolandRaytchev I'm almost there 😁
I've so poor knowledge of TWX for now.
I've created and edited everything, I have two more questions and then, hopefully it'll be done.
question 1: what is that valueLink you created? I don't see it in my list but I see it in your screenshot and project (mine below)
Question 2: when I change the path and click on "update" the list updates but it seems that the lack of the valueLink won't let me click and load the 3d files uploaded, because it only loads one at the beginning. Instead, the labels show the path of the model when I click on the elements of the list
Hi @AndreaT ,
to question 1.) the method was defined in TWX as:
var params = {
infoTableName : "InfoTable",
dataShapeName : "HoloLens3DTestList"
};
// CreateInfoTableFromDataShape(infoTableName:STRING("InfoTable"), dataShapeName:STRING):INFOTABLE(SIT_HololensList.dataShape)
var result = Resources["InfoTableFunctions"].CreateInfoTableFromDataShape(params);
//
var repositoryName = "CADRepository1_test";
try{
// result: INFOTABLE dataShape: "FileSystemFile"
var files = Things[repositoryName].GetFileListing({
//path: "/SIT" + folderName /* STRING */,
path: path,
nameMask: undefined /* STRING */
});
var order = 0;
var tableLength = files.rows.length;
for (var x = 0; x < tableLength; x++) {
var row = files.rows[x];
let myVal= "/Thingworx/FileRepositories/" + repositoryName + row.path
result.AddRow({src: myVal,
ID: order++,
Name: row.name,
Number: 0,
srcnotpressed: myVal,
text: "text",
value: "/Thingworx/FileRepositories/" + repositoryName + row.path,
//valueLink: myVal,
valueLink: myVal,
view: "CAD-PVZ"});
}
}catch(err){
logger.error(err);
var newEntry = {
text: undefined, // STRING
ID: 0, // STRING [Primary Key]
Name: "ERROR in TW: " + err // STRING
};
result.AddRow(newEntry);
}
It returns an InfoTable with specific dataShape:
means is an info table containing many rows for specific folder path. The current value is is the row currently selected in the List widget. The row itself contains different fields and one of them is the valueLink field property which contains a link to the file in the repository
to point 2.)
the usage is according to picture:
path parameter is linked to app parameter CustomListPath - when we change it then we will change the path service parameter.
We need also to call the service e.g. here getDataForHololensList. The one possible way is to click on button where the click event is linked do the service (explicit call)
or we can use the select event (implicit call) because the 3DList is linked to all Items - the results of the service getDataForHololensList(). and in the configuration of this service we will set that it should be called on entity change-
I think the mechanism is that both settings will update the service with the current path when we click on Item in the 3dlist /item selection in the 3D list.
Amazing @RolandRaytchev it works for me too now 😁
Even though I could accept the solution, you did helped me A LOT, have you tried to play with the button's aspect?
I mean it'd be nice to add the CAD name and remove that "missing picture" image.
In my old version I had both picture and name working but now they don't. The cad name would be just perfect.
Any clue?