var DemoApp = angular.module('DemoApp', ['dx']);
DemoApp.controller('DemoController', function DemoController($scope) {
$scope.dataGridOptions = {
dataSource: DevExpress.data.AspNet.createStore({
key: "ID",
loadUrl: url + "/Tasks",
updateUrl: url + "/UpdateTask",
insertUrl: url + "/InsertTask",
onBeforeSend: function(method, ajaxOptions) {
ajaxOptions.xhrFields = { withCredentials: true };
}
}),
showBorders: true,
paging: {
enabled: true,
pageSize: 15
},
headerFilter: {
visible: true
},
searchPanel: {
visible: true
},
editing: {
mode: "cell",
allowUpdating: true,
allowAdding: true
},
onRowInserted: function(e) {
e.component.navigateToRow(e.key);
},
columns: [{
dataField: "Owner",
width: 150,
allowSorting: false,
lookup: {
dataSource: employees,
valueExpr: "ID",
displayExpr: "FullName"
},
validationRules: [{ type: "required" }],
editCellTemplate: "dropDownBoxEditorTemplate"
}, {
dataField: "AssignedEmployee",
caption: "Assignees",
width: 200,
allowSorting: false,
editCellTemplate: "tagBoxEditorTemplate",
lookup: {
dataSource: employees,
valueExpr: "ID",
displayExpr: "FullName"
},
validationRules: [{ type: "required" }],
cellTemplate: function(container, options) {
var noBreakSpace = "\u00A0",
text = (options.value || []).map(function(element) {
return options.column.lookup.calculateCellValue(element);
}).join(", ");
container.text(text || noBreakSpace).attr("title", text);
},
calculateFilterExpression: function(filterValue, selectedFilterOperation, target) {
if(target === "search" && typeof(filterValue) === "string") {
return [this.dataField, "contains", filterValue]
}
return function(data) {
return (data.AssignedEmployee || []).indexOf(filterValue) !== -1
}
}
}, {
dataField: "Subject",
validationRules: [{ type: "required" }]
}, {
dataField: "Status",
lookup: {
dataSource: statuses,
valueExpr: "id",
displayExpr: "name"
},
validationRules: [{ type: "required" }],
width: 200,
editorOptions: {
itemTemplate: "statusTemplate"
}
}
]
}
$scope.initTagBoxEditor = function(data) {
return {
dataSource: employees,
value: data.value,
valueExpr: "ID",
displayExpr: "FullName",
showSelectionControls: true,
maxDisplayedTags: 3,
showMultiTagOnly: false,
applyValueMode: "useButtons",
searchEnabled: true,
onValueChanged: function(e) {
data.setValue(e.value);
},
onSelectionChanged: function(e) {
data.component.updateDimensions();
}
}
}
$scope.initDropDownBoxEditor = function(data) {
return {
dropDownOptions: { width: 500 },
dataSource: employees,
value: data.value,
valueExpr: "ID",
displayExpr: "FullName",
contentTemplate: "contentTemplate"
}
}
$scope.initContent = function(data, component) {
return {
dataSource: employees,
remoteOperations: true,
columns: ["FullName", "Title", "Department"],
hoverStateEnabled: true,
scrolling: { mode: "virtual" },
height: 250,
selection: { mode: "single" },
selectedRowKeys: [data.value],
focusedRowEnabled: true,
focusedRowKey: data.value,
onSelectionChanged: function(selectionChangedArgs) {
component.option("value", selectionChangedArgs.selectedRowKeys[0]);
data.setValue(selectionChangedArgs.selectedRowKeys[0]);
if(selectionChangedArgs.selectedRowKeys.length > 0) {
component.close();
}
}
}
}
});
<!DOCTYPE html>
<html xmlns="http://www.w3.org/1999/xhtml" >
<head>
<title>DevExtreme Demo</title>
<meta http-equiv="X-UA-Compatible" content="IE=edge" />
<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
<meta name="viewport" content="width=device-width, initial-scale=1.0, maximum-scale=1.0" />
<script src="https://ajax.googleapis.com/ajax/libs/jquery/3.5.1/jquery.min.js"></script>
<script>window.jQuery || document.write(decodeURIComponent('%3Cscript src="js/jquery.min.js"%3E%3C/script%3E'))</script>
<link rel="stylesheet" type="text/css" href="https://cdn3.devexpress.com/jslib/20.2.4/css/dx.common.css" />
<link rel="stylesheet" type="text/css" href="https://cdn3.devexpress.com/jslib/20.2.4/css/dx.light.css" />
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.3.16/angular.min.js"></script>
<script>window.angular || document.write(decodeURIComponent('%3Cscript src="js/angular.min.js"%3E%3C/script%3E'))</script>
<script src="https://cdn3.devexpress.com/jslib/20.2.4/js/dx.all.js"></script>
<script src="https://unpkg.com/devextreme-aspnet-data@2.7.1/js/dx.aspnet.data.js"></script>
<script src="data.js"></script>
<link rel="stylesheet" type="text/css" href="styles.css" />
<script src="index.js"></script>
</head>
<body class="dx-viewport">
<div class="demo-container" ng-app="DemoApp" ng-controller="DemoController">
<div id="gridContainer" dx-data-grid="dataGridOptions" dx-item-alias="row">
<div data-options="dxTemplate:{ name: 'statusTemplate' }">
<div ng-if="row != null">
<img ng-src="{{'images/icons/status-' + row.id + '.svg'}}" class="status-icon middle"></img>
<span class="middle">{{row.name}}</span>
</div>
<span ng-if="row == null">
(All)
</span>
</div>
<div data-options="dxTemplate:{ name: 'tagBoxEditorTemplate'}">
<div dx-tag-box="initTagBoxEditor(row)"></div>
</div>
<div data-options="dxTemplate:{ name: 'dropDownBoxEditorTemplate'}">
<div dx-drop-down-box="initDropDownBoxEditor(row)" dx-item-alias="item">
<div data-options="dxTemplate:{ name: 'contentTemplate'}">
<div dx-data-grid="initContent(row, item.component)"></div>
</div>
</div>
</div>
</div>
</div>
</body>
</html>
.status-icon {
height: 16px;
width: 16px;
display: inline-block;
margin-right: 8px;
}
.middle {
vertical-align: middle;
}
var statuses = [{
"id": 1, "name": "Not Started"
}, {
"id": 2, "name": "In Progress"
}, {
"id": 3, "name": "Deferred"
}, {
"id": 4, "name": "Need Assistance"
}, {
"id": 5, "name": "Completed"
}
];
var url = "https://js.devexpress.com/Demos/Mvc/api/CustomEditors";
var employees = DevExpress.data.AspNet.createStore({
key: "ID",
loadUrl: url + "/Employees",
onBeforeSend: function(method, ajaxOptions) {
ajaxOptions.xhrFields = { withCredentials: true };
}
});