Skip to content

Commit 321bf89

Browse files
TagBox Overview Demo: Add tagTemplate and Popover (#2658) (#2685)
* TagBox Overview Demo: Add tagTemplate and Popover * Add Vue * fix image path to repair local run * Remove !important * Fix lint * Add etalon * Add Tag.js * Add aria-disabled to disabled tags --------- Co-authored-by: EugeniyKiyashko <[email protected]>
1 parent 7c04361 commit 321bf89

File tree

18 files changed

+471
-49
lines changed

18 files changed

+471
-49
lines changed

JSDemos/Demos/TagBox/Overview/Angular/app/app.component.css

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -31,3 +31,19 @@ body .dx-popup-content .custom-item {
3131
text-overflow: ellipsis;
3232
overflow: hidden;
3333
}
34+
35+
::ng-deep .dx-tag-content {
36+
display: flex;
37+
align-items: center;
38+
}
39+
40+
::ng-deep .tag-img {
41+
height: 30px;
42+
margin-right: 5px;
43+
}
44+
45+
::ng-deep .dx-tag-content.disabled-tag {
46+
padding-right: 6px;
47+
opacity: 0.5;
48+
cursor: not-allowed;
49+
}

JSDemos/Demos/TagBox/Overview/Angular/app/app.component.html

Lines changed: 36 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -106,9 +106,11 @@
106106
<div class="dx-field-value">
107107
<dx-tag-box
108108
[dataSource]="dataSource"
109+
[value]="value"
109110
displayExpr="Name"
110111
valueExpr="Id"
111112
itemTemplate="customItem"
113+
tagTemplate="customTag"
112114
[inputAttr]="{ 'aria-label': 'Product' }"
113115
>
114116
<div *dxTemplate="let product of 'customItem'">
@@ -119,7 +121,41 @@
119121
</div>
120122
</div>
121123
</div>
124+
<div *dxTemplate="let product of 'customTag'">
125+
<div
126+
[ngClass]="{
127+
'dx-tag-content': true,
128+
'disabled-tag': isDisabled(product)
129+
}"
130+
[attr.aria-disabled]="isDisabled(product)"
131+
(mouseenter)="onMouseEnter($event, product)"
132+
(mouseleave)="onMouseLeave()"
133+
>
134+
<img [src]="product.ImageSrc" class="tag-img" />
135+
<span>{{ product.Name }}</span>
136+
<div
137+
*ngIf="!isDisabled(product)"
138+
class="dx-tag-remove-button"
139+
></div>
140+
</div>
141+
</div>
122142
</dx-tag-box>
143+
<dx-popover [target]="target" [visible]="visible">
144+
<div *dxTemplate="let data of 'content'">
145+
<p>
146+
<b>Name: </b><span>{{ product.Name }}</span>
147+
</p>
148+
<p>
149+
<b>Price: </b><span>{{ product.Price }}</span>
150+
</p>
151+
<p>
152+
<b>In-stock: </b><span>{{ product.Current_Inventory }}</span>
153+
</p>
154+
<p>
155+
<b>Category: </b><span>{{ product.Category }}</span>
156+
</p>
157+
</div>
158+
</dx-popover>
123159
</div>
124160
</div>
125161
</div>

JSDemos/Demos/TagBox/Overview/Angular/app/app.component.ts

Lines changed: 26 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
import { Component, NgModule, enableProdMode } from '@angular/core';
22
import { BrowserModule, BrowserTransferStateModule } from '@angular/platform-browser';
33
import { platformBrowserDynamic } from '@angular/platform-browser-dynamic';
4-
import { DxTagBoxModule, DxTemplateModule } from 'devextreme-angular';
4+
import { DxTagBoxModule, DxPopoverModule, DxTemplateModule } from 'devextreme-angular';
55
import ArrayStore from 'devextreme/data/array_store';
66

77
import { Service, Product } from './app.service';
@@ -24,13 +24,22 @@ export class AppComponent {
2424

2525
dataSource: any;
2626

27+
product: Product;
28+
29+
value: number[];
30+
31+
target: any;
32+
33+
visible = false;
34+
2735
constructor(service: Service) {
2836
this.dataSource = new ArrayStore({
2937
data: service.getProducts(),
3038
key: 'Id',
3139
});
3240
this.simpleProducts = service.getSimpleProducts();
3341
this.editableProducts = this.simpleProducts.slice();
42+
this.value = [1, 2];
3443
}
3544

3645
onCustomItemCreating(args) {
@@ -41,6 +50,21 @@ export class AppComponent {
4150
}
4251
args.customItem = newValue;
4352
}
53+
54+
onMouseEnter(e, product) {
55+
this.target = e.target;
56+
this.product = product;
57+
this.visible = true;
58+
}
59+
60+
onMouseLeave() {
61+
this.target = null;
62+
this.visible = false;
63+
}
64+
65+
isDisabled(product) {
66+
return product.Name === 'SuperHD Video Player';
67+
}
4468
}
4569

4670
@NgModule({
@@ -49,6 +73,7 @@ export class AppComponent {
4973
BrowserTransferStateModule,
5074
DxTemplateModule,
5175
DxTagBoxModule,
76+
DxPopoverModule,
5277
],
5378
declarations: [AppComponent],
5479
bootstrap: [AppComponent],

JSDemos/Demos/TagBox/Overview/React/App.js

Lines changed: 35 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,11 @@
11
import React from 'react';
22

33
import TagBox from 'devextreme-react/tag-box';
4+
import Popover from 'devextreme-react/popover';
45
import ArrayStore from 'devextreme/data/array_store';
56

67
import Item from './Item.js';
8+
import Tag from './Tag.js';
79
import { simpleProducts, products, productLabel } from './data.js';
810

911
const disabledValue = [simpleProducts[0]];
@@ -17,8 +19,12 @@ class App extends React.Component {
1719
});
1820
this.state = {
1921
editableProducts: [...simpleProducts],
22+
value: [1, 2],
23+
target: null,
24+
product: {},
2025
};
2126
this.onCustomItemCreating = this.onCustomItemCreating.bind(this);
27+
this.onMouseEnter = this.onMouseEnter.bind(this);
2228
}
2329

2430
onCustomItemCreating(args) {
@@ -32,6 +38,13 @@ class App extends React.Component {
3238
args.customItem = newValue;
3339
}
3440

41+
onMouseEnter(e, product) {
42+
this.setState({
43+
target: e.currentTarget,
44+
product,
45+
});
46+
}
47+
3548
render() {
3649
return (
3750
<React.Fragment>
@@ -115,10 +128,31 @@ class App extends React.Component {
115128
<div className="dx-field-label">Custom template</div>
116129
<div className="dx-field-value">
117130
<TagBox dataSource={this.dataSource}
131+
defaultValue={this.state.value}
118132
inputAttr={productLabel}
119133
displayExpr="Name"
120134
valueExpr="Id"
121-
itemRender={Item} />
135+
itemRender={Item}
136+
tagRender={(data) => <Tag product={data} onMouseEnter={this.onMouseEnter} />} />
137+
138+
<Popover
139+
showEvent="mouseenter"
140+
hideEvent="mouseleave"
141+
target={this.state.target}
142+
>
143+
<p>
144+
<b>Name: </b><span>{ this.state.product.Name }</span>
145+
</p>
146+
<p>
147+
<b>Price: </b><span>{ this.state.product.Price }</span>
148+
</p>
149+
<p>
150+
<b>In-stock: </b><span>{ this.state.product.Current_Inventory }</span>
151+
</p>
152+
<p>
153+
<b>Category: </b><span>{ this.state.product.Category }</span>
154+
</p>
155+
</Popover>
122156
</div>
123157
</div>
124158
</div>
Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,19 @@
1+
import React from 'react';
2+
3+
export default function Tag({ product, onMouseEnter }) {
4+
const isDisabled = product.Name === 'SuperHD Video Player';
5+
return (
6+
<React.Fragment>
7+
<div
8+
className={`dx-tag-content ${isDisabled && 'disabled-tag'}`}
9+
onMouseEnter={(e) => onMouseEnter(e, product)}
10+
aria-disabled={isDisabled}
11+
>
12+
<img src={product.ImageSrc} className="tag-img" />
13+
<span>{product.Name}</span>
14+
{!isDisabled && <div className="dx-tag-remove-button"></div>}
15+
</div>
16+
17+
</React.Fragment>
18+
);
19+
}

JSDemos/Demos/TagBox/Overview/React/data.js

Lines changed: 18 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -23,7 +23,7 @@ export const products = [{
2323
Backorder: 0,
2424
Manufacturing: 10,
2525
Category: 'Video Players',
26-
ImageSrc: 'images/products/1.png',
26+
ImageSrc: '../../../../images/products/1.png',
2727
}, {
2828
Id: 2,
2929
Name: 'SuperHD Video Player',
@@ -32,7 +32,7 @@ export const products = [{
3232
Backorder: 0,
3333
Manufacturing: 25,
3434
Category: 'Video Players',
35-
ImageSrc: 'images/products/2.png',
35+
ImageSrc: '../../../../images/products/2.png',
3636
}, {
3737
Id: 3,
3838
Name: 'SuperPlasma 50',
@@ -41,7 +41,7 @@ export const products = [{
4141
Backorder: 0,
4242
Manufacturing: 0,
4343
Category: 'Televisions',
44-
ImageSrc: 'images/products/3.png',
44+
ImageSrc: '../../../../images/products/3.png',
4545
}, {
4646
Id: 4,
4747
Name: 'SuperLED 50',
@@ -50,7 +50,7 @@ export const products = [{
5050
Backorder: 0,
5151
Manufacturing: 55,
5252
Category: 'Televisions',
53-
ImageSrc: 'images/products/4.png',
53+
ImageSrc: '../../../../images/products/4.png',
5454
}, {
5555
Id: 5,
5656
Name: 'SuperLED 42',
@@ -59,7 +59,7 @@ export const products = [{
5959
Backorder: 0,
6060
Manufacturing: 0,
6161
Category: 'Televisions',
62-
ImageSrc: 'images/products/5.png',
62+
ImageSrc: '../../../../images/products/5.png',
6363
}, {
6464
Id: 6,
6565
Name: 'SuperLCD 55',
@@ -68,7 +68,7 @@ export const products = [{
6868
Backorder: 0,
6969
Manufacturing: 5,
7070
Category: 'Televisions',
71-
ImageSrc: 'images/products/6.png',
71+
ImageSrc: '../../../../images/products/6.png',
7272
}, {
7373
Id: 7,
7474
Name: 'SuperLCD 42',
@@ -77,7 +77,7 @@ export const products = [{
7777
Backorder: 0,
7878
Manufacturing: 20,
7979
Category: 'Televisions',
80-
ImageSrc: 'images/products/7.png',
80+
ImageSrc: '../../../../images/products/7.png',
8181
}, {
8282
Id: 8,
8383
Name: 'SuperPlasma 65',
@@ -86,7 +86,7 @@ export const products = [{
8686
Backorder: 0,
8787
Manufacturing: 0,
8888
Category: 'Televisions',
89-
ImageSrc: 'images/products/8.png',
89+
ImageSrc: '../../../../images/products/8.png',
9090
}, {
9191
Id: 9,
9292
Name: 'SuperLCD 70',
@@ -95,7 +95,7 @@ export const products = [{
9595
Backorder: 0,
9696
Manufacturing: 5,
9797
Category: 'Televisions',
98-
ImageSrc: 'images/products/9.png',
98+
ImageSrc: '../../../../images/products/9.png',
9999
}, {
100100
Id: 10,
101101
Name: 'DesktopLED 21',
@@ -104,7 +104,7 @@ export const products = [{
104104
Backorder: 425,
105105
Manufacturing: 75,
106106
Category: 'Monitors',
107-
ImageSrc: 'images/products/10.png',
107+
ImageSrc: '../../../../images/products/10.png',
108108
}, {
109109
Id: 12,
110110
Name: 'DesktopLCD 21',
@@ -113,7 +113,7 @@ export const products = [{
113113
Backorder: 0,
114114
Manufacturing: 60,
115115
Category: 'Monitors',
116-
ImageSrc: 'images/products/12.png',
116+
ImageSrc: '../../../../images/products/12.png',
117117
}, {
118118
Id: 13,
119119
Name: 'DesktopLCD 19',
@@ -122,7 +122,7 @@ export const products = [{
122122
Backorder: 0,
123123
Manufacturing: 210,
124124
Category: 'Monitors',
125-
ImageSrc: 'images/products/13.png',
125+
ImageSrc: '../../../../images/products/13.png',
126126
}, {
127127
Id: 14,
128128
Name: 'Projector Plus',
@@ -131,7 +131,7 @@ export const products = [{
131131
Backorder: 55,
132132
Manufacturing: 10,
133133
Category: 'Projectors',
134-
ImageSrc: 'images/products/14.png',
134+
ImageSrc: '../../../../images/products/14.png',
135135
}, {
136136
Id: 15,
137137
Name: 'Projector PlusHD',
@@ -140,7 +140,7 @@ export const products = [{
140140
Backorder: 0,
141141
Manufacturing: 90,
142142
Category: 'Projectors',
143-
ImageSrc: 'images/products/15.png',
143+
ImageSrc: '../../../../images/products/15.png',
144144
}, {
145145
Id: 16,
146146
Name: 'Projector PlusHT',
@@ -149,7 +149,7 @@ export const products = [{
149149
Backorder: 75,
150150
Manufacturing: 57,
151151
Category: 'Projectors',
152-
ImageSrc: 'images/products/16.png',
152+
ImageSrc: '../../../../images/products/16.png',
153153
}, {
154154
Id: 17,
155155
Name: 'ExcelRemote IR',
@@ -158,7 +158,7 @@ export const products = [{
158158
Backorder: 0,
159159
Manufacturing: 190,
160160
Category: 'Automation',
161-
ImageSrc: 'images/products/17.png',
161+
ImageSrc: '../../../../images/products/17.png',
162162
}, {
163163
Id: 18,
164164
Name: 'ExcelRemote Bluetooth',
@@ -167,7 +167,7 @@ export const products = [{
167167
Backorder: 0,
168168
Manufacturing: 0,
169169
Category: 'Automation',
170-
ImageSrc: 'images/products/18.png',
170+
ImageSrc: '../../../../images/products/18.png',
171171
}, {
172172
Id: 19,
173173
Name: 'ExcelRemote IP',
@@ -176,7 +176,7 @@ export const products = [{
176176
Backorder: 325,
177177
Manufacturing: 225,
178178
Category: 'Automation',
179-
ImageSrc: 'images/products/19.png',
179+
ImageSrc: '../../../../images/products/19.png',
180180
}];
181181

182182
export const productLabel = { 'aria-label': 'Product' };

0 commit comments

Comments
 (0)