Attribute Container

Attribute container is an attribute consisting of other attributes. Rather than writing complex product rules where attributes need to be dynamically added to a configuration, the administrator is now able to use attribute container which can be dynamically expanded, either by a set of attributes or another product.

Container has structure like a table. Its columns are defined in attribute administration. Its rows can be added and deleted in rules or manually during configuration. Each cell can have some value according to its column definition.


Container Columns

You define container columns through attribute administration. By defining column you define next:

  • column name
  • whether the column is a stand alone or an attribute
  • display type - label, text box, check box, drop down list, list box…
  • column total (optional)

When an attribute is referenced in a column with the display type Label, the attribute display value is visible in the configurator.

Column total can be defined as:

  • sum of its values
  • average of its values
  • total calculation formula - for example to make column total as a function of other column totals or container properties

Types of Columns

You are allowed to define a container without any product and attribute. If this is a case, then its rows are just a collection of cell values.

For example: User defines a container with two columns ”Name” and ”Description” both as text box stand alone columns. During configuration you can enter a value in each row for both columns.

Also, you can define a container without any product but with some attributes in columns. In this case, its rows are collection of selected attribute values. If you plan to have some check box, drop down, or list displayed in container cell, then it is necessary to use attributes of the appropirate type for the particular cell.

For example: You can define a container with columns:

Name” as stand alone text box, and
Voltage” as Voltage attribute with 110 and 220 values in a drop down list.

Finally, you can define a container with products. In this case each container row represent a product. Columns of such container are stand alone columns and product attributes. Its rows are union of cell values and selected product attribute values. Such container can be marked as line item in the product - then all its rows will appear in the cart as child line items of the main item.

For example: First you should define several products then create a container with columns as some of attributes used in those products. During configuration of such container each row will be a product, and user will be able to edit that product attribute in line of container row.

Container column calculation formula

The column value can be calculated automatically with a specific formula. The label column formula is evaluated each time, while other column type formulas are evaluated only once when a row is added.

Take a look at the following case: a user defines text box columns First Name, Last Name and the label column Full Name with the following calculation formula:
<*CTX(MyContainer.CurrentRow.Column(First Name).Get)*><*CTX(MyContainer.CurrentRow.Column(Last Name).Get)*>
as well as another text box column Date Added with the following calculation formula: <*CTX(Date)*>.

The Full Name column value will be updated every time when First Name or Last Name column value is changed while Date Added will be calculated only once when a row is added.

Displaying product attributes in container columns

Depending of selected display option on product attribute details container column will show selected attribute value code (formula equivalent <*valuecode(attribute name)*>) or selected attribute display value (formula equivalent <*value(attribute name)*>) where in case of attribute type User Input or Computed - Date attribute display value gets validated against valid date string.

This is the list of attribute display options that shows selected attribute value in container column:

  • Button
  • Display Only Text
  • File Attachment
  • Free Form exact match w. Otherwise option
  • Free Form, Exact Match
  • Free Form, Match lower
  • Free Form, Match upper
  • Free Form, Set Match lower
  • Free Form, Set Match upper
  • Free Input, no Matching
  • Hidden calculated, Match lower
  • Hidden calculated, Match upper
  • Hidden, Calculated, no Matching

Rest of the attribute display options shows selected attribute value code.

Container column permissions

For each container column is possible to define permissions per user type group. Possible values are:

  • Hidden
  • Read Only
  • Editable
  • Required

This allows, for example to hide a column from users of some user type group, make a column read only, make it required… Default permission for all user type groups is Editable. Choosing a value from - All permissions - will set that value to all user type groups.

In the configurator, if there's any row that have unfilled column that was marked as Required in the admin, it will make the whole container invalid. You can validate container state with the <*CTX( Container(AttributeContainerName).IsValid )*> tag.

Container Column Sorting

Container columns can be sorted and viewed in the configurator in ascending and descending order.
Please note that column sorting does not affect the actual order on the quote.

To sort a container column, click the column heading.
An arrow displays in the top-right corner of the column heading, showing whether column sorting is ascending or descending.
To switch between ascending and descending sort order, click the arrow.

Note: Numbers and strings stored in a text field are sorted in the same way they are sorted in Excel spreadsheets.

Container Rows

Container rows are added/deleted during configuration, manually by user or by a product rule. In administration it is possible to define min and max constraints and whether rows can be added, deleted, moved or not.

Adding rows to the container

When you set up the attribute container and you choose more than one product that can be added to it, then when user clicks to add a row during configuration, he will be introduced with the list of defined product that can be added. User must select one product per row.

