Skip to content

Instantly share code, notes, and snippets.

@cliffordp
Last active April 10, 2026 14:57
Show Gist options
  • Select an option

  • Save cliffordp/c0b48b14f0f6f42d27c79e8f39013774 to your computer and use it in GitHub Desktop.

Select an option

Save cliffordp/c0b48b14f0f6f42d27c79e8f39013774 to your computer and use it in GitHub Desktop.
Gravity Forms: add the READONLY property to an input UNTIL it gets a value set
/*
* This snippet: https://gist.github.com/cliffordp/c0b48b14f0f6f42d27c79e8f39013774
* DEMO: https://share.zight.com/bLu9x8Y6 (3min)
* WHAT: This adds the READONLY property to an input field and then removes it AFTER this same field has a value in it.
* .readonly-until-value -> because self-referential, it's hidden until this field gets a value entered, such as via Populate Anything.
* .readonly-until-value-77 -> the field with this class will be READONLY until Field #77 has a value.
* WHY: Useful when a text field gets a dynamically-filled value but you want the input to remain editable thereafter.
* EXAMPLE: a "County" text input (Field #9) has class `readonly-until-value-77` so when Full Address text input (Field #77)
* gets a value (from human or dynamic), then County (#9) has its READONLY removed because #77 got a value. The idea is that
* County would be dynamically-filled once Full Address is entered, but it remains editable for user correction and/or in case
* it does not get a value entered (remains blank but is no longer READONLY).
* HOW-TO:
* 1. Install and activate the Code Chest plugin: https://gravitywiz.com/gravity-forms-code-chest/ (this code is formatted for use in that plugin).
* 2. Paste this snippet into the form's Code Chest JavaScript input.
* 3. Add the `readonly-until-value` or `.readonly-until-value-77` class to a text input field (not tested on other field types).
*/
gform.addAction("gfcc_deferred", function () {
if (window['gfcc_poller_started_GFFORMID']) return;
window['gfcc_poller_started_GFFORMID'] = true;
var checkAllFields = function() {
jQuery("#gform_GFFORMID .gfield").each(function () {
var $field = jQuery(this);
var classes = $field.attr("class") || "";
var match = classes.match(/readonly-until-value(?:-(\d+))?(?:\s|$)/);
if (!match) return;
var explicitSourceId = match[1] || null;
var isSelfReferential = !explicitSourceId;
var $inputs = $field.find("input, select, textarea").not(':button, :submit, [type="hidden"]');
if ($inputs.length === 0) return;
if (!$inputs.first().data('ro_initialized')) {
$inputs.data('ro_initialized', true);
$inputs.prop("readonly", true).attr("tabindex", -1);
if (isSelfReferential) {
$field.css("visibility", "hidden");
} else {
var $sourceLabel = jQuery("#field_GFFORMID_" + explicitSourceId + " .gfield_label").first();
if ($sourceLabel.length) {
var labelName = $sourceLabel.text().replace(/\*/g, '').trim();
$inputs.attr("title", "First, enter " + labelName);
}
$inputs.on("focus.ro_bounce", function () {
jQuery("#input_GFFORMID_" + explicitSourceId).focus();
});
}
}
var $monitoredInputs = $inputs; // Default to self
if (!isSelfReferential && explicitSourceId) {
// Since this explicitly relies on a source field (-77), we shift our surveillance
// to evaluate if Field 77 has data inside it yet instead.
var $sourceField = jQuery("#field_GFFORMID_" + explicitSourceId);
if ($sourceField.length) {
$monitoredInputs = $sourceField.find("input, select, textarea").not(':button, :submit, [type="hidden"]');
}
}
// Check if the monitored field has a value
var hasValue = false;
$monitoredInputs.each(function() {
var type = jQuery(this).attr('type');
if (type === 'checkbox' || type === 'radio') {
if (jQuery(this).is(':checked')) hasValue = true;
} else {
var val = jQuery(this).val();
if (val && String(val).trim() !== "") hasValue = true;
}
});
// If the appropriate event condition is met, unlock!
if (hasValue && $inputs.prop("readonly")) {
if (isSelfReferential) {
$field.css("visibility", "");
}
$inputs
.prop("readonly", false)
.removeAttr("readonly")
.removeAttr("tabindex")
.removeAttr("title")
.off("focus.ro_bounce");
}
});
};
checkAllFields();
setInterval(checkAllFields, 333);
});
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment