diff --git a/_data/components/data-view.yml b/_data/components/data-view.yml
new file mode 100644
index 000000000..16be5d074
--- /dev/null
+++ b/_data/components/data-view.yml
@@ -0,0 +1,110 @@
+directive: "o-data-view"
+version: "15.0.0"
+
+apiTitle: "ODataViewComponent"
+inheritedAttributes:
+ [
+ {
+ component: "OServiceBaseComponent",
+ path: "components/service/service-base/api",
+ attributes:
+ [
+ "attr",
+ "columns",
+ "configure-service-args",
+ "delete-method",
+ "entity",
+ "insert-method",
+ "keys",
+ "pageable",
+ "paginated-query-method",
+ "parent-keys",
+ "query-fallback-function",
+ "query-method",
+ "query-on-bind",
+ "query-on-init",
+ "query-rows",
+ "query-with-null-parent-keys",
+ "service",
+ "service-type",
+ "static-data",
+ "store-state",
+ "update-method",
+ "show-buttons-text",
+ "quick-filter-placeholder",
+ "insert-button",
+ "refresh-button",
+ "fixed-header",
+ "controls",
+ "title",
+ "quick-filter",
+ "quick-filter-appearance",
+ "recursive-detail",
+ "recursive-edit",
+ "recursive-insert",
+ "detail-form-route",
+ "pagination-controls",
+ "insert-form-route",
+ "filter-case-sensitive",
+ ],
+ },
+ ]
+
+attributes:
+ [
+ {
+ name: "default-view",
+ type: "'table' | 'grid'",
+ default: "table",
+ required: "",
+ description: "Default view rendered by the component.",
+ },
+ {
+ name: "toggle-button",
+ type: "no | false | yes | true",
+ default: "yes",
+ required: "",
+ description: "Indicates whether or not to show the built-in view toggle. By default it is enabled, which is the standard way `o-data-view` provides view switching.",
+ },
+ {
+ name: "toggle-on-toolbar",
+ type: "no | false | yes | true",
+ default: "no",
+ required: "",
+ description: "Indicates whether or not to render the view toggle inside the toolbar.",
+ },
+ {
+ name: "toggle-floatable",
+ type: "no | false | yes | true",
+ default: "no",
+ required: "",
+ description: "Indicates whether or not the view toggle is rendered as a floating control.",
+ },
+ {
+ name: "table-config",
+ type: "TableConfig",
+ default: "",
+ required: "",
+ description: "Table view configuration object. Values defined here have precedence over the global table configuration injection token and the component defaults.",
+ },
+ {
+ name: "grid-config",
+ type: "GridConfig",
+ default: "",
+ required: "",
+ description: "Grid view configuration object.",
+ },
+ {
+ name: "delete-button",
+ type: "no | false | yes | true",
+ default: "yes",
+ required: "",
+ description: "Indicates whether or not to show a button for deleting data",
+ },
+ { name: "insert-button" },
+ { name: "refresh-button" },
+ ]
+
+extraComponents: "dataViewData"
+
+directives: [{ name: "oDataViewTableColumns" }, { name: "oDataViewGridItem" }]
diff --git a/_data/components/dataViewData/types/grid-config.yml b/_data/components/dataViewData/types/grid-config.yml
new file mode 100644
index 000000000..ef413f7b2
--- /dev/null
+++ b/_data/components/dataViewData/types/grid-config.yml
@@ -0,0 +1,52 @@
+type: "GridConfig"
+
+description: "Represents the configuration object used by o-data-view to customize the embedded o-grid view.
+All options are equivalent to the o-grid inputs, so you can consult its API to understand the meaning of each property.
+
+type GridConfig = {
+ enabled?: CustomBoolean;
+ visible?: CustomBoolean;
+ cols?: number;
+ gridItemHeight?: string | number;
+ gutterSize?: string;
+ insertButtonFloatable?: CustomBoolean;
+ insertButtonPosition?: 'botton' | 'top';
+ pageSizeOptions?: any[];
+ orderable?: CustomBoolean;
+ quickFilterColumns?: string;
+ showFooter?: CustomBoolean;
+ showPageSize?: CustomBoolean;
+ sortColumn?: string;
+ sortableColumns?: string;
+ detailMode?: 'none' | 'click' | 'dblclick';
+};
+
+"
+
+propertiesColumns: ["Name", "Type", "Description"]
+
+attributes:
+ [
+ { name: "enabled", type: "'yes' | 'no' | 'true' | 'false'", optional: true },
+ { name: "visible", type: "'yes' | 'no' | 'true' | 'false'", optional: true },
+
+ { name: "cols", type: "number", optional: true },
+ { name: "gridItemHeight", type: "string | number", optional: true },
+ { name: "gutterSize", type: "string", optional: true },
+
+ { name: "insertButtonFloatable", type: "'yes' | 'no' | 'true' | 'false'", optional: true },
+ { name: "insertButtonPosition", type: "'botton' | 'top'", optional: true },
+
+ { name: "pageSizeOptions", type: "any[]", optional: true },
+ { name: "orderable", type: "'yes' | 'no' | 'true' | 'false'", optional: true },
+
+ { name: "quickFilterColumns", type: "string", optional: true },
+
+ { name: "showFooter", type: "'yes' | 'no' | 'true' | 'false'", optional: true },
+ { name: "showPageSize", type: "'yes' | 'no' | 'true' | 'false'", optional: true },
+
+ { name: "sortColumn", type: "string", optional: true },
+ { name: "sortableColumns", type: "string", optional: true },
+
+ { name: "detailMode", type: "'none' | 'click' | 'dblclick'", optional: true }
+ ]
\ No newline at end of file
diff --git a/_data/components/dataViewData/types/table-config.yml b/_data/components/dataViewData/types/table-config.yml
new file mode 100644
index 000000000..2f5899102
--- /dev/null
+++ b/_data/components/dataViewData/types/table-config.yml
@@ -0,0 +1,137 @@
+type: "TableConfig"
+
+description: "Represents the configuration object used by o-data-view to customize the embedded o-table view.
+All options are equivalent to the o-table inputs, so you can consult its API to understand the meaning of each property.
+
+type TableConfig = {
+ visible?: CustomBoolean;
+ detailButtonInRow?: CustomBoolean;
+ detailButtonInRowIcon?: string;
+ editButtonInRow?: CustomBoolean;
+ editButtonInRowIcon?: string;
+ editFormRoute?: string;
+ rowHeight?: 'small' | 'medium' | 'large';
+ autoAdjust?: CustomBoolean;
+ autoAlignTitles?: CustomBoolean;
+ collapseGroupedColumns?: CustomBoolean;
+ columnsVisibilityButton?: CustomBoolean;
+ defaultVisibleColumns?: string;
+ disableSelectionFunction?: (item: any) => boolean;
+ detailMode?: 'none' | 'click' | 'dblclick';
+ editionMode?: 'none' | 'click' | 'dblclick';
+ enabled?: CustomBoolean;
+ exportButton?: CustomBoolean;
+ exportServiceType?: string;
+ filterColumnActiveByDefault?: CustomBoolean;
+ groupable?: CustomBoolean;
+ groupedColumns?: string;
+ horizontalScroll?: CustomBoolean;
+ keepSelectedItems?: CustomBoolean;
+ multipleSort?: CustomBoolean;
+ nonHidableColumns?: string;
+ pageSizeOptions?: any[];
+ orderable?: CustomBoolean;
+ quickFilterFunction?: QuickFilterFunction;
+ resizable?: CustomBoolean;
+ rowClass?: (rowData: any, rowIndex: number) => string | string[];
+ selectAllCheckbox?: CustomBoolean;
+ selectAllCheckboxVisible?: CustomBoolean;
+ selectionMode?: 'none' | 'single' | 'multiple';
+ showConfigurationOption?: CustomBoolean;
+ showExpandableIconFunction?: Function;
+ showFilterOption?: CustomBoolean;
+ showPaginatorFirstLastButtons?: CustomBoolean;
+ showReportOnDemandOption?: CustomBoolean;
+ showChartsOnDemandOption?: CustomBoolean;
+ showResetWidthOption?: CustomBoolean;
+ sortColumns?: string;
+ virtualScroll?: CustomBoolean;
+ visibleColumns?: string;
+ visibleExportDialogButtons?: string;
+ selectionOnRowClick?: CustomBoolean;
+};
+
+"
+
+propertiesColumns: ["Name", "Type", "Description"]
+
+attributes:
+ [
+ { name: "visible", type: "'yes' | 'no' | 'true' | 'false'", optional: true },
+ { name: "detailButtonInRow", type: "'yes' | 'no' | 'true' | 'false'", optional: true },
+ { name: "detailButtonInRowIcon", type: "string", optional: true },
+ { name: "editButtonInRow", type: "'yes' | 'no' | 'true' | 'false'", optional: true },
+ { name: "editButtonInRowIcon", type: "string", optional: true },
+ { name: "editFormRoute", type: "string", optional: true },
+ { name: "rowHeight", type: "'small' | 'medium' | 'large'", optional: true },
+ { name: "autoAdjust", type: "'yes' | 'no' | 'true' | 'false'", optional: true },
+ { name: "autoAlignTitles", type: "'yes' | 'no' | 'true' | 'false'", optional: true },
+ { name: "collapseGroupedColumns", type: "'yes' | 'no' | 'true' | 'false'", optional: true },
+ { name: "columnsVisibilityButton", type: "'yes' | 'no' | 'true' | 'false'", optional: true },
+ { name: "defaultVisibleColumns", type: "string", optional: true },
+ {
+ name: "disableSelectionFunction",
+ type: "(item: any) => boolean",
+ optional: true,
+ },
+ {
+ name: "detailMode",
+ type: "'none' | 'click' | 'dblclick'",
+ optional: true,
+ },
+ {
+ name: "editionMode",
+ type: "'none' | 'click' | 'dblclick'",
+ optional: true,
+ },
+ { name: "enabled", type: "'yes' | 'no' | 'true' | 'false'", optional: true },
+ { name: "exportButton", type: "'yes' | 'no' | 'true' | 'false'", optional: true },
+ { name: "exportServiceType", type: "string", optional: true },
+ {
+ name: "filterColumnActiveByDefault",
+ type: "'yes' | 'no' | 'true' | 'false'",
+ optional: true,
+ },
+ { name: "groupable", type: "'yes' | 'no' | 'true' | 'false'", optional: true },
+ { name: "groupedColumns", type: "string", optional: true },
+ { name: "horizontalScroll", type: "'yes' | 'no' | 'true' | 'false'", optional: true },
+ { name: "keepSelectedItems", type: "'yes' | 'no' | 'true' | 'false'", optional: true },
+ { name: "multipleSort", type: "'yes' | 'no' | 'true' | 'false'", optional: true },
+ { name: "nonHidableColumns", type: "string", optional: true },
+ { name: "pageSizeOptions", type: "any[]", optional: true },
+ { name: "orderable", type: "'yes' | 'no' | 'true' | 'false'", optional: true },
+ {
+ name: "quickFilterFunction",
+ type: "QuickFilterFunction",
+ optional: true,
+ },
+ { name: "resizable", type: "'yes' | 'no' | 'true' | 'false'", optional: true },
+ {
+ name: "rowClass",
+ type: "(rowData: any, rowIndex: number) => string | string[]",
+ optional: true,
+ },
+ { name: "selectAllCheckbox", type: "'yes' | 'no' | 'true' | 'false'", optional: true },
+ { name: "selectAllCheckboxVisible", type: "'yes' | 'no' | 'true' | 'false'", optional: true },
+ {
+ name: "selectionMode",
+ type: "'none' | 'single' | 'multiple'",
+ optional: true,
+ },
+ { name: "showConfigurationOption", type: "'yes' | 'no' | 'true' | 'false'", optional: true },
+ { name: "showExpandableIconFunction", type: "Function", optional: true },
+ { name: "showFilterOption", type: "'yes' | 'no' | 'true' | 'false'", optional: true },
+ {
+ name: "showPaginatorFirstLastButtons",
+ type: "'yes' | 'no' | 'true' | 'false'",
+ optional: true,
+ },
+ { name: "showReportOnDemandOption", type: "'yes' | 'no' | 'true' | 'false'", optional: true },
+ { name: "showChartsOnDemandOption", type: "'yes' | 'no' | 'true' | 'false'", optional: true },
+ { name: "showResetWidthOption", type: "'yes' | 'no' | 'true' | 'false'", optional: true },
+ { name: "sortColumns", type: "string", optional: true },
+ { name: "virtualScroll", type: "'yes' | 'no' | 'true' | 'false'", optional: true },
+ { name: "visibleColumns", type: "string", optional: true },
+ { name: "visibleExportDialogButtons", type: "string", optional: true },
+ { name: "selectionOnRowClick", type: "'yes' | 'no' | 'true' | 'false'", optional: true }
+ ]
diff --git a/_data/menu_descriptions.yml b/_data/menu_descriptions.yml
index edbf9d29e..1b238928d 100644
--- a/_data/menu_descriptions.yml
+++ b/_data/menu_descriptions.yml
@@ -425,4 +425,10 @@ sections:
- url: "/guide/service/ontimize"
title: "Ontimize"
imagepath: "/assets/images/menus/services/ontimize"
-
+ "extra-components":
+ - url: "/extra-components/installation"
+ title: "Installation"
+ description: "How to install the ontimize-web-ngx-extra-components addon"
+ - url: "/extra-components/data-view/overview"
+ title: "Data View"
+ description: "Display the same dataset using two different visualizations"
diff --git a/_includes/o-component-single-api.md b/_includes/o-component-single-api.md
index dabf5d3d2..01850cee9 100644
--- a/_includes/o-component-single-api.md
+++ b/_includes/o-component-single-api.md
@@ -178,7 +178,15 @@
{% endif %}
-
+ {% if componentData.directives %}
+ Directives
+
+ {% assign sortedDirectives = (componentData.directives | sort: 'name') %}
+ {% for d in sortedDirectives %}
+ - {{ d.name }}
+ {% endfor %}
+
+ {% endif %}
{% if componentData.inheritedOutputs %}
Inherited outputs
@@ -260,3 +268,16 @@
{% endif %}
{% endif %}
+
+{% assign typesFolder = componentData.types %}
+
+{% if componentData.extraComponents %}
+ {% assign extraKey = componentData.extraComponents %}
+ {% assign typesFolder = site.data.components[extraKey].types | default: typesFolder %}
+{% endif %}
+
+{% if typesFolder and typesFolder.size > 0 %}
+
+ {% include functions/o-table/type-api.html folder=typesFolder %}
+
+{% endif %}
\ No newline at end of file
diff --git a/_includes/o-component-single.md b/_includes/o-component-single.md
index 17f704b75..2fbc2594c 100644
--- a/_includes/o-component-single.md
+++ b/_includes/o-component-single.md
@@ -137,12 +137,18 @@
{% endfor %}
{% assign filenameArray = filenameArray | sort %}
{% for filename in filenameArray %}
- {% assign dataFile = site.data.components[extraComp][filename] %}
- {% capture dataFileCapture %}
- {% include o-component-single-api.md component=dataFile extra=true %}
- {% endcapture %}
-
- {{ dataFileCapture | replace: ' ', '' }}
+ {% if filename != 'types' %}
+ {% assign dataFile = site.data.components[extraComp][filename] %}
+
+ {%- comment -%} render only "file-like" entries {%- endcomment -%}
+ {% if dataFile.directive or dataFile.class or dataFile.apiTitle or dataFile.title %}
+ {% capture dataFileCapture %}
+ {% include o-component-single-api.md component=dataFile extra=true %}
+ {% endcapture %}
+
+ {{ dataFileCapture | replace: ' ', '' }}
+ {% endif %}
+ {% endif %}
{% endfor %}
{% endif %}
diff --git a/assets/images/extra-components/data-view/data-view-example.gif b/assets/images/extra-components/data-view/data-view-example.gif
new file mode 100644
index 000000000..a1e440239
Binary files /dev/null and b/assets/images/extra-components/data-view/data-view-example.gif differ
diff --git a/assets/images/menus/data/data-view.svg b/assets/images/menus/data/data-view.svg
new file mode 100644
index 000000000..6d057209c
--- /dev/null
+++ b/assets/images/menus/data/data-view.svg
@@ -0,0 +1,16 @@
+
diff --git a/assets/images/menus/data/data-view_dark.svg b/assets/images/menus/data/data-view_dark.svg
new file mode 100644
index 000000000..5b71cd4bf
--- /dev/null
+++ b/assets/images/menus/data/data-view_dark.svg
@@ -0,0 +1,16 @@
+
diff --git a/assets/images/menus/data/tree.svg b/assets/images/menus/data/tree.svg
index 0033ea51c..56d6bfb7d 100644
--- a/assets/images/menus/data/tree.svg
+++ b/assets/images/menus/data/tree.svg
@@ -1,5 +1,12 @@
-