If there is no products in container or there is just one, then you can use a following tag in rules to add rows:
Container(X).Rows.Add(2); 2 is the number of rows that will be added.

On the other hand if there is more then one product in a container, following tag should be used in rules for adding rows:
To add two rows of product A, and four rows of product B in the container X.

Min and Max number of rows constraints - Also, it is possible to define min and max number of rows. In addition, user can also define min and max number of rows for certain product. If min constraint is violated - delete row action will not be available. Similarly, if max constraint is violated - add rows action will not be available during configuration.

Validation rules - User can also define validation rules that will display appropriate messages to users if container is configured to some invalid state. If validation condition evaluates to 1 it is assumed that validation rule is broken and its message is displayed below the container.

Container Actions - In administration one can define actions that user can execute on container rows - add, delete, copy, reorder, edit…


Container can also have one or more properties. If a calculation formula for a property is defined it will be evaluated on each configuration modification. On the other hand user can leave calculation formula empty and set container property from parent product rule with CTX tag.

Container is defined globally so its execution product context is unknown at design time. Hence user should not reference some parent attributes values directly from container but use properties instead. From the parent, product set a property from a rule, and use that property inside the container. So, properties should be used as data container for interaction between container and parent product.

Automatic value propagation

If a product contains one or more attribute container, and beside that contains an attribute that is also contained within the attribute container, then it is possible to mark that attribute as “Transfer to Container”.

In this case, when user selects a value(s) for that attribute during configuration, then selected value(s) will be automatically transferred to all containers in that product that contains that attribute.

To make long story short - a value selected in parent product will be selected in all container rows products.

For example: User can have a product “System” that has attributes “Voltage” and attribute container “Elements” that can have product A, B, and C which all have “Voltage” attribute too. If user marks “Voltage” attribute in “System” product as “Transfer to container”, during configuration all rows in the container (products A, B, C) will have same “Voltage” attribute value as in the “System” parent product.

Note that propagation of attribute values from parent product to child container products may result in different container state (totals, properties…) which may further trigger a new rule execution in the parent product, which leads to another propagation of parent attribute values to containers… This loop execution may decrease performance, especially if there are more then one container in the parent product, and is limited only to a several repetitions. So, avoid any dependency loops between parent product and child container products if you are using “Transfer to container” option.

Edit row action

If container uses products, then container's row represents that product. Editing a container cell, which is product attribute in the configurator, user actually edits row product attribute inline from the container. If Edit row action is available for that container, user is able to open the configurator for the row product and configure it same way as if it was opened from the catalog. This allows the user to edit more attributes, not just those visible from the container columns. Once a user finishes configuration of that container row and click save button, he is returned back to the parent product and the container columns for that row are refreshed with the newly configured attributes.

During configuration of a container row in its separate configurator, rules of the parent product are executed along with rules of the row product.

Container will be used to present results of product search

Instead of being able to only use containers flagged as “Container will be used to present results of product search” in System or Collection type products, these containers are now also able to work in Configurable products and add their rows as line items to product configuration without affecting anything else.
Each container row in “Container will be used to present results of product search” container contains a column which carries product part number. This column is known to container, and container can obtain product ID for this part number.

User can select, de-select row, add product to the quote or edit existing item. Typically, there is a checkbox on each row, which serves for user to select this row – meaning he would like to add it to the cart. Once the row is selected, container knows the product ID of this row, because it’s looked up based on part number. To enable users to search for and add simple products in configurator, based on their part number, you should go to the Columns tab in Attribute and add two new columns. When adding the first column, set Text Box as its Display type and set Product Part Number as its Column Type. When adding the second column, set Stand Alone Column as its Column Type and set Selector Check Box as its Display Type.


When user selects one or several rows in the container, and clicks on ‘Add To Quote’:

  1. If product is marked as ‘System’ and attribute container is marked as line item, SAP CPQ will add line items for each selected product (found based on part number). Attribute container itself won’t be added to the quote as line item. When user clicks on ‘Edit’ on any of these products in the quote, SAP CPQ will take user to the parent product
  2. If product is marked as ‘Collection’ and attribute container is marked as line item, SAP CPQ will add line items for each selected product (found based on part number). Attribute container itself won’t be added to the quote as line item. Users will be able to delete separate items from the quote.
  3. If product is marked as ‘Configurable’ and attribute container is marked as line item, SAP CPQ will add line items for each selected product (found based on part number). Attribute container itself won’t be added to the quote as line item. When user clicks on ‘Edit’ for main item, SAP CPQ will take user to the product configuration page.

Container Paging

Container with large number of rows can be divided in multiple pages. Container paging provides the ability not to show all rows for that container at once but subdivide them into pages. Considering the flag ‘Enable Paging for Container’ on particular container (if it is checked) and combo box ‘Default number of rows per container page’, that are on admin side under Setup > Attributes, you will define if paging will be available and how many rows will be available per container page by default.


If flag ‘Enable Paging for Container’ is not checked, then no paging will be available. From the combo box ‘Default number of rows per container page’ you can choose how many rows will be preselected by default per container page. Available rows per page will be 5, 10, 20, 50 or 100. Paging is located at the bottom of the container page and arrows to navigate from page to page are shown - Figure 2.

Figure 2

If container contains selectable column (type Selector Check Box or Selector Radio Button) then 2 radio buttons will be shown on the bottom (‘Show All’ and ‘Show selected’), and user will be able to choose what rows to be shown between these two selections - Figure 3.

Figure 3

On the user side under combo box ‘Show items’ user can change default pre selection of the number of container rows to be shown per page - Figure 4. This change will be applied on the admin side as well, so next time the user comes to this product the changed preselected value for items per page will be shown (preselected).

Figure 4

Multiple rows copy

You are able to set number of row’s copies and to select which fields/columns will be copied.

To turn on this functionality admin should set flag “Allow multiple copy” in container setup. (See Figure 5). picture5.jpg

Figure 5

On User Side, when user click on Copy row action, a pop-up with next feilds appears: (See Figure 6)

* Number of copies - input quantity field

* Fields that will be copied – checkboxes with all container rows

Field “Number of copies” is populated with number 1 by default. User can override this number by typing the desired number of row copies. When clicked on Copy, defined number of rows are added to the container.

By default checkboxes corresponding to container columns are selected. User can select or diselect the column as desired.

Unchecked fields, will be empty upon row is copied. These fields can be populated by user afterwards. picture6.jpg

Figure 6

Example - Creating an attribute container

To create a sample container attribute, go to setupProduct CatalogAttribute, then click on Add New button. From the Attribute Type dropdown list, select Container. You can find more information on how to create an attribute on the next help page: Create attribute.

Now, when you have your container attribute created, define some columns:

  • Define a column ”Price A” that is a stand alone column and will be displayed as text box
  • Define a column ”Price B” that is a stand alone column and will be displayed as text box
  • Define a column ”Name” that is a stand alone column and will be displayed as text box
  • Define a column ”Memory” that is attribute “Memory” and will be displayed as drop down list
  • Define a column ”Amount” that is stand alone column and will be displayed as text box. Also set its total as sum. This way all values in this column will be summed and sum will be displayed in the column footer.
  • Define a column “X” with total formula as follows

<*eval( <*CTX(MyContainer.Total(Price A))*> + <*CTX(MyContainer.Total(Price B))*> )*>

This formula will sum Total of column named Price A and Total of column named Price B.

Container Iron Python events

Four Iron Python events are available in attribute container setup. These events trigger when the particular container action is performed. The list of events follows:

  • onRowCopied - triggers when the existing row is copied
  • onRowDeleted - triggers when row is deleted from the container
  • onRowAdded - triggers when row is is added to the container
  • onCellEdited - triggers when cell content is updated

You can set actions for these events in attribute container setup as shown in the Figure 7.

Figure 7 - Container's events

These events trigger only on a user interaction. If the container is manipulated through another script (such as Adding a new row through another Iron Python script) these events will not trigger. Having these events exposed enables you to attach the Iron Python script to them. It appears to be very useful to have these events avalable in case when you want to make some decisions during container manipulations. Each event has a list of available arguments and particular context. For more information on available context and arguments check this scripting help page.

Container "Collapse/Expand" customization in Responsive Design

SAP CPQ classic design uses xslt files to render the page, therfore it is pretty easy to modify the xslt file and enable collapse/expand functionality. On the other hand, in SAP CPQ responsive design, contaner rows are not collapsible by default. While there is no system option to enable this feature in responsive design, the same behaviour can be enabled by making some customizations on the responsive templates. Next steps contain instructions on what should be done to make container row collapsible.

  • Go to Setup > UI Design > Responsive Templates and click Add New. This way you will create new custom template that you can use instead of the default one. (See Figure 1)
  • Under Page drop down list select Configurator
  • Under Template drop down list select Editor/Container/ContainerTemplate. This will load the default template into “Default Template” textarea. (See Figure 1)
  • Click on Copy default template to load the copy of the template into another textarea where you will make customizations (javascript, css, html, knockout.js). (See Figure 2)

