Creating Elements

Use IModelDb.Elements.insertElement to insert a new element into an IModelDb. This method takes as its input an ElementProps or a subclass of it, which defines the class and all required properties of the new element. The pattern is:

const elementProps: SomeBisClassProps = {
  classFullName: bisFullClassName
  ... other required props ...
const newElementId: Id64String = iModel.elements.insertElement(elementProps);

The type of the "props" object is chosen as appropriate for the particular Element subclass that is to be instanced. There are InformationPartitionElementProps, SubjectProps, GeometricElement3dProps, and many more. See Wire Formats for the complete list of props interfaces defined in iModel.js. Domains may define their own "props" subclasses.

Why "props"?

As explained in the article on elements and schemas, an element is always an instance of a class in the BIS hierarchy. The BIS class of an element defines what the element is, so that it accurately represents an entity in the real world, according to a well thought out classification scheme that is appropriate to the modeling problem at hand. To that end, domains define many subclasses of Element. These BIS classes support strong modeling semantics. At the same time, it is very convenient to work with BIS classes in iModel.js apps. In particular, there is no need to write a TypeScript class for every BIS class that you may work with.

The IModelDb.Elements.insertElement API is a good example of the way iModel.js combines strong data-modeling semantics with programming convenience. When creating a new element, the app only needs to specify the required properties of the element, including its BIS class. These defining properties are called "props". Often there will be no pre-defined TypeScript or JavaScript class corresponding to a given BIS class at compile time. That's no obstacle. All that matters is that the BIS class is defined in the BIS schema, and the app just needs to supply its name, along with its other required props.

Once an element has been inserted into the iModel, it is understood by iModel.js to be an instance of the specified BIS class. When an app gets the element from the iModel, it will see an instance of a JavaScript class that corresponds exactly to the BIS class definition for that element. All defined properties will be there and will be accessible as properties in a natural, JavaScript way.

That is why the IModelDb.Elements.insertElement API takes a "props" object and why many BIS subclasses can share the same props JavaScript class without confusion.


Here are examples of creating various specific types of elements:


See Subject.insert


  public static insertRobot(iModelDb: IModelDb, modelId: Id64String, name: string, location: Point3d, radius: number = 0.1): Id64String {
    const props = {
      model: modelId,
      code: Code.createEmpty(),
      classFullName: RobotWorld.Class.Robot,      // In this example, I know what class and category to use.
      category: Robot.getCategory(iModelDb).id,
      geom: Robot.generateGeometry(radius),       // In this example, I know how to generate geometry, and I know that the placement is empty.
      placement: { origin: location, angles: new YawPitchRollAngles() },
      userLabel: name,
      radius,                                     // Add extra, Robot-specific properties. Be sure to spell them correctly, as the compiler won't help you here.
    return iModelDb.elements.insertElement(props);

See GeometricElement3dProps.


// Simple example of using GeometryStreamBuilder. Note how the building works with
// geometry primitive types such as Arc3d.
export function generateGeometry(radius: number = 0.1): GeometryStreamProps {
  const builder = new GeometryStreamBuilder();
  const circle = Arc3d.createXY(Point3d.createZero(), radius);
  return builder.geometryStream;

See GeometryStreamBuilder


See SpatialCategory.insert


See ModelSelector.insert


See CategorySelector.insert


See DisplayStyle3d.insert


See OrthographicViewDefinition.insert

Last Updated: 08 January, 2020