documentationfor yFiles for HTML 3.0.0.1

Automatic Type Conversion

yFiles offers automatic type conversion as a convenient way to specify complex yFiles types using a shorthand syntax. In parameter lists, parameter objects, or property setters, you can assign these convertible types from a substitute type, such as a simple string. The substitute type is then converted into the actual type at runtime.

This approach often allows for more compact code, especially for object initialization. The code also becomes more readable because many of the replacement strings resemble well-known CSS declarations. The potential drawback is that code completion cannot strictly validate all substitute types.

If a property or method accepts a convertible type, it is marked with CONVERSION in the API documentation. For example, see fill. A section in the class description of each convertible type describes the available conversions for that type.

Additionally, convertible types provide a static from method, such as from. These methods convert convertible values into an instance of the actual type.

Most types that support automatic type conversion work for all public properties, parameters of constructors, and factory methods. For performance reasons, some protected methods and less frequently called, performance-critical methods do not allow automatic type conversion. If you are unsure, consult the documentation and look for the CONVERSION tag. Be aware that you cannot use shorthand variants of convertible types directly within collections. They are converted automatically only when passed directly as arguments to the yFiles API. The runtime type checks should detect most invalid usages, but without debugging checks, runtime behavior can be undefined.

Enums

Enum types are generally convertible. Almost everywhere enum values are expected, you can substitute them with a simple string that consists of the enum value’s name. The name is accepted in uppercase and lowercase letters. If a name consists of several words, you can separate them with the - or _ character.

When enum values can be combined bit-wise, you can use the |, +, and , characters to combine the string representations of several enum values in a single string, or you can specify them in an array of strings, as in the following example:

Conversions using bit-wise operators and all-caps conversions are not covered by the typescript typings. We advise using an array of lower-case conversion.

const labelStyle = new DefaultLabelStyle({
  horizontalTextAlignment: 'center',
  verticalTextAlignment: 'CENTER'
})

graphComponent.inputMode.selectableItems = 'node,edge'
graphComponent.inputMode.selectableItems = 'NODE|EDGE'
graphComponent.inputMode.selectableItems = ['node', 'edge']

Colors, Fills, and Strokes

Colors and Fills can be defined as CSS color strings. Strokes are converted from strings adhering to the CSS shorthand properties for border definition. Number values are also supported to conveniently use hexadecimal notations and numeric calculations.

const nodeStyle = new ShapeNodeStyle({
  fill: 'blue',
  stroke: "3px dashed red"
})
nodeStyle.fill = 'hsl(225, 98%, 60%)'
nodeStyle.fill = 'rgba(255, 255, 0, 0.5)'
nodeStyle.fill = new SolidColorFill('rgb(255, 255, 0)')
nodeStyle.stroke = '#336699'
nodeStyle.stroke = 0xff00ff

Fonts

Fonts can be created from strings that adhere to the CSS shorthand property for fonts.

const labelStyle = new DefaultLabelStyle({
  font: 'bold 16px sans-serif'
})
labelStyle.font = 'italic Tahoma'
labelStyle.font = 'normal xx-large Arial'

Rectangles, Points, Sizes, and Insets

Geometric classes like IRectangle, IPoint, and ISize are defined using numbers for x, y, width, and height. Instead of using the constructor directly, these classes can be created from arrays or plain JavaScript objects.

graph.createNode([10, 10, 50, 20])
graph.createNode({ layout: { x: 10, y: 10, width: 50, height: 20 }})

graph.createNodeAt([10, 10])
graph.createNodeAt({ location: { x: 10, y: 10 }})

graphComponent.doubleClickSize = [20, 20]
graphComponent.doubleClickSize = { width: 20, height: 30 }

Insets can be specified with a single number (that describes the inset for all sides), an array, or a plain JavaScript object. This works similarly to the shorthand for CSS margins.

const rectangle = new Rect(0, 0, 10, 10)
rectangle.getEnlarged(10)               // horizontal and vertical
rectangle.getEnlarged([5, 10])          // vertical, horizontal
rectangle.getEnlarged([15, 10, 5])      // top, horizontal, bottom
rectangle.getEnlarged([5, 10, 15, 20])  // top, right, bottom, left

rectangle.getEnlarged({ left: 5, top: 10, bottom: 5, right: 10 })

When using plain objects to describe a convertible type, they may not work together with method overloads. That is because if the substitute object is the only parameter, it creates an ambiguous overload with the parameter object notation. Also, it may not be possible to determine the correct overload at runtime if there are multiple possible overloads. However, using a substitute object in a parameter list or as a named option argument in a parameter object is valid unless the resulting type is ambiguous.

Arrows

Most Arrows are described by a shape, a scale, and a color. A string that provides some or all of these values can be used to define an Arrow.

const edgeStyle = new PolylineEdgeStyle({
  sourceArrow: 'circle',
  targetArrow: 'green xx-large diamond',
})
edgeStyle.sourceArrow = 'blue simple'
edgeStyle.targetArrow = 'rgb(200, 200, 0) simple'

Cursors

To set one of the default Cursors, you can use the name of the constant as a string. Similar to enum values, the name is accepted in uppercase and lowercase letters. If a name consists of several words, they can be separated with the - or _ character.

const itemHoverInputMode = graphComponent.inputMode.itemHoverInputMode
itemHoverInputMode.hoverCursor = 'grab'
itemHoverInputMode.hoverCursor = 'MOVE'

TimeSpan

TimeSpan is defined using a simple number representing the duration in milliseconds or through one of the static factory methods. A more convenient and readable way is to use strings that are converted into TimeSpan objects.

graphComponent.doubleClickTime = 300  //milliseconds
graphComponent.doubleClickTime = '4s'
graphComponent.doubleClickTime = '250ms'
graphComponent.doubleClickTime = '0:23:10'
graphComponent.doubleClickTime = '1m 0.5s'

Enumerables, Collections, and Lists

Arrays and JavaScript Sets can be converted to IEnumerable<T>, ICollection<T>, and IList<T>.

graph.groupNodes([child1, child2, child3])
graph.groupNodes(new Set([child1, child2]))

In fact, any value that implements the 'iterable' protocol will also be converted automatically. For example, the return value of a Generator function:

let node = graph.createNode()

function* createNodeGenerator(){
  yield node
  let i = 0
  for (let n of graph.nodes) {
    if (i++ %2 === 1) yield n
  }
}

// obtain an iterator from the generator
const generator = createNodeGenerator()
graph.groupNodes(generator)

Be careful with iterators when converting them to IEnumerable, though. Iterator instances can only be iterated once. So if the iterator is passed to an API that expects an IEnumerable<T>, it will be converted to a live enumerable that will enumerate all the values in the iterable on request. Once the iterable has completed, the enumerator will complete, too. But unlike most IEnumerable implementations, it will be unable to enumerate the values again because the iterable is complete and cannot be reset. If the API expects a List, however, the iterable will be iterated immediately, once, and the values will be cached in the list that is passed on to the API.

If you want the receiver of the value to be able to enumerate the values of an iterator more than once, either cache the values in an iterable first, or use a generator function that can be called again. If you don’t want it to be dynamic, or if generation is computationally expensive, consider caching it:

let node = graph.createNode()

function* createNodeGenerator(){
  yield node
  let i = 0
  for (let n of graph.nodes) {
    if (i++ %2 === 1) yield n
  }
}

// pass the generator function without calling it,
// yFiles will create an IEnumerable that can be re-enumerated, dynamically,
// any number of times.
graph.groupNodes(createNodeGenerator)

// cache the generated values in an iterable that can be iterated more than once
graph.groupNodes(Array.from(createNodeGenerator()))
// or
graph.groupNodes([...createNodeGenerator()])
// or
graph.groupNodes(new Set(createNodeGenerator()))

ItemMapping, ItemCollection, SingleItem

These types are used in LayoutData<TNode,TEdge,TNodeLabel,TEdgeLabel> and graph algorithm wrappers to provide different ways to specify additional data for the graph. Type conversion allows you to omit these properties and directly assign the property of the actual LayoutData<TNode,TEdge,TNodeLabel,TEdgeLabel> or graph algorithm wrapper.

// ItemMapping
const hierarchicLayoutData = new HierarchicLayoutData()
// omitting 'constant'
hierarchicLayoutData.sourcePortCandidates = new List([
  PortCandidate.createCandidate('RIGHT', 0),
  PortCandidate.createCandidate('LEFT', 0)
])
// omitting 'delegate'
hierarchicLayoutData.sourcePortCandidates = () =>
  east ? PortCandidate.createCandidate('RIGHT', 0) : PortCandidate.createCandidate('LEFT', 0)
// omitting 'mapper'
hierarchicLayoutData.sourcePortCandidates = new Mapper()

// ItemCollection
const treeLayoutData = new TreeLayoutData()
// omitting 'delegate'
treeLayoutData.assistantNodes = node => isAssistant(node)
// omitting 'constant'
treeLayoutData.assistantNodes = node1
// omitting 'items'
treeLayoutData.assistantNodes = [node1, node2]
// omitting 'mapper'
treeLayoutData.assistantNodes = new Mapper()
// omitting 'source'
treeLayoutData.assistantNodes = graphComponent.selection.selectedNodes

// SingleItem
const shortestPath = new ShortestPath()
// omitting 'constant'
shortestPath.source = node1
// omitting 'delegate'
shortestPath.source = node => isSource(node)
// omitting 'source'
shortestPath.source = graphComponent.selection.selectedNodes

All these types also provide option overloads with their constructors. Therefore, instantiations can be simplified further. For example:

const shortestPath = new ShortestPath({
  source: graphComponent.selection.selectedNodes,
  costs: 20,
  sink: node => isSink(node)
})

IMapper

The IMapper<K,V> type is used to associate additional information with graph items in layout algorithms. IMapper<K,V> instances can be created from native JavaScript Map instances.

const layerIndexMap = new Map()
// use a JavaScript Map as IMapper
const hierarchicLayoutData = new HierarchicLayoutData({
  layerIndices: layerIndexMap
})