Hello,
So I am trying to use the uploader component in a grid but in synchronous mode. I have it displaying correctly and everything seems to be working correctly, except when I click the save button for the grid dialog, it is sending a string of the file up and not the binary. I assume I am doing the read function incorrectly. Please see the below code:
Option 1 is what we are trying to do. We just need the file name to be shown as the file is being saved in S3 bucket and we will need to do a temporary URL to download - which we already have code for. This is our dataManager:
{"count":1,"result":[{"id":1,"task_id":53,"name":"Sample PO","size":186425,"type":"pdf","s3_path":"attachments\/234cuyC33P3j4r94CHsrZ4.pdf","signing_user_id":1,"signed_at":null,"approval_required":1,"created_at":"2021-08-14T06:01:35.000000Z","created_by":1,"updated_at":"2021-08-14T06:01:35.000000Z","updated_by":1,"deleted_at":null,"deleted_by":null}]}
We need to do synchronous and save the file on insert because we need new record id for association in S3 bucket.
So to be clear, the anticipated behavior is that a user clicks Add for the grid, the dialog is shown, they fill out the form,
browse for the file and the uploader component acts like a regular input type="file" and then on Save, the file is
submitted using the grids crudUrl to the server.
Index.cshtml
<div id="container">
<div id="Grid"></div>
</div>
<script id="template2" type="text/x-template">
<div class="link">
<a rel='nofollow' href=""></a>
</div>
</script>
<script>
var file;
var elem;
var richText;
var rte;
class custom extends ej.data.UrlAdaptor {
processResponse(data, ds, query, xhr, request, changes) {
request.data = JSON.stringify(data);
return ej.data.UrlAdaptor.prototype.processResponse.call(this, data, ds, query, xhr, request, changes)
}
insert(dm, data, tableName) {
var fd = new FormData();
for (var prop of data.file) {
fd.append('UploadFiles', prop.rawFile);
}
fd.append('OrderID', data.OrderID);
fd.append('CustomerID', data.CustomerID);
// data.File = fd;
return {
url: dm.dataSource.insertUrl || dm.dataSource.crudUrl || dm.dataSource.url,
type: "POST",
data: fd,
contentType: null
}
}
update(dm, data, tableName) {
var fd = new FormData();
for (var prop of tableName.file) {
fd.append('UploadFiles', prop.rawFile);
}
fd.append('OrderID', tableName.OrderID);
fd.append('CustomerID', tableName.CustomerID);
// data.File = fd;
return {
url: dm.dataSource.updateUrl || dm.dataSource.crudUrl || dm.dataSource.url,
type: "POST",
data: fd,
contentType: null
}
}
};
let data = new ej.data.DataManager({
url: "/Home/UrlDatasource",
insertUrl: "/Home/Save",
updateUrl: "/Home/Update",
removeUrl: "Home/Delete",
adaptor: new custom
});
let grid = new ej.grids.Grid({
dataSource: data,
editSettings: { allowEditing: true, allowAdding: true, allowDeleting: true, mode: 'Dialog' },
allowPaging: true,
toolbar: ['Add', 'Edit', 'Delete'],
columns: [
{ field: 'OrderID', headerText: 'Order ID', textAlign: 'Right', width: 100, isPrimaryKey: true },
{ field: 'CustomerID', headerText: 'Customer ID', width: 120 },
{
field: 'file', headerText: "File", type: 'string', template: "#template2", width: 180, edit: {
//cellEditTemplate
create: () => {
// Input element is created and returned for appending the Uploader control.
elem = document.createElement('input');
return elem;
},
read: () => {
//read function is used to read the value from the component at the time of save.
return (file) ? file : uploadObj.filesData;
},
destroy: () => {
// Uploader is destroyed on edit save/close action.
uploadObj.destroy();
},
write: args => {
//write function is used to create custom component or assign default value at the time of editing.
uploadObj = new ej.inputs.Uploader({
files: ['']
});
uploadObj.appendTo(elem)
}
} },
],
height: 265,
queryCellInfo: queryCellInfo,
actionComplete: complete,
});
grid.appendTo('#Grid');
function queryCellInfo(args) {
if (args.column.field === 'file') {
if (args.data.file) {
var anchotEle = args.cell.getElementsByTagName('a')[0];
anchotEle.innerText = args.data.file.name;
anchotEle.onclick = function click(args) {
args.target.setAttribute("rel='nofollow' href", http://localhost:63371/Home/Download?filename= + args.target.innerText);
};
}
}
}
function complete(args) {
if (args.requestType === 'add') {
args.form.setAttribute('enctype', 'multipart/form-data');
args.form.setAttribute('encoding', 'multipart/form-data');
}
if (args.requestType === 'save' && args.action === "edit") {
var gridInstance = document.getElementById('Grid').ej2_instances[0]; //Grid Instance
gridInstance.refresh();
}
}
</script> |
|
Thank you, I guess I can figure this out. This is all Razor and .Net right?
Edit: I was able to get this working. For anyone else who may need it, here you go (you may need to add update function in your adaptor depending on how your server process is looking for data):