- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
3 weeks ago
Hi All,
I have requirement to check the attached csv file's 1st column header using client controller script in the widget.
I am trying to use below code and changed the name of the header name of the csv file but its not working.
Solved! Go to Solution.
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
3 weeks ago
this is a sample working code for your validation
I am checking if first column is Name
you can enhance it further based on your requirement.
HTML:
<label for="csvUpload">Upload CSV file:</label>
<input type="file" id="csvUpload" accept=".csv" onchange="angular.element(this).scope().validateCSV(event)" />
<div ng-if="error" style="color: red; margin-top: 10px;">
{{ error }}
</div>
Client Controller:
function($scope) {
$scope.error = "";
$scope.validateCSV = function(event) {
let file = event.target.files[0];
$scope.error = "";
if (!file) return;
let reader = new FileReader();
reader.onload = function(e) {
let contents = e.target.result;
let lines = contents.split(/\r\n|\n/);
if (lines.length === 0) {
$scope.$apply(() => $scope.error = "CSV file is empty.");
return;
}
// Get first line (header)
let headers = lines[0].split(',');
if (headers[0].trim() !== "Name") {
$scope.$apply(() => $scope.error = "First column header must be 'Name'.");
return;
}
$scope.$apply(() => $scope.error = "CSV file is valid.");
};
reader.readAsText(file);
};
}
Server:
(function() {
data.error = "";
// Server script doesn't need to process file here, validation done client-side
})();
Output:
I hope you will mark my response as correct as I shared a working solution which you can enhance further based on your developer skills and customer requirements
Ankur
✨ Certified Technical Architect || ✨ 9x ServiceNow MVP || ✨ ServiceNow Community Leader
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
3 weeks ago
Here is a snippet html template and controller you can start from but getting it to your specs might require a little bit of understanding of angular and the oob widgets. You can put this in a catalog item as a widget variable and test it out.
The logic you are talking of could be put in the setAttachments callback function passed to the nowAttachmentHandler.
<!-- from oob sc cat item widget -->
<div ng-if="true" class="wrapper-md row no-margin" role="region" data-label="Attachments"
aria-label="${Attachments}">
<div
ng-class="{'flex-center attachment-height': c.isNative == 'true', 'flex-start': c.isNative != 'true'}">
<div ng-if="!submitting && !submitted" style="font-weight:normal;cursor:default;margin-bottom:2rem;">
<sp-attachment-button ng-if="::!showDragAndDrop()" modal="true" supported-extensions="exe, bat, sh"
required="{{data.mandatory_attachment}}"></sp-attachment-button>
<sp-attachment-button ng-if="::showDragAndDrop()" modal="true"
required="{{data.mandatory_attachment}}"
ng-class="{'hidden-xs': false, 'hidden-sm': true, 'hidden-md': true, 'hidden-lg': true}"></sp-attachment-button>
<span class="fa fa-asterisk mandatory" ng-if="data.mandatory_attachment"
ng-class="{'mandatory-filled': data.mandatory_attachment && (data.attachment_submitted || attachments.length > 0)}"
style="vertical-align:super" aria-hidden="true"></span>
<span ng-class="{'attachment-text' : options.native_mobile == 'true'}" aria-hidden="true">${Add
attachments}</span>
</div>
</div>
<div ng-if="::showDragAndDrop()" class="panel panel-{{options.color}} b drag-and-drop-area"
ng-class="{'hidden-xs': true}" aria-hidden="true">
<sp-attachment-picker on-file-pick="dropFiles($files)"></sp-attachment-picker>
</div>
<span ng-if="attachmentUploadInProgress">${Uploading attachments}
<div class="sp-loading-indicator la-sm" style="color:black;display:inline">
<div></div>
<div></div>
<div></div>
</div>
</span>
<now-attachments-list template="sp_attachment_single_line"></now-attachments-list>
</div>
api.controller = function ($scope, nowAttachmentHandler, spUtil, spAttachmentUpload, $timeout, cabrillo, spModal) {
var c = this;
c.isNative = cabrillo.isNative()
$scope.table = $scope.page.g_form.recordTableName;
$scope.guid = $scope.$parent.c.getAttachmentGuid();
$scope.data.maxAttachmentSize = 24;
var ah = $scope.attachmentHandler = new nowAttachmentHandler(setAttachments, appendError);
ah.setParams($scope.table, $scope.guid, 1024 * 1024 * $scope.data.maxAttachmentSize);
$scope.showDragAndDrop = function () {
if (true)
return true;
else
return false;
}
function setAttachments(attachments, action) {
if (!angular.equals($scope.attachments, attachments))
$scope.attachments = attachments;
if (action === "added") {
console.log(attachments[0]);
}
if (action === "renamed") {
// attachment renamed logic
}
if (action === "deleted") {
// attachment deleted logic
}
spUtil.get($scope, {
action: "from_attachment"
});
}
function appendError(error) {
spUtil.addErrorMessage(error.msg + error.fileName);
}
$scope.dropFiles = function (files) {
if (files && files.length > 0) {
$scope.attachmentUploadInProgress = true;
$scope.totalFilesBeingUploaded++;
spAttachmentUpload.uploadAttachments($scope.attachmentHandler, files);
}
$timeout(function () {
if ($scope.attachmentUploadInProgress != false)
spUtil.addInfoMessage($scope.data.attachmentUploadProgressMsg);
}, 2000);
$scope.$on('attachment.upload.idle', function () {
$scope.attachmentUploadInProgress = false;
$scope.totalFilesBeingUploaded = 0;
});
};
$scope.confirmDeleteAttachment = function (attachment) {
if (c.isNative) {
if (confirm("delete attachment?")) {
$scope.data.attachment_action_in_progress = true;
$scope.attachmentHandler.deleteAttachment(attachment);
}
} else {
spModal.confirm("delete attachment?").then(function () {
$scope.data.attachment_action_in_progress = true;
$scope.attachmentHandler.deleteAttachment(attachment);
});
}
}
};
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
3 weeks ago
Hello @Virendra K ,
I am also not much expert in portal ,I found something related which you can try once
1.angular.element('#header').val() does not read inside a file
2.Browsers do NOT expose CSV content via <input type="file">
3.You must read the file using JavaScript FileReader first.
1.In widget HTML
<input type="file" id="csvFile" accept=".csv" />
2.In client controller use FileReader to read the CSV
$scope.validateCSV = function() {
var fileInput = document.getElementById('csvFile');
var file = fileInput.files[0];
if (!file) {
alert("Please upload a file first.");
return false;
}
var reader = new FileReader();
reader.onload = function(e) {
var text = e.target.result;
// Split first line (header row)
var firstLine = text.split('\n')[0].trim();
// Read the first column header
var firstColumnHeader = firstLine.split(',')[0].trim().replace(/"/g, '');
console.log("First Column Header:", firstColumnHeader);
if (firstColumnHeader !== 'CI Name') {
$scope.title = "Invalid file format";
$scope.message = "Ensure the 'CI Name' column is the first column in the CSV.";
alert($scope.message);
$scope.$apply();
return false;
} else {
alert("CSV is valid!");
}
};
reader.readAsText(file);
};
3.Add a button to trigger the validation
<button class="btn btn-primary" ng-click="validateCSV()">Validate CSV</button>