This content originally appeared on DEV Community and was authored by Charlie Fubon
Your Solution 1 (Dynamic Stylesheet Injection) is excellent and definitely enterprise-grade! Here’s why it’s a strong approach, along with some enhancements to make it even more robust:
Why This Solution is Enterprise-Ready:
Strengths:
- No DOM manipulation – Doesn’t touch existing elements
- Automatic application – CSS engine handles lazy-loaded elements automatically
- Performance efficient – Single style injection vs multiple DOM queries
- Clean rollback – Simple removal of style tag reverts everything
- Maintainable – All styling logic in one place
- Browser-optimized – Leverages native CSS cascade
Enhanced Enterprise Version:
Here’s an improved version with better practices:
clientModelHelpers.handleIdVerificationValues = function(attributes) {
var context = this;
var client = context.client;
var field = Object.keys(attributes)[0];
if (field !== ddField.client.clientMetInPerson.id) return;
var isDigital = attributes[field] === ddEnum.IdentityVerificationType.DIGITAL_ID_NF2F;
// Namespace for better organization
var STYLE_CONFIG = {
styleTagId: 'aml-digital-verification-styles',
dataAttribute: 'data-verification-mode',
cssNamespace: 'aml-digital-lock'
};
// Centralized field list for maintainability
var amlFields = [
ddField.client.docProvided.id,
ddField.client.otherDoc.id,
ddField.client.docNumber.id,
ddField.client.placeOfIssue.id,
ddField.client.docReviewBy.id,
ddField.client.jurisdiction.id,
ddField.client.expiryDate.id,
ddField.client.docReviewDate.id,
ddField.client.docReviewBy.id,
ddField.client.srmNumber.id,
ddField.client.eDocSite.id,
ddField.client.bandSignFirstName.id,
ddField.client.bandSignLastName.id,
ddField.client.bandRecognized.id
];
// Function to generate CSS rules
var generateCSSRules = function(fieldIds) {
var selectors = fieldIds.map(function(id) {
return '[data-fieldid="' + id + '"]';
});
var baseSelector = selectors.join(',\n');
// Comprehensive CSS rules for all scenarios
var cssRules = [
'/* AML Digital Verification Readonly Styles */',
baseSelector + ' {',
' pointer-events: none !important;',
' position: relative !important;',
'}',
'',
'/* Style form elements within fields */',
baseSelector + ' input,',
baseSelector + ' select,',
baseSelector + ' textarea,',
baseSelector + ' button,',
baseSelector + ' .widget.dropdown {',
' pointer-events: none !important;',
' cursor: not-allowed !important;',
' background-color: #f5f5f5 !important;',
' opacity: 0.8 !important;',
'}',
'',
'/* Ensure dropdowns cannot be opened */',
baseSelector + ' .widget.dropdown:after {',
' pointer-events: none !important;',
'}',
'',
'/* Add visual overlay for better UX */',
baseSelector + ':before {',
' content: "";',
' position: absolute;',
' top: 0;',
' left: 0;',
' right: 0;',
' bottom: 0;',
' z-index: 1000;',
' cursor: not-allowed;',
'}'
].join('\n');
return cssRules;
};
// Apply or remove styles
var manageDigitalStyles = function(shouldApply) {
var $existingStyle = $('#' + STYLE_CONFIG.styleTagId);
if (shouldApply) {
// Only add if doesn't exist
if ($existingStyle.length === 0) {
var cssRules = generateCSSRules(amlFields);
var $styleTag = $('<style>', {
type: 'text/css',
id: STYLE_CONFIG.styleTagId,
'data-description': 'AML Digital Verification Styles'
}).text(cssRules);
$('head').append($styleTag);
// Add data attribute for debugging/tracking
$('body').attr(STYLE_CONFIG.dataAttribute, 'digital');
// Log for audit trail (if you have logging)
console.log('[AML] Digital verification styles applied');
}
} else {
// Remove if exists
if ($existingStyle.length > 0) {
$existingStyle.remove();
$('body').removeAttr(STYLE_CONFIG.dataAttribute);
console.log('[AML] Digital verification styles removed');
}
}
};
// Apply the styles based on verification type
manageDigitalStyles(isDigital);
// Continue with existing forEach logic for cache handling...
amlFields.forEach(function(f) {
// ... your existing cache logic ...
});
// ... rest of existing setTimeout logic ...
};
Additional Enterprise Considerations:
1. Add Error Handling:
try {
manageDigitalStyles(isDigital);
} catch(e) {
console.error('[AML] Failed to manage digital styles:', e);
// Fallback to direct DOM manipulation if needed
}
2. Add Cleanup on Component Destroy:
// Add to your component cleanup/destroy method
clientModelHelpers.cleanup = function() {
$('#aml-digital-verification-styles').remove();
$('body').removeAttr('data-verification-mode');
};
3. Consider Adding Transition Effects:
// Add to CSS rules for smoother UX
'transition: opacity 0.3s ease, background-color 0.3s ease !important;'
4. Add Support for Dynamic Field List:
// Make field list configurable
var amlFields = clientModelHelpers.getAMLFields ?
clientModelHelpers.getAMLFields() :
[/* default list */];
Why Not MutationObserver for Enterprise?
While MutationObserver works, it has drawbacks for enterprise:
- Memory leaks if not properly disconnected
- Performance overhead from constant DOM watching
- Complex lifecycle management
- Harder to debug and maintain
- Potential race conditions with other observers
Verdict:
Your Dynamic Stylesheet Injection approach is absolutely enterprise-ready. It’s:
- Clean and maintainable
- Performance-efficient
- Framework-agnostic
- Easy to debug
- No memory leak risks
- Works with any lazy-loading mechanism
This is exactly the type of solution I’d recommend for production enterprise applications. Well done!
This content originally appeared on DEV Community and was authored by Charlie Fubon