Preserve Selected Multi-Select Choices Across Filter Changes
When GPPA repopulates a Multi-Select field, previously selected choices that are no longer in the new result set get removed. This snippet stores selections in a hidden field and ensures they remain available and selected even after GPPA refreshes the field.
Instructions
- Add a Hidden field to your form to store selections.
- Update the form ID, multi-select field ID, and hidden field ID via the configuration
Code
Filename: gppa-preserve-multiselect-choices-across-filter-changes.php
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
<?php
/**
* Gravity Perks // Populate Anything // Preserve Selected Multi-Select Choices Across Filter Changes
* https://gravitywiz.com/documentation/gravity-forms-populate-anything/
*
* When GPPA repopulates a Multi-Select field, previously selected choices that are no longer
* in the new result set get removed. This snippet stores selections in a hidden field and
* ensures they remain available and selected even after GPPA refreshes the field.
*
* Instructions:
* 1. Add a Hidden field to your form to store selections.
* 2. Update the form ID, multi-select field ID, and hidden field ID via the configuration
*/
class GPPA_Preserve_Multiselect_Choices {
private $form_id;
private $field_id;
private $store_id;
public function __construct( $args ) {
$this->form_id = $args['form_id'];
$this->field_id = $args['field_id'];
$this->store_id = $args['store_id'];
add_filter( "gform_pre_render_{$this->form_id}", array( $this, 'pre_render' ), 20 );
add_filter( "gform_pre_validation_{$this->form_id}", array( $this, 'restore_choices' ), 20 );
}
public function pre_render( $form ) {
$this->enqueue_script();
return $this->restore_choices( $form );
}
public function restore_choices( $form ) {
$stored = json_decode( wp_unslash( rgpost( 'input_' . $this->store_id ) ), true );
if ( empty( $stored ) || ! is_array( $stored ) ) {
return $form;
}
foreach ( $form['fields'] as &$field ) {
if ( (int) $field->id !== $this->field_id ) {
continue;
}
$existing = array_column( $field->choices ?: array(), 'value' );
foreach ( $stored as $value => $label ) {
if ( ! in_array( (string) $value, $existing, true ) ) {
$field->choices[] = array(
'text' => $label,
'value' => $value,
);
}
}
break;
}
return $form;
}
public function enqueue_script() {
if ( ! has_action( 'wp_footer', array( $this, 'output_script' ) ) ) {
add_action( 'wp_footer', array( $this, 'output_script' ) );
add_action( 'gform_preview_footer', array( $this, 'output_script' ) );
}
}
public function output_script() {
?>
<script type="text/javascript">
( function( $ ) {
window.GPPAPreserveMultiselectChoices = function( args ) {
var formId = args.formId,
fieldId = args.fieldId,
storeId = args.storeId,
isUpdating = false;
function getTS() {
var el = document.getElementById( 'input_' + formId + '_' + fieldId );
return el?.tomselect;
}
function getStore() {
var $store = $( '#input_' + formId + '_' + storeId );
try {
return JSON.parse( $store.val() ) || {};
} catch ( e ) {
return {};
}
}
function setStore( map ) {
$( '#input_' + formId + '_' + storeId ).val( JSON.stringify( map ) );
}
function refresh() {
var ts = getTS();
if ( ! ts ) {
return;
}
var $select = $( '#input_' + formId + '_' + fieldId );
// Rebind events (element is replaced on GPPA refresh).
if ( ! $select.data( 'gppa-preserve-bound' ) ) {
$select.data( 'gppa-preserve-bound', true );
ts.on( 'item_add', function( value ) {
if ( isUpdating ) return;
var map = getStore();
map[ value ] = ts.options[ value ]?.text || value;
setStore( map );
} );
ts.on( 'item_remove', function( value ) {
if ( isUpdating ) return;
var map = getStore();
delete map[ value ];
setStore( map );
} );
}
isUpdating = true;
var map = getStore();
// Add stored options and select them.
Object.keys( map ).forEach( function( val ) {
if ( ! ts.options[ val ] ) {
ts.addOption( { id: val, text: map[ val ] } );
}
} );
ts.addItems( Object.keys( map ), true );
setTimeout( function() { isUpdating = false; }, 0 );
}
$( document ).on( 'gppa_updated_batch_fields', function( e, updatedFormId, updatedFieldIds ) {
if ( Number( updatedFormId ) !== formId ) return;
if ( updatedFieldIds?.length && ! updatedFieldIds.some( function( id ) { return Number( id ) === fieldId; } ) ) return;
setTimeout( refresh, 0 );
} );
$( document ).on( 'gform_post_render', function( e, id ) {
if ( Number( id ) === formId ) refresh();
} );
refresh();
};
} )( jQuery );
</script>
<?php
$script = 'new GPPAPreserveMultiselectChoices( ' . wp_json_encode( array(
'formId' => $this->form_id,
'fieldId' => $this->field_id,
'storeId' => $this->store_id,
) ) . ' );';
GFFormDisplay::add_init_script( $this->form_id, 'gppa_preserve_multiselect_' . $this->field_id, GFFormDisplay::ON_PAGE_RENDER, $script );
}
}
# Configuration
new GPPA_Preserve_Multiselect_Choices( array(
'form_id' => 123, // Replace with your form ID.
'field_id' => 3, // Replace with your Multi-Select field ID.
'store_id' => 5, // Replace with your Hidden field ID.
) );