Goal
Touch UI extension to support required on FileUpload widget - /libs/granite/ui/components/foundation/form/fileupload using Granite validator. For validation api check documentation
For a similar extension on 61 supporting required on RTE check this post
Dialog of foundation image component /libs/foundation/components/image/cq:dialog/content/items/column/items/file was modified for demonstration purposes only
Demo | Package Install
File Upload widget - required = true
Validation Error
Solution
1) Login to CRXDE Lite (http://localhost:4502/crx/de) and create folder /apps/eaem-touchui-image-required
2) Create node /apps/eaem-touchui-image-required/clientlib of type cq:ClientLibraryFolder and add a String property categories with value cq.authoring.dialog and dependencies to underscore
3) Create file (nt:file) /apps/eaem-touchui-image-required/clientlib/js.txt and add
image-required.js
4) Create file (nt:file) /apps/eaem-touchui-image-required/clientlib/image-required.js and add the following code
(function ($, $document, gAuthor) {
var EAEM_IMAGE_REQ_FIELD_ID_PREFIX = "eaem-img-required-",
FILE_UPLOAD = ".coral-FileUpload",
FILE_UPLOAD_CLEAR = ".cq-FileUpload-clear",
DATA_ATTR_FILE_UPLOAD = "fileUpload",
FILE_UPLOAD_SEL = ".coral-FileUpload-input",
FILE_NAME = "./fileName",
COMPONENT = "foundation/components/image",
FIELD_ERROR_EL = $("<span class='coral-Form-fielderror coral-Icon coral-Icon--alert " +
"coral-Icon--sizeS' data-init='quicktip' data-quicktip-type='error'>" +
"</span>");
if(!gAuthor){
return;
}
$document.on('dialog-ready', checkFileRequired);
function checkFileRequired(){
var $fileUpload = $(FILE_UPLOAD),
$fileName = $("[name='" + FILE_NAME + "']"),
fileReqId = EAEM_IMAGE_REQ_FIELD_ID_PREFIX + getStringAfterLastSlash(FILE_NAME),
editable = gAuthor.DialogFrame.currentDialog.editable;
//if not an image component dialog, return
if((editable.type !== COMPONENT) || _.isEmpty($fileName)){
return;
}
//fileName field is hidden input, for the validator to work, add a invisible text field
//holding the file name
$fileUpload.append("<input type=text style='display:none' id='" + fileReqId + "'/>");
var cuiFileUpload = $fileUpload.data(DATA_ATTR_FILE_UPLOAD),
$fileReqInvisibleField = $("#" + fileReqId);
addValidatorIfRequiredSet(editable, cuiFileUpload, $fileReqInvisibleField);
}
function addValidatorIfRequiredSet(editable, cuiFileUpload, $fileReqInvisibleField){
var $fileUploadInput = cuiFileUpload.$element.find(FILE_UPLOAD_SEL);
if ($fileUploadInput.attr("aria-required") !== "true") {
return;
}
//user can either drop or upload an image; with required set to true
//validator with selector: ".coral-FileUpload-input"
//in /libs/granite/ui/components/foundation/clientlibs/foundation.js
//always checks if there is a file queued for upload, so workaround it by removing
//the required attribute on file upload input
$fileUploadInput.removeAttr( "aria-required" );
cuiFileUpload.$element.find(FILE_UPLOAD_CLEAR).on("click tap", function (e) {
performRequiredCheck($fileReqInvisibleField, '');
});
cuiFileUpload.$element.on("fileuploadsuccess", function (event) {
performRequiredCheck($fileReqInvisibleField, event.item.file.name);
});
cuiFileUpload.$element.on("assetselected", function (event) {
performRequiredCheck($fileReqInvisibleField, event.path);
});
addValidator($fileReqInvisibleField);
initRequiredField($fileReqInvisibleField, editable.path);
}
function initRequiredField($fileReqInvisibleField, path){
var fileName = getStringAfterLastSlash(FILE_NAME);
$.ajax(path + ".json").done(function(data){
var value = data[fileName];
if(_.isEmpty(value)){
value = data["fileReference"];
if(_.isEmpty(value)){
return;
}
value = getStringAfterLastSlash(value);
}
$fileReqInvisibleField.val(value);
})
}
function performRequiredCheck($fileReqInvisibleField, value){
$fileReqInvisibleField.val(value);
$fileReqInvisibleField.checkValidity();
$fileReqInvisibleField.updateErrorUI();
}
function addValidator($fileReqInvisibleField){
$.validator.register({
selector: "#" + $fileReqInvisibleField.attr("id"),
validate: validate ,
show: show ,
clear: clear
});
function validate($fileReqInvisibleField) {
if (_.isEmpty($fileReqInvisibleField.val())) {
return "Drop or upload an image";
}
return null;
}
function show($fileReqInvisibleField, message) {
var $fileUploadField = $fileReqInvisibleField.closest(FILE_UPLOAD),
arrow = $fileUploadField.closest("form").hasClass("coral-Form--vertical") ? "right" : "top",
$error = $fileUploadField.nextAll(".coral-Form-fielderror");
if (!_.isEmpty($error)) {
return;
}
FIELD_ERROR_EL.clone()
.attr("data-quicktip-arrow", arrow)
.attr("data-quicktip-content", message)
.insertAfter($fileUploadField);
}
function clear($fileReqInvisibleField) {
var $fileUploadField = $fileReqInvisibleField.closest(FILE_UPLOAD);
$fileUploadField.nextAll(".coral-Form-fielderror").remove();
}
}
function getStringAfterLastSlash(str){
if(!str || (str.indexOf("/") == -1)){
return "";
}
return str.substr(str.lastIndexOf("/") + 1);
}
}(jQuery, jQuery(document), Granite.author));


Hi Sreekanth ,
ReplyDeleteI was trying this in my component. It was successfully implemented and the validations are implementing correctly without any fail.
But when i am dragging and dropping the image component on the same page . These validations are implemented in the image component also.
I have implemented validations in my custom component only. Not in the image component.
if((editable.type !== COMPONENT) || _.isEmpty($fileName)){
return;
}
above piece of code is also not working:
I have given COMPONENT="apps/myproject/components/mycustomcomponent"
Please give some pointers on this.