Figure 1 - Define new custom template

Figure 2 - Load default template into “New Template” textarea

  • Give a name to your custom template.
  • Check Default. This way you instructed SAP CPQ to render container using your custom template, not the standard one.
  • Customize New Template as instructed below

1. At the very beginning of template add this chunk of code.

.label-inline label{
  display: inline-block !important;
<script type="text/javascript">
  var expandingContainersModel = {};
  cpq.ready(function() {
    expandingContainersModel = {
        expandedContainers: ko.observableArray([]),
        isExpanded: function(id) {
            return this.expandedContainers.indexOf(id) > -1;
        expandCollapse: function(id) {
            if (this.isExpanded(id)) {
            	for (var i = this.expandedContainers().length - 1; i >= 0; i--) {
                	if (this.expandedContainers()[i] === id) {
                        this.expandedContainers.splice(i, 1);
            } else {

This script tag will create global model – expandingContainersModel which have one observable array where expanded containers ids are stored. Since all containers are initially collapsed, this array will be empty when page is loaded.

2. At the very beginning of template add this chunk of code

    <!-- ko template: { name: 'LabelTemplate' } -->
    <!-- /ko -->

and replace it with this code:

<div class="label-inline" data-bind="click: expandingContainersModel.expandCollapse($, visible: expandingContainersModel.isExpanded($">
  <i class="fa fa-arrow-circle-down"></i>
    <!-- ko template: { name: 'LabelTemplate' } -->
    <!-- /ko -->
  <div class="label-inline" data-bind="click: expandingContainersModel.expandCollapse($, visible: !expandingContainersModel.isExpanded($">
  <i class="fa fa-arrow-circle-right"></i>
    <!-- ko template: { name: 'LabelTemplate' } -->
    <!-- /ko -->

This code adds expand/collapse icons next to the container label and binds container label to the collapse/expand action. You can modify code if you want to position arrows differently or exclude label click bindings.

3. Locate the script template with id ContainerTemplate and surround it with this div:

<div data-bind="visible: expandingContainersModel.isExpanded($"></div>

This part of code will hide/show the container body based on your previous action (whether you clicked to expand or to collapse the container).

4. Click Save

To see expand/collapse feature in action, go to SAP CPQ configurator and configure the product that has containers. You will notice that container expand/collapse state is preserved even if you move from one tab to another. See next figures for the demonstration.

Figure 3 - All containers collapsed

Figure 4 - Container “My Second Container” is expanded

Figure 5 - We switched to the “Type” tab

Figure 6 - Switched back to the “Content” tab. State is preserved

Hidden container columns available in Knockout context in Responsive Design

Any container column can be set to be hidden. This is usually done when an administrator wants to store some information to be used in calculations but at the same time doesn’t want to display it to the end user.

Prior to Responsive Design, administrators were able to access this information through Iron Python scripting but in Responsive Design, due to the optimization of http requests, this information is not served in the server’s response. The result is that administrators are not able to access these pieces of information to include it in any kind of data manipulation or in calculations.

This feature now allows access to information in hidden container columns in Responsive Design.


This example assumes that a product with one container attribute has already been defined. This attribute, beside standard columns, contains one hidden column named hdn column (See Figure 1)

Figure 1 - Hidden column in container

By default, this column is not served through server response (json file), therefore it is not available in the knockout context. (See Figure 2)

Figure 2 - Hidden columns and their values are not available in knockout context

To make data from this column available in the knockout context, go to the attribute setup page - Setup > Product Catalog > Attributes find the attribute and edit it. (See Figure 3)

Figure 3 - Locate and edit container attribute

Go to tab columns, and click to edit the desired column. (See Figure 4)

Figure 4 - Edit hidden column

Under the calculation formula textbox there is an option labeled Always include in KO context. You should check this option when you want to make the data from the hidden column available in knockout context. (See Figure 5)

Figure 5 - Make data available in knockout context

From now on, data is sent through json file via http response and is therefore available to the SAP CPQ administrator. (See Figure 6)

Figure 6 - hidden column’s data is now available in knockout context

Note that the hiddenColumns array contains a list of all hidden columns that were marked to be available in knockout context. All values are contained within the hiddenValues array, and for each column, three properties are available to the administrator:

  • columnId – Id of the hidden column
  • headerLabel – label of the hidden column
  • value – value of the hidden column
You are here: SAP Sales Cloud CPQ Online HelpAdmin Page HelpProduct AdministrationAttributesAttribute Container