A Composite Input is an input on a Component that can take an entire entity, instead of just a single attribute. (We recommend reviewing the Exaptive Data Model, if the terms entity and value are foreign.) The component author controls whether there are Composite Inputs and how you, the xap builder, interacts with them. This article will walk you through how to recognize Composite Inputs and how to work with them, including examples.  

By the end, you may find yourself wanting to know more about Merge Gates.

If you want to learn how the component author does this, check out this article on creating Composite Inputs 

What are Composite Inputs and Granular Inputs?

Here's a component with a single input port, userLocation. 

If you click the input, userLocation, you'll see userLocation is an entity with attributes firstName, lastName, and location, which consists of attributes lat and lng.




So to work with this component in a xap, you'd need to pass it an entity with those attributes. That is a composite input. It requires multiple attributes and values...that is, unless the composite input has granular inputs exposed...

Here is the same component, except the component author has exposed the granular inputs. Each attribute has it's own input, in addition to the entire entity. 



So what's the difference? Granular inputs give you, the xap builder, greater flexibility with how you pass data to the components. It need not be in a clean package - the entity - beforehand. It's up to the component author whether to enable this. Sometimes granular inputs create a component that's too large or messy in the dataflow. Sometimes the flexibility of granular inputs aren't a good fit for the component author's use-case. As the xap builder, if you didn't build the component, you just have to know what you're seeing and how to work with it. 

If you want to learn how the component author does this, check out this article on creating Composite Inputs


NOTE: Exposing Granular Inputs doesn't prevent you from assembling the entity and passing it to the component as a whole, as if they weren't there. You just pass the entity to the "userLocation" input, instead of using the Granular Inputs below it.  




So let's go through some examples to see how Composite Inputs, with and without exposing the granularity, get used to address Xap challenges.


Timing: Without Granular Inputs

Without Granular Inputs, the xap builder has to use Merge Gates to control the flow of data and timing of triggering your Component. 


Let's take the same userLocation example. Assume all potential last names are unique, but some users may share the same first name. Location can be updated multiple times for the same user, but updating occurs in an unpredictable pattern. Without granularity, we have an input that looks like this: 


The xap builder must construct the entity with all of the relevant data prior to sending it to the input. They can do this using a merge gate, like this: 

The merge gate allows the xap builder to assemble the entity in the proper structure and to design the specifics of when the output is triggered. By default the condition for the merge gate to trigger is true, meaning it will be triggered any time a new input is received. But they only want it to trigger when it has all of the data, and when it's the right data. To do that, they use thetimeOf()  function (learn more about merge gates here) like this: 

Now, the component will only trigger when all inputs have received a value. So, to some degree this solves the timing issue. But what about if the user being updated changes and the first value received is the first name? Now the merge gate will trigger with the new first name, but the old last name and location. To solve this, the xap builder can reset inputs either on receipt of another input or on output. A good starting point is resetting location on output. Clicking on the x2 input opens that input: 


Further, clicking on the reset icon opens reset options. 

Here, they've checked the box for "Reset on Output". Now, each time the merge gate triggers (based on the condition set) this input will be cleared. Now if a new first name or last name is received the merge gate won't trigger until a new location is also received. 


The last thing the xap builder can do to handle timing is "Reset on Input". In this case, if a new first name is received and a new location is received we don't want the merge gate to trigger with the old last name. They're able to add a list of all inputs we want to reset when an input is received, like this: 

In this case they only want to reset the last name, so "x1" is the only input reset. 

Timing: With Granular Inputs


The same thing happens more or less with Granular Inputs, but you control it in the Component Script, instead of the xap builder with a Merge Gate. 


Here's the component from the above example with the Granular Inputs exposed: 

Note there is an input called "userLocation", which is identical to the input used in the above example. This input takes an entity that's been preassembled, just like in the above example. Now, though, there is an input for each property. These can be used to assemble the entity on the component, rather than in an external merge gate. 


Wiring the same outputs from the above example into this component looks like this: 

Now, the same issue presents itself around the timing of triggering the Python component. In the previous example, the component was triggered each time the input was received based on the assumption the data was properly assembled when it arrived. Now, this is handled in the component using merge logic. 


Merge logic lets xap builders design when the component should trigger, just like the merge gate in the previous example. Opening the mergeLogic input you see all of the options available in a merge gate are available here: 

To achieve the same effect as the previous example, we make the same changes. Here's the code snippet: 


  "condition": "timeOf('firstName') && timeOf('lastName') && timeOf('location')", 
  "resetOnOutput": [
  "resetOnInput": {
    "firstName": [
  "debug": false


So, the condition is unchanged. I want the component to only trigger if there is a value for all three inputs, remember that by default it triggers any time there's a new value for any of the inputs. I've set the location input to be reset any time the component triggers. resetOnInput is less intuitive, so let's break it down. resetOnInput is an entity that takes key-value pairs where the key is the name of an input and the value is a list of the inputs that should be reset when that input is received. So, in the above snippet when the firstName input is received the lastName input will be cleared.