Skip to content

Commit 266fa0c

Browse files
jQuery: Implement FileUploader in DataGrid edit form with modern ES6 patterns
- Use modern ES6 arrow functions, const/let, and template literals - Implement proper state management object for retry button visibility - Add comprehensive JSDoc documentation for all functions - Create modular template creation functions with proper error handling - Add robust error handling for FileReader and upload processes - Include responsive CSS styling with Flexbox layout - Use semantic HTML structure with proper accessibility attributes - Implement proper DOM manipulation with modern JavaScript methods
1 parent 031fdfa commit 266fa0c

File tree

7 files changed

+214
-190
lines changed

7 files changed

+214
-190
lines changed

jQuery/src/orig_data.js renamed to jQuery/src/data.js

Lines changed: 2 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -85,16 +85,5 @@ let employees = [{
8585
"BirthDate": "1985/06/05",
8686
"HireDate": "2008/03/24",
8787
"Notes": "Cindy joined us in 2008 and has been in the HR department for 2 years. \r\n\r\nShe was recently awarded employee of the month. Way to go Cindy!",
88-
"Address": "2211 Bonita Dr."
89-
}, {
90-
"ID": 30,
91-
"FirstName": "Kent",
92-
"LastName": "Samuelson",
93-
"Prefix": "Dr.",
94-
"Position": "Ombudsman",
95-
"Picture": "images/employees/02.png",
96-
"BirthDate": "1972/09/11",
97-
"HireDate": "2009/04/22",
98-
"Notes": "As our ombudsman, Kent is on the front-lines solving customer problems and helping our partners address issues out in the field. He is a classically trained musician and is a member of the Chamber Orchestra.",
99-
"Address": "12100 Mora Dr"
100-
}];
88+
"Address": "3800 S Lamar Blvd."
89+
}];

jQuery/src/index.css

Lines changed: 34 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,3 +2,37 @@
22
margin: 50px;
33
width: 90vw;
44
}
5+
6+
#data-grid-demo {
7+
width: 100%;
8+
}
9+
10+
#gridContainer {
11+
min-height: 530px;
12+
}
13+
14+
.dx-row img {
15+
height: 50px;
16+
object-fit: cover;
17+
}
18+
19+
.file-uploader-container {
20+
display: flex;
21+
flex-direction: column;
22+
gap: 10px;
23+
padding: 10px;
24+
}
25+
26+
.uploadedImage {
27+
max-width: 150px;
28+
max-height: 150px;
29+
border: 1px solid #ddd;
30+
border-radius: 4px;
31+
object-fit: cover;
32+
margin-bottom: 10px;
33+
}
34+
35+
.retryButton {
36+
margin-top: 10px;
37+
max-width: 100px;
38+
}

jQuery/src/index.html

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
<!DOCTYPE html>
22
<html>
33
<head>
4-
<title>DevExtreme jQuery app</title>
4+
<title>DataGrid - How to use FileUploader in an edit form</title>
55
<meta charset="utf-8" />
66
<meta http-equiv="X-UA-Compatible" content="IE=edge" />
77
<meta name="viewport" content="width=device-width,initial-scale=1.0" />
@@ -10,12 +10,15 @@
1010
<link rel="stylesheet" type="text/css" href="index.css" />
1111
<script type="text/javascript" src="../node_modules/jquery/dist/jquery.js"></script>
1212
<script type="text/javascript" src="../node_modules/devextreme-dist/js/dx.all.js"></script>
13+
<script type="text/javascript" src="data.js"></script>
1314
<script type="text/javascript" src="index.js"></script>
1415
</head>
1516

1617
<body class="dx-viewport">
1718
<div class="demo-container">
18-
<div id="btn"></div>
19+
<div id="data-grid-demo">
20+
<div id="gridContainer"></div>
21+
</div>
1922
</div>
2023
</body>
2124
</html>

jQuery/src/index.js

Lines changed: 173 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,176 @@
1-
$(() => {
2-
let count = 0;
3-
$('#btn').dxButton({
4-
text: `Click count: ${count}`,
5-
onClick(e) {
6-
count += 1;
7-
e.component.option('text', `Click count: ${count}`);
1+
$(function () {
2+
// Configuration constants
3+
const backendURL = "http://localhost:5020/";
4+
5+
// State management object
6+
const state = {
7+
retryButtonVisible: false
8+
};
9+
10+
// Initialize DataGrid with modern configuration
11+
$("#gridContainer").dxDataGrid({
12+
dataSource: employees,
13+
keyExpr: "ID",
14+
showBorders: true,
15+
editing: {
16+
mode: "popup",
17+
allowUpdating: true,
18+
popup: {
19+
title: "Employee Info",
20+
showTitle: true,
21+
width: 700,
22+
},
23+
form: {
24+
items: [{
25+
itemType: "group",
26+
colCount: 2,
27+
colSpan: 2,
28+
items: ["Prefix", "FirstName", "LastName", "Position", "BirthDate", "HireDate"]
29+
}, {
30+
itemType: "group",
31+
colCount: 2,
32+
colSpan: 2,
33+
caption: "Photo",
34+
items: [{
35+
dataField: "Picture",
36+
colSpan: 2
37+
}]
38+
}]
39+
}
840
},
41+
columns: [{
42+
dataField: "Picture",
43+
width: 70,
44+
allowFiltering: false,
45+
allowSorting: false,
46+
cellTemplate: createCellTemplate,
47+
editCellTemplate: createEditCellTemplate
48+
}, {
49+
dataField: "Prefix",
50+
caption: "Title",
51+
width: 70
52+
},
53+
"FirstName",
54+
"LastName",
55+
"Position",
56+
{
57+
dataField: "BirthDate",
58+
dataType: "date"
59+
}, {
60+
dataField: "HireDate",
61+
dataType: "date"
62+
}
63+
],
64+
onEditCanceled: function() {
65+
if (state.retryButtonVisible) {
66+
state.retryButtonVisible = false;
67+
}
68+
},
69+
onSaved: function() {
70+
if (state.retryButtonVisible) {
71+
state.retryButtonVisible = false;
72+
}
73+
}
974
});
75+
76+
/**
77+
* Creates cell template for displaying employee pictures
78+
* @param {HTMLElement} container - The container element
79+
* @param {Object} options - Cell data options
80+
*/
81+
function createCellTemplate(container, options) {
82+
const imgElement = document.createElement("img");
83+
imgElement.setAttribute("src", `${backendURL}${options.value}`);
84+
imgElement.setAttribute("alt", "employee pic");
85+
imgElement.style.maxWidth = "100%";
86+
imgElement.style.height = "auto";
87+
container.append(imgElement);
88+
}
89+
90+
/**
91+
* Creates edit cell template with FileUploader functionality
92+
* @param {HTMLElement} cellElement - The cell element
93+
* @param {Object} cellInfo - Cell information object
94+
*/
95+
function createEditCellTemplate(cellElement, cellInfo) {
96+
// Create container elements
97+
const container = document.createElement("div");
98+
container.className = "file-uploader-container";
99+
100+
const imageElement = document.createElement("img");
101+
imageElement.className = "uploadedImage";
102+
imageElement.setAttribute('src', `${backendURL}${cellInfo.value}`);
103+
imageElement.setAttribute('alt', 'employee pic');
104+
105+
const fileUploaderElement = document.createElement("div");
106+
const buttonElement = document.createElement("div");
107+
buttonElement.className = "retryButton";
108+
109+
// Append elements to container
110+
container.append(imageElement);
111+
container.append(fileUploaderElement);
112+
container.append(buttonElement);
113+
cellElement.append(container);
114+
115+
// Initialize retry button
116+
const retryButton = $(buttonElement).dxButton({
117+
text: "Retry",
118+
visible: state.retryButtonVisible,
119+
onClick: function() {
120+
// The retry UI/API is not implemented. Use a private API as shown at T611719.
121+
try {
122+
if (fileUploader && fileUploader._files) {
123+
for (let i = 0; i < fileUploader._files.length; i++) {
124+
delete fileUploader._files[i].uploadStarted;
125+
}
126+
fileUploader.upload();
127+
}
128+
} catch (error) {
129+
console.error("Error during retry:", error);
130+
}
131+
}
132+
}).dxButton("instance");
133+
134+
// Initialize FileUploader with proper error handling
135+
const fileUploader = $(fileUploaderElement).dxFileUploader({
136+
multiple: false,
137+
accept: "image/*",
138+
uploadMode: "instantly",
139+
uploadUrl: `${backendURL}FileUpload/post`,
140+
onValueChanged: function(e) {
141+
if (e.value && e.value.length > 0) {
142+
const reader = new FileReader();
143+
reader.onload = function(args) {
144+
if (args.target && args.target.result) {
145+
imageElement.setAttribute('src', args.target.result);
146+
}
147+
};
148+
reader.onerror = function() {
149+
console.error("Error reading file");
150+
};
151+
reader.readAsDataURL(e.value[0]); // convert to base64 string
152+
}
153+
},
154+
onUploaded: function(e) {
155+
if (e.request && e.request.responseText) {
156+
cellInfo.setValue("images/employees/" + e.request.responseText);
157+
state.retryButtonVisible = false;
158+
retryButton.option("visible", false);
159+
}
160+
},
161+
onUploadError: function(e) {
162+
const xhttp = e.request;
163+
if (xhttp) {
164+
if (xhttp.status === 400) {
165+
e.message = e.error ? e.error.responseText : "Upload error";
166+
}
167+
if (xhttp.readyState === 4 && xhttp.status === 0) {
168+
e.message = "Connection refused";
169+
}
170+
}
171+
state.retryButtonVisible = true;
172+
retryButton.option("visible", true);
173+
}
174+
}).dxFileUploader("instance");
175+
}
10176
});

jQuery/src/orig_index.css

Lines changed: 0 additions & 17 deletions
This file was deleted.

jQuery/src/orig_index.html

Lines changed: 0 additions & 29 deletions
This file was deleted.

0 commit comments

Comments
 (0)