Getting error in speckle viewer: e.appendChild is not a function

Hi,
trying my first attempt to use speckle viewer API but getting this error in the very beginning:
@speckle_viewer.js?v=771f4b4c:68914 Uncaught TypeError: e.appendChild is not a function at index.html:50:20 (anonymous) @ index.html:50

it throws here: const viewer = new Viewer({ container: viewerContainer, showStats: false, // Optional: Display performance stats });

Any tips what cause this? or any link to working example of speckle viewer api?
code is very simple:

<body>
  <div id="viewer-container"></div>
  <script type="module">
    import { Viewer } from '@speckle/viewer';
    document.addEventListener('DOMContentLoaded', () => {
      const container = document.getElementById('viewer-container');
      if (!container) {
        console.error('Container not found');
        return;
      }
      const viewer = new Viewer({
        container,
      });
    });
  </script>
</body>

thanks

Hi @Robson

I recommend you have a look at a basic usage of viewer API example available as a live example.

Additionally, we provide documentation for the viewer, which includes some examples like the one here

There is also an ever-growing library of live examples

Cheers

thanks, trying the sample code in sandbox and cannot get a hold for mouse event, to be able to get object properties once clicked. this sample works fine but adding click event causes error “could not get extension of type Ar” when trying add event on object<clicked> any tip with that?

import {
  Viewer,
  DefaultViewerParams,
  SpeckleLoader,
  UrlHelper,
  ArcticViewPipeline,
} from '@speckle/viewer';
import { CameraController, SelectionExtension } from '@speckle/viewer';

async function main() {
  /** Get the HTML container */
  const container = document.getElementById('renderer') as HTMLElement;

  /** Configure the viewer params */
  const params = DefaultViewerParams;
  params.showStats = false;
  params.verbose = true;

  /** Create Viewer instance */
  const viewer = new Viewer(container, params);
  /** Initialise the viewer */
  await viewer.init();

  /** Add the stock camera controller extension */
  viewer.createExtension(CameraController);
  /** Add the selection extension for extra interactivity */
  viewer.createExtension(SelectionExtension);

  
  /** Create a loader for the speckle stream */
  const urls = await UrlHelper.getResourceUrls(
    'https://app.speckle.systems/projects/24c98619ac/models/38639656b8'
  );
  var t = viewer.getObjectProperties(urls.toLocaleString());

  console.log("test",t);

  for (const url of urls) {
    const loader = new SpeckleLoader(viewer.getWorldTree(), url, '');
    /** Load the speckle data */
    await viewer.loadObject(loader, true);
  }
}
main();

Hi Robson

I’ve made this live example that shows how you can get object properties when clicking on them.

Additionally,

getObjectProperties is asynchronous as per the documentation so you will need to await it’s execution

Cheers

hi, i know that’s not the problem. Problems gives the code below: Cannot get click event to fire

viewer.on('object-clicked', (event: any) => {
console.log('Object clicked event fired:', event);

if (event.data && event.data.length > 0) {
console.log('Clicked object data:', event.data[0]);
} else {
console.log('No data associated with the click event.');
}
});

const urls = await UrlHelper.getResourceUrls(
'[https://app.speckle.systems/projects/24c98619ac/models/38639656b8](https://urldefense.com/v3/__https:/app.speckle.systems/projects/24c98619ac/models/38639656b8__;!!B5cixuoO7ltTeg!G0iqs0gi_CZJHn2dX37wRXkpHnkt4iwqgcg2u_RnLOWz0CxDgo-ADZhKo6fAWIugwC0wnFZte9W8sL3-LU87U1hh$)'
);

for (const url of urls) {
const loader = new SpeckleLoader(viewer.getWorldTree(), url, '', {
enableInteractions: true,
});

try {
await viewer.loadObject(loader, true);
console.log('Model loaded successfully:', url);
} catch (error) {
console.error('Error loading model:', error);
return;
}
}

Could you please make a live example of the issue you are facing? Like the one I did here?

It’s impossible for us to determine the cause of your issue just by looking at out of context blocks of code. If you do not want to use stackblitz, a github repo will also do

Cheers

ok, i posted same working sample from you with my changes to be able to display object properties when selected/clicked but it doesn’t display work as intended.

(Basic Setup (forked) - StackBlitz)
thanks

Hi @Robson

Thank you for providing me with the live example. There are several issues regarding what you are trying to do, but all of them concern the way you are trying to use the viewer API

You are trying to do:

selectionExtension.on('object_selected', (event: any)

Which is incorrect, as the SelectionExtension does not emit any events, and especially the 'object_selected' event which does not exist anywhere in the viewer API. Instead what you want to do is:

viewer.on(ViewerEvent.ObjectClicked, (event: SelectionEvent | null) as per the documentation. So the viewer instance emits the ViewerEvent.ObjectClicked so you want to hook up with it.

You are also trying to do:

const selectedObject = event.data[0]; // First selected object
if (selectedObject) {
  const properties = selectedObject.properties;
  // Display properties in a popup or sidebar
  ...
}

Which is also incorrect as data[0] does not exist on the SelectionEvent type or anywhere in the viewer API for that matter. What you want to get is event.hits[0].node which represents the closest object you’ve clicked on.

Then you attempt to read const properties = selectedObject.properties which again does not exist. Continuing from the previous paragraph, you can the properties from the TreeNode like this

const node = event.hits[0].node
const properties = node.mode.raw

Finally, here is a live example, with all the corrections, working as intented

If you are using a generative AI for writing code, it’s clearly hallucinating wildly, as the API calls you are trying to make do not exist. The viewer library has an explicit API which you can thoroughly consult in our documentation

Cheers

thanks, that will start me up, now I’ll look into documentation then :slight_smile:

1 Like