If you have technical questions, please create a support ticket in the DevExpress Support Center.
<dx-chart
id="chart"
[dataSource]="populationData"
title="Population: Age Structure"
>
<dxi-series valueField="maleyoung" name="Male: 0-14" stack="male">
</dxi-series>
<dxi-series valueField="malemiddle" name="Male: 15-64" stack="male">
</dxi-series>
<dxi-series valueField="maleolder" name="Male: 65 and older" stack="male">
</dxi-series>
<dxi-series valueField="femaleyoung" name="Female: 0-14" stack="female">
</dxi-series>
<dxi-series valueField="femalemiddle" name="Female: 15-64" stack="female">
</dxi-series>
<dxi-series
valueField="femaleolder"
name="Female: 65 and older"
stack="female"
>
</dxi-series>
<dxo-common-series-settings argumentField="state" type="fullStackedBar">
</dxo-common-series-settings>
<dxo-legend verticalAlignment="bottom" horizontalAlignment="center">
</dxo-legend>
<dxo-export [enabled]="true"></dxo-export>
<dxo-tooltip [enabled]="true" [customizeTooltip]="customizeTooltip">
</dxo-tooltip>
</dx-chart>
xxxxxxxxxx
import { NgModule, Component, enableProdMode } from '@angular/core';
import { BrowserModule } from '@angular/platform-browser';
import { platformBrowserDynamic } from '@angular/platform-browser-dynamic';
import { DxChartModule } from 'devextreme-angular';
import { Population, Service } from './app.service';
if (!/localhost/.test(document.location.host)) {
enableProdMode();
}
let modulePrefix = '';
// @ts-ignore
if (window && window.config?.packageConfigPaths) {
modulePrefix = '/app';
}
@Component({
selector: 'demo-app',
templateUrl: `app/app.component.html`,
styleUrls: [`app/app.component.css`],
providers: [Service],
})
export class AppComponent {
populationData: Population[];
constructor(service: Service) {
this.populationData = service.getPopulationData();
}
customizeTooltip = ({ valueText, percentText }) => (
{
text: `${percentText} - ${valueText}`,
}
);
}
@NgModule({
imports: [
BrowserModule,
DxChartModule,
],
declarations: [AppComponent],
bootstrap: [AppComponent],
})
export class AppModule { }
platformBrowserDynamic().bootstrapModule(AppModule);
xxxxxxxxxx
::ng-deep #chart {
height: 440px;
}
xxxxxxxxxx
import { Injectable } from '@angular/core';
export class Population {
state: string;
maleyoung: number;
malemiddle: number;
maleolder: number;
femaleyoung: number;
femalemiddle: number;
femaleolder: number;
}
const populationData: Population[] = [{
state: 'USA',
maleyoung: 29.956,
malemiddle: 90.354,
maleolder: 14.472,
femaleyoung: 28.597,
femalemiddle: 91.827,
femaleolder: 20.362,
}, {
state: 'Brazil',
maleyoung: 25.607,
malemiddle: 55.793,
maleolder: 3.727,
femaleyoung: 24.67,
femalemiddle: 57.598,
femaleolder: 5.462,
}, {
state: 'Russia',
maleyoung: 13.493,
malemiddle: 48.983,
maleolder: 5.802,
femaleyoung: 12.971,
femalemiddle: 52.14,
femaleolder: 12.61,
}, {
state: 'Japan',
maleyoung: 9.575,
malemiddle: 43.363,
maleolder: 9.024,
femaleyoung: 9.105,
femalemiddle: 42.98,
femaleolder: 12.501,
}, {
state: 'Mexico',
maleyoung: 17.306,
malemiddle: 30.223,
maleolder: 1.927,
femaleyoung: 16.632,
femalemiddle: 31.868,
femaleolder: 2.391,
}, {
state: 'Germany',
maleyoung: 6.679,
malemiddle: 28.638,
maleolder: 5.133,
femaleyoung: 6.333,
femalemiddle: 27.693,
femaleolder: 8.318,
}, {
state: 'United Kindom',
maleyoung: 5.816,
malemiddle: 19.622,
maleolder: 3.864,
femaleyoung: 5.519,
femalemiddle: 19.228,
femaleolder: 5.459,
}];
@Injectable()
export class Service {
getPopulationData(): Population[] {
return populationData;
}
}
xxxxxxxxxx
// In real applications, you should not transpile code in the browser.
// You can see how to create your own application with Angular and DevExtreme here:
// https://js.devexpress.com/Documentation/Guide/Angular_Components/Getting_Started/Create_a_DevExtreme_Application/
const componentNames = [
'accordion',
'action-sheet',
'autocomplete',
'bar-gauge',
'box',
'bullet',
'button-group',
'button',
'calendar',
'chart',
'chat',
'check-box',
'circular-gauge',
'color-box',
'context-menu',
'data-grid',
'date-box',
'date-range-box',
'defer-rendering',
'diagram',
'draggable',
'drawer',
'drop-down-box',
'drop-down-button',
'file-manager',
'file-uploader',
'filter-builder',
'form',
'funnel',
'gallery',
'gantt',
'html-editor',
'linear-gauge',
'list',
'load-indicator',
'load-panel',
'lookup',
'map',
'menu',
'multi-view',
'nested',
'number-box',
'pagination',
'pie-chart',
'pivot-grid-field-chooser',
'pivot-grid',
'polar-chart',
'popover',
'popup',
'progress-bar',
'radio-group',
'range-selector',
'range-slider',
'recurrence-editor',
'resizable',
'responsive-box',
'sankey',
'scheduler',
'scroll-view',
'select-box',
'slider',
'sortable',
'sparkline',
'speed-dial-action',
'splitter',
'switch',
'tab-panel',
'tabs',
'tag-box',
'text-area',
'text-box',
'tile-view',
'toast',
'toolbar',
'tooltip',
'tree-list',
'tree-map',
'tree-view',
'validation-group',
'validation-summary',
'validator',
'vector-map',
];
window.exports = window.exports || {};
window.config = {
transpiler: 'ts',
typescriptOptions: {
module: 'system',
emitDecoratorMetadata: true,
experimentalDecorators: true,
},
meta: {
'typescript': {
'exports': 'ts',
},
'devextreme/time_zone_utils.js': {
'esModule': true,
},
'devextreme/localization.js': {
'esModule': true,
},
'devextreme/viz/palette.js': {
'esModule': true,
},
'@angular/platform-browser-dynamic': {
'esModule': true,
},
'@angular/platform-browser': {
'esModule': true,
},
'@angular/core': {
'esModule': true,
},
'@angular/common': {
'esModule': true,
},
'@angular/common/http': {
'esModule': true,
},
'@angular/animations': {
'esModule': true,
},
'@angular/forms': {
'esModule': true,
},
'openai': {
'esModule': true,
},
},
paths: {
'npm:': 'https://unpkg.com/',
'bundles:': 'bundles/',
'externals:': 'bundles/externals/',
},
map: {
'ts': 'npm:plugin-typescript@8.0.0/lib/plugin.js',
'typescript': 'npm:typescript@4.2.4/lib/typescript.js',
'jszip': 'npm:jszip@3.10.1/dist/jszip.min.js',
/* @angular */
'@angular/compiler': 'bundles:@angular/compiler.umd.js',
'@angular/platform-browser-dynamic': 'bundles:@angular/platform-browser-dynamic.umd.js',
'@angular/core': 'bundles:@angular/core.umd.js',
'@angular/core/primitives/signals': 'bundles:@angular/core.primitives.signals.umd.js',
'@angular/common': 'bundles:@angular/common.umd.js',
'@angular/common/http': 'bundles:@angular/common-http.umd.js',
'@angular/platform-browser': 'bundles:@angular/platform-browser.umd.js',
'@angular/platform-browser/animations': 'bundles:@angular/platform-browser.umd.js',
'@angular/forms': 'bundles:@angular/forms.umd.js',
/* devextreme */
'devextreme': 'npm:devextreme@24.2.5/cjs',
'@devextreme/runtime': 'npm:@devextreme/runtime@3.0.12',
'devextreme/bundles/dx.all': 'npm:devextreme@24.2.5/bundles/dx.all.js',
'devextreme-quill': 'npm:devextreme-quill@1.7.1/dist/dx-quill.min.js',
'devexpress-diagram': 'npm:devexpress-diagram@2.2.5',
'devexpress-gantt': 'npm:devexpress-gantt@4.1.54',
/* devextreme-angular umd maps */
'devextreme-angular': 'bundles:devextreme-angular/devextreme-angular.umd.js',
'devextreme-angular/core': 'bundles:devextreme-angular/devextreme-angular-core.umd.js',
'devextreme-angular/http': 'bundles:devextreme-angular/devextreme-angular-http.umd.js',
componentNames.reduce((acc, name) => {
acc[`devextreme-angular/ui/${name}`] = `bundles:devextreme-angular/devextreme-angular-ui-${name}.umd.js`;
acc[`devextreme-angular/ui/${name}/nested`] = `bundles:devextreme-angular/devextreme-angular-ui-${name}-nested.umd.js`;
return acc;
}, {}),
'tslib': 'npm:tslib/tslib.js',
'rxjs': 'npm:rxjs@7.5.3/dist/bundles/rxjs.umd.js',
'rxjs/operators': 'npm:rxjs@7.5.3/dist/cjs/operators/index.js',
'rrule': 'npm:rrule@2.6.4/dist/es5/rrule.js',
'luxon': 'npm:luxon@3.4.4/build/global/luxon.min.js',
'es6-object-assign': 'npm:es6-object-assign',
'inferno': 'npm:inferno@7.4.11/dist/inferno.min.js',
'inferno-compat': 'npm:inferno-compat/dist/inferno-compat.min.js',
'inferno-create-element': 'npm:inferno-create-element@7.4.11/dist/inferno-create-element.min.js',
'inferno-dom': 'npm:inferno-dom/dist/inferno-dom.min.js',
'inferno-hydrate': 'npm:inferno-hydrate/dist/inferno-hydrate.min.js',
'inferno-clone-vnode': 'npm:inferno-clone-vnode/dist/inferno-clone-vnode.min.js',
'inferno-create-class': 'npm:inferno-create-class/dist/inferno-create-class.min.js',
'inferno-extras': 'npm:inferno-extras/dist/inferno-extras.min.js',
// Prettier
'prettier/standalone': 'npm:prettier@2.8.8/standalone.js',
'prettier/parser-html': 'npm:prettier@2.8.8/parser-html.js',
},
packages: {
'app': {
main: './app.component.ts',
defaultExtension: 'ts',
},
'devextreme': {
defaultExtension: 'js',
},
'devextreme/events/utils': {
main: 'index',
},
'devextreme/events': {
main: 'index',
},
'es6-object-assign': {
main: './index.js',
defaultExtension: 'js',
},
'rxjs': {
defaultExtension: 'js',
},
'rxjs/operators': {
defaultExtension: 'js',
},
},
packageConfigPaths: [
'npm:@devextreme/*/package.json',
'npm:@devextreme/runtime@3.0.12/inferno/package.json',
'npm:rxjs@7.5.3/package.json',
'npm:rxjs@7.5.3/operators/package.json',
'npm:devexpress-diagram@2.2.5/package.json',
'npm:devexpress-gantt@4.1.54/package.json',
],
};
System.config(window.config);
// System.import('@angular/compiler').catch(console.error.bind(console));
xxxxxxxxxx
<html xmlns="http://www.w3.org/1999/xhtml" lang="en">
<head></head>
<body class="dx-viewport">
<div class="demo-container">
<demo-app>Loading...</demo-app>
</div>
</body>
</html>
Bind Chart to Data
The side-by-side full-stacked bar chart contains series with the same argument field. In this demo, the data source array consists of objects with the same field structure. Assign the state
field to the argumentField property of the commonSeriesSettings object to specify the common argument for the series. Then, define the series array of objects. In each object, specify the valueField property and use the stack property to group the series in stacks depending on the stack property values.
Customize Side-By-Side Stacked Bar Chart
Customize Chart Legend
Use the verticalAlignment and horizontalAlignment properties of the legend object to specify the legend layout.
Configure Tooltips
To configure tooltips in the chart, use the tooltip object. To enable tooltips, assign true to the enabled property of this object. To customize a tooltip, assign a function to the customizeTooltip property. In this demo, the function returns the tooltip's text that shows the point's percent value and absolute value.
Export Chart
To allow users to export your side-by-side full-stacked bar chart into a PNG, JPEG, PDF, or SVG file, or print the chart, set the export.enabled property to true. Since the export functionality is enabled in this demo, you can click the hamburger button in the chart to invoke a drop-down menu with export and print commands.