Get Property Name of Part that is Selected - autodesk-forge

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

Related

Autodesk Forge Viewer, Search

I am using Autodesk Forge Viewer.
viewer.search('"' + keyword +'"', function(e)
{
viewer.select(e);
viewer.fitToView(e);
}
I am searching like this.
The problem is that it searches for both "SG-100" and "SSG-100".
I only want to search for SG-100.
How can I do this?
Help!
My suggestion would be to do a second filter inside the search:
viewer.search(keyword, (dbIds) => {
// success
viewer.getBulkProperties(dbIds, ['AttributeName'], (elements) => {
let dbIdsToSelect = [];
for(var i=0; i<elements.length; i++){
if (elements[i].properties[0].displayValue===keyword)
dbIdsToSelect.push(elements[i].dbId;
}
viewer.select(dbIdsToSelect);
viewer.fitToView(dbIdsToSelect);
}
}, (e) => {
// error, handle here...
}, ['AttributeName']);
I agree with Augusto's suggestion that you'd need to limit the search scope to specific properties only to avoid partial matches. According to the search function description it's supposed to do just that if you provide the list of property names in the 4th argument that is called 'attributeNames'. Unfortunately, from my experience, that does not work, so you need a second level filtering by using a getBulkProperties function that will reduce the list of dbIds from the search to only those that have specific properties defined. Pay attention, that the search method belong to the viewer object but the getBulkProperties method belongs to the viewer.model object.

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
});

How to access db data in a svf model?

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))

How to add custom menu to Autodesk Forge Viewer?

Helo
I'm using Viewer Example form here: https://forge.autodesk.com/en/docs/viewer/v5/tutorials/basic-viewer/
(Step 1)
and now I need:
1. add custom menu on right click
2. get info's for clicked object, like Area, Volume, Length (if 3D) or length if 2D.
How to do that, please?
I try to copy whole "class MyContextMenu extends ... " code from
https://forge.autodesk.com/blog/customize-viewer-context-menu
but it does not worked.
Thank you.
Here's a simple example of adding custom menu items to the context menu: http://jsfiddle.net/s47vy5u3/2. You'll just need to include your Forge app's access token and some viewable URN. The menu customization code itself looks like this:
function customizeMenu() {
const viewer = NOP_VIEWER;
viewer.registerContextMenuCallback('MyCustomMenuItems', function(menu, status) {
menu.push({
title: 'My custom menu item',
target: () => {
// Add your menu item's code here
}
});
});
}

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!