Projected ports, as opposed to projection ports, allow users to work with data coming from a projection port. For example, consider that you have created a scatter plot with a duffle of entities. You have set the projection input so that channels map properties on each entity to attributes of the scatter plot (x, y, size, etc.). A projected input on the scatter plot would accept data in the same format as the primary projection input and with the added benefit of mapping objects to the same unique projected id used for the primary projection input. Projected outputs work in the opposite manner by allowing the user to transform the output format using a projection. Don't worry if this is not all clear at this point, we are going to take a closer look below.


We recommend you get familiar with projections, the concept, and how to create projection ports before diving into this article.


You can also read about how to use projected ports in the dataflow.




Creating Projected Inputs


Creating a projected input requires working with a component that has a projection. The component's projection must have at least one target. To create a projected input, open the component editor. Add a new input port. Select the 'Use Projection' checkbox and select the target that matches your desired projection.



In order to use projected inputs, you must make some changes to your component's script. You can access the selected entities as shown below with the 'selectedNodes' variable. Each selected node will contain a projected Id and the projection channels. 


const nodes = this.api.inputState.get(['data', 'nodes']).export();

// A multiset of projected IDs
const selection = this.api.inputState.get('selection').export();

// Get the selected nodes
const selectedNodes = nodes.filter(n => selection.includes(n.projectedId));




Creating Projected Outputs


Creating a projected output requires working with a component that has a projection. The component's projection must have at least one target. To create a projected output, open the component editor. Add a new output port. Select the 'Use Projection' checkbox and select the target that matches your desired projection.



A projected output must receive the projected ids for all of the entities in the projection input. Otherwise, the output selector will not function correctly. Users can access and output the projected ids using a script such as the one below.


let nodes = state.data.nodes;
const ids = nodes.map(d => d.projectedId);
this.api.output('data', ids);




Working With Channels - References


There's a convenience you should be aware of. Suppose we're making a network diagram with nodes and edges. Let's take a look back at the channel form.


Here I have two targets: node and edge. A node has a name and a color. An edge has a source and a destination. The edge's source  and destination are what are called "references." This is because they reference another entity from the data, in this case, nodes. The edges begin from a node - their source. They end at a node - their destination.


To declare that a channel references another target, check the box for 'Use Reference'.



Notice that the 'Type' field changes to 'Reference'. In this drop-down menu, you'll select the target that this channel references. In the network example, I'd choose "node".



Working With Channels - Multiplex Channels


Multiplex channels allow users to map the attributes of a data port's incoming entities to multiple channels of the component. It is specifically applicable to visualizations that require 

the data definitions of one target to inform the use of other targets. As an example, the table component has two targets: rows and columns. Each entity in the incoming duffle represents a row in the table. The multiplex functionality allows the user to select the entity attributes that will be shown as columns in the table. Let's go through an example.


Adding multiplex functionality is very similar to setting a channel as a reference. However, there are some requirements. Multiplex functionality can only be added to a projection port. The projection must also have two targets. For example, the table component has rows and columns. The rows target has a multiplex channel called fields. To set a channel as a multiplex, expand the channel and select the checkbox as multiplex. Then, select the other target that will serve as a multiplexer. In the table example, the columns target is the multiplexer. 


Within your component's script you can access multiplex data as properties on the component's data object. The properties will be named after the projection targets. In our table example, you would use the following code:


const data = this.api.inputState.get('data');
const columns = data.get('columns').export();
// each column will contain the column channels, a multiplex value selector and a projected id
// ex:
{
    label: "first"
    projectedId: "id1209"
    rows_mvs_fields: "first"
}

const rows = data.get('rows').export();
// each row will contain the row channels, a projected id, and the multiplex channel, fields
// the properties in the multiplex channel will have keys that match the projected id of a            // column and values that correspond to the column value from the multiplex value selector
// ex 
{
    dummy: 0,
    fields: {
        id1209:  "Willie"
        id1210: "Hunt"
        id1211: 37
    },
    projectedId: "id1159"
}



To work with multiplex channels for the table component, we must provide it with a duffle of entities. Each entity has the following properties: first name, last name, age and children.


[
  {
    "first": "Bess", 
    "last": "Drake", 
    "age": 65, 
    "children": 4
  }
...


By default the multiplex channel, columns, is set to auto mode. This will display every entity property as a column.






















Fixed mode offers more control by allowing the user to set the specific properties that will be displayed. For each entity property that is added, the user can then configure the channel values for that property. In the example below, I have removed the "first" property and edited the labels value selector for the "last" property to display "first." As you can see, the table shows a "first" column that is filled with last names.