How to access db data in a svf model? - autodesk-forge

I'm looking for a way to acces "property data" in a programmatic way in my svf model open in auto desk viewer.
https://autodeskviewer.com/viewers-dev/latest/docs/PropDbLoader.html
I found that in the api, but can figure out how it should be working and what data it needs.
The API documentation seems exhaustive but is not of any help on how to use those function...
I'm trying to make an extension, that when on click, i could access property of the model part that i clicked on.
( the same data that I can see in the property section of the basic viewer )
So far I have that:
MyAwesomeExtension.prototype.onSelectionEvent = function(event) {
//here i have an ID related to the part clicked
var currSelection = this.viewer.getSelection();
//here I acces what seems to be the data loader, which is defined
console.log(event.model.myData.propDbLoader );
//but here, when i give the first id, it respond null
event.model.myData.propDbLoader.getProperties( currSelection, (e)=>{
console.log('success',e );
},(e) => {
console.log('error',e );
} );
Any idea would be appreciated :)

There are several APIs to query the model data through Viewer:
Viewer.search:
viewer.search('keywords',dbids=>console.log(dbids),err=>console.error(err))
Viewer.getProperties
Viewer.getProperties(dbId,rst=>console.log(rst),err=>console.error(err))
Viewer.model.getBulkProperties:
Viewer.model.getBulkProperties(dbids,['propname1','prop2'],rst=>console.log(rst), err=>console.error(err))

Related

Get Property Name of Part that is Selected

I am currently making a web page that uses the forge viewer. How can I make a function that will return the value from the "Properties" tab inside the viewer. I need to be able to get the value of the 'name' property inside the viewer, when a part is selected by the user. Any help is much appreciated!
Cheers!
viewer.addEventListener(Autodesk.Viewing.SELECTION_CHANGED_EVENT, onSelectionChanged)
function onSelectionChanged(dbids){
console.log(dbids)
viewer.getProperties(dbIds, props => {
props.properties.forEach(prop => {
// any custom action with data?
//prop.displayName
//prop.displayValue
//prop.displayCategory
// etc
});
}
Blog: https://forge.autodesk.com/blog/property-inspector-viewer

How to get client side data from Kendo Grid to controller

I am trying to get Kendo Grid data which is hydrated from client side to a MVC controller method. My view contains several single fields like name, date of birth etc and tabular field which I hooked with a Kendo Grid. Since its a new operation I have no data in the grid ( and other fields) and user enters them from client side.
I have no idea how to proceed on this. Ideally I would like to get this data to a list in my viewmodal. So that when the user hits save, I have all other data and the grid data coming into a controller method.
I am able to successfully bind a list with kendo grid and display it. I have very little experience on JavaScript and Kendo and web programming.
If any of you can point me to the right direction, sample code would be greatly appreciated.
$("#departmet").kendoGrid({
dataSource: dataSource,
height: 250,
scrollable: true,
sortable: true,
filterable: true,
pageable: {
input: true,
numeric: false
},
columns: [
"DepartmentName",
"SubDivision"
]
});
From experience I know their documentation is not easy to navigate. It seems there is the documentation and then the API. The API is usually what you will always want to find. What you will need is the information from here https://docs.telerik.com/kendo-ui/api/javascript/ui/grid. If I understand the question correctly. There are several ways you can achieve posting. You could make use of editor templates. Click the Open in Dojo to get an idea how it looks.
https://docs.telerik.com/kendo-ui/api/javascript/ui/grid/configuration/editable.template
With this you do not have to worry about modifying the data via javascript. Assuming your grid is surrounded with a form element it will get posted when submitted. Note paging is not accounted for here. Also, this method by default can auto post after each edit. If you don't want this behavior then you will have to have advanced knowledge of the API.....Correction on that last statement. The API is different when dealing with the data all on the client side. Click the Open in Dojo to see it all on the client side. If you are not wanting to use editor templates and want to manage the data editing yourself then you need to use the grid methods provided.
Once you have your grid created. To access the data source of the grid you will need to get the dataSource.
$('#departmet').data('kendoGrid').dataSource;
https://docs.telerik.com/kendo-ui/api/javascript/data/datasource
If you need to use a different data source(or change it) you can use the setDataSource method below(grid function).
https://docs.telerik.com/kendo-ui/api/javascript/ui/grid/methods/setdatasource
To add to the data source use the add function to add a new object.
$('#departmet').data('kendoGrid').dataSource.add({ id: 2, name: 'name'});
https://docs.telerik.com/kendo-ui/api/javascript/data/datasource/methods/add
It is important with kendo to ALWAYS use the methods provided to change the data source so that the proper events can fire to update the UI accordingly. This includes if you need to set a property on a specific data item. In that case you need to use the set method on the item itself.
After you are done modifying your data. Within javascript get the data and either create DOM elements within a form
//JQuery sudo code example
var data = $("#departmet").data("kendoGrid").dataSource.data();
var dataLen = data.length;
var myForm = $('#my-form'); //Already within DOM
for (var i = 0; i < dataLen; i++) {
var item = data[i];
var idEl = $('<input type="hidden" name="userData[' + i + '].id" />');
idEl.val(item.id);
var nameEl = $('<input type="hidden" name="userData[' + i + '].name" />');
nameEl.val(item.name);
myForm.append(idEl);
myForm.append(nameEl);
}
myForm.submit();
This assumes your controller function(??) on the backend is expecting an array of objects with the property name of userData.
Alternatively, you can post it via ajax. For example, the ajax jquery function. Passing your data as the data of the ajax call.
http://api.jquery.com/jquery.ajax/
Don't want to ramble. Let me know if you need more help.
SO won't let me comment yet so have to add another answer. You will not need to define the data source within the .NET code when dealing with client only data. Just use this.
.DataSource(dataSource => dataSource
.Ajax()
.ServerOperation(false)
)
If you will have data coming from the backend then you need to use the generic-less constructor and pass in the object else keep what you have.
Html.Kendo().Grid(Model.MyList)
However, if you are preprocessing some client data on the screen that you want to initialize then you will need to do this on ready. Don't worry about the schema part of the data source. It already knows this when you used the .NET MVC wrapper because you gave it the schema(type) via the generic or the parameter provided.
var initialDS= new kendo.data.DataSource({
data: [
{ ActionName: "Some Name", ActionType: "Some Type" }
]
});
$(document).ready(function () {
$('#docworkflow').data('kendoGrid').setDataSource(initialDS);
});
As I mentioned in the other answer. Use the data source functions for adding additional data to the data source. No need to setDataSource each time you want to add. Just
//Assuming you have 2 inputs on the screen the user is entering info into
var nameEntry = $('#action-name').val();
var typeEntry = $('#action-type').val();
$('#docworkflow').data('kendoGrid').dataSource.add({ ActionName: nameEntry , ActionType: typeEntry });
So after some efforts I come up with. But I don't know where to specify the
data in the html code. Is it possible this way?
#(Html.Kendo().Grid <DockData.Action> ()
.Name("docworkflow")
.Columns(columns =>
{
columns.Bound(e => e.ActionName);
columns.Bound(e => e.ActionType);
}).DataSource( **How do I load a script variable here***)
//This script variable should be fed to the above code.
This variable is populatedwhen the user adds data from the UI which works fine.
var dataSource = new kendo.data.DataSource({
data: result,
schema: {
model: {
fields: {
ActionName: { type: "string" },
ActionType: { type: "string" }
}
}
},
pageSize: 20
});

Load multiple models(aggregation) in forge viewer and load other models as hidden by default until user selects from model browser

I am trying to load multiple models(aggregation) on to the forge viewer(v.6.x) initially while loading, but I want to show only one model and other models as hidden by default(can be with ghost view). Later when user clicks on eye icon from model browser, then that model should be visible/hidden.
I tried calling viewer.hideModel(modelId) after loading the model. But even though the model is showing in model browser, when I click on it, it says error model is not loaded.
var showModel = false;
this.viewer.loadModel(url, {globalOffset: { x:0, y:0, z:0 }, modelNameOverride: modelName}, () =>
{
this.isModelLoaded = true;
this.viewer.caller = this;
this.addEventListenersToViewer();
if(!showModel){
this.viewer.hideModel(modelId); // This is to hide the model by default after loading.
}
},
errorMsg => {
this.isModelLoaded = false;
this.viewer.container.style.opacity = 0;
this.modelLoadError(this.fetchTranslationByKey('getModelError'));
}
);
Expected behavior is to allow user to select from model browser, which models to show/hide on the viewer among all the models loaded initially(linked models should be hidden by default).
Current result I am getting is the linked models are showing in the model browser but when I click on that it says - Error Model is not loaded
A few issues here:
When using arrow function the context that this points to is different so be careful with that
how did you obtain the modelId? Instead of using arbitrary counter better to iterate the model array via Viewer.impl.modelQueue()
I am unable to replicate the model not loaded error with model browser. Can you provide more details or a live sample (jsfiddle/jsbin)?

Change default ViewCube Orientation

I'm using the Forge Viewer to display simple geometry extractions from buildings.
However, when loading them the orientation of the model/view cube is not matching the expected use case (see image).
Basically I would need to swap the "Front View" with the "Top View".
Is this possible to achieve such a thing through e.g. default settings on the viewer object?
My set up is basically identical to the one in this 3rd-party react wrapper of the Forge Viewer: https://github.com/outer-labs/react-forge-viewer
Thank you already very much.
Daniel
EDIT: The model is in STP format
Basically, you can archive this with following steps via Viewer APIs after the model is loaded completely and can be separated into two parts.
(Preproccess) Get the Front view state of the Viewer that your want to make it as the Top:
a. Orient the current view to Front view: viewer.setViewCube( 'front' ).
b. Obtain current view statue of the viewport: var viewState = .getState( { viewport: true } ).
c. Save this viewState to somewhere, your js file or database.
Restore view state and set it as the Top view:
a. Obtain the viewState from somewhere (e.g. js file or database) that you got from the step1.
b. Restore view state via viewer.restoreState( viewState ).
c. Set the current view as Top view: viewer.autocam.setCurrentViewAsTop().
d. Set the current view as Home to avoid the state of the viewcube to be reset: viewer.autocam.setCurrentViewAsHome().
The code snippet for step2:
viewer.addEventListener(
Autodesk.Viewing.GEOMETRY_LOADED_EVENT,
function( event ) {
console.log( '%cGEOMETRY_LOADED_EVENT: !!!Geometries loaded!!!', 'color: green;' );
setTimeout(() => {
const onOrientTopViewCompleted = function() {
viewer.removeEventListener(
Autodesk.Viewing.CAMERA_TRANSITION_COMPLETED,
onOrientTopViewCompleted
);
viewer.autocam.setCurrentViewAsTop();
viewer.autocam.setCurrentViewAsHome();
console.log( 'CAMERA_TRANSITION_COMPLETED' );
};
viewer.addEventListener(
Autodesk.Viewing.CAMERA_TRANSITION_COMPLETED,
onOrientTopViewCompleted
);
var viewState = '....'; //!<< the view state of the original `Front` view.
viewer.restoreState( viewState )
}, 1000);
});
Hope it helps!

Getting selected elements properties in forge viewer when more then one model loaded

I have have a viewer app with 8 models loaded
I have a plugin looking for the "AGGREGATE_SELECTION_CHANGED_EVENT" event
this.viewer.addEventListener(Autodesk.Viewing.AGGREGATE_SELECTION_CHANGED_EVENT, this.onSelectionBinded);
I need to be able to get access to the selected elements properties
this.viewer.getProperties(_dbId, (result) => { })
but it seams the viewer is only looking at the last loaded model not all of them.
do i have to load/switch to the other models ? and if so how.
The viewer.model is always pointed to the first loaded model with my experience. If you want to access other loaded models, you can obtain them via calling viewer.impl.modelQueue().getModels(). Afterward, call Viewer properties APIs in this way:
var allModels = viewer.impl.modelQueue().getModels();
var model = allModels[1];
model.getProperties( dbId, onSuccessCallback, onErrorCallback );
Besides, you can obtain the model instance in the function argument event of your onSelectionBinded callback. So, your onSelectionBinded can be modified to this based on the above logic:
this.onSelectionBinded = function( event ) {
var selSet = event.selections;
var firstSel = selSet[0];
var model = firstSel.model;
var dbIds = firstSel.dbIdArray;
var firstDbId = dbIds[0];
model.getProperties( firstDbId, onSuccessCallback, onErrorCallback );
}
Hope it helps!
I know this is a little late...
Another way to get properties for multi-model, is to use the aggregated method.
var DBids = viewer.impl.selector.getAggregateSelection();
I have a blog post and sample website that goes through the details:
https://forge.autodesk.com/blog/highlighting-clashes-multi-model