Hidden ACF front end form not saving - wordpress

I'm using the front end form functionality of Advanced Custom Fields which works fine when on a standard page but when it's within a div that's hidden (either using Jquery to hide it or setting css to display none) the update button stops working and no data is saved. It doesn't show any errors in the console either.
How can I get around this? It's integral that the ACF form is hidden.
This is the code I'm using to display a particular set of fields:
<?php $activity_information = array(
'post_id' => $ID, // post id to get field groups from and save data to
'field_groups' => array(1781), // this will find the field groups for this post (post ID's of the acf post objects)
'form_attributes' => array( // attributes will be added to the form element
'class' => ''
),
'return' => add_query_arg( 'updated', 'true', get_permalink() ), // return url
'html_field_open' => '<div>', // field wrapper open
'html_field_close' => '</div>', // field wrapper close
'html_before_fields' => '', // html inside form before fields
'html_after_fields' => '', // html inside form after fields
'submit_value' => 'Update', // value for submit field
'updated_message' => '', // default updated message. Can be false to show no message
); ?>
<?php acf_form( $activity_information ); ?>
CSS:
.reveal-area {
display: none;
}
This is what it's generating (with the 3 dots representing all the fields):
<section class="row reveal-area">
<div class="columns">
<form id="acf-form" action="" method="post">
<div id="acf-form-data" class="acf-hidden">
<input type="hidden" id="_acf_post_id" name="_acf_post_id" value="1773"> <input type="hidden" id="_acf_nonce" name="_acf_nonce" value="6798af667b"> <input type="hidden" id="_acf_validation" name="_acf_validation" value="1"> <input type="hidden" id="_acf_ajax" name="_acf_ajax" value="0"> <input type="hidden" id="_acf_changed" name="_acf_changed" value="0"> <input type="hidden" id="_acf_form" name="_acf_form" value="cllBUjlDU09QMUtyVXBKalJ3VmVsS3lFQXpPcHEwUm5KNmdHRzVrYXRnY0RCT0xrUndDMWhQTXg4UVJzZm1xTHlVQllDWkFrV2R4ZzNmT3FQdjhnNWJSMFdaTUNHYlNjNzZ5OEcvbzBkOHROcW5BYXlRYmdQZ1R0bW93UmJyUXV0MEZQVmZkWlZSbEVGV2hqS1E2dHJxSjFxR2xuU1gxZUwydGRrR254VjZuTTRHdFV0WXBmRGJTeS9KQ2VIbkkxR0Rxcit0ZWlDck9IL2pOYk16ODVqQ28reFBNR05QSWRUc3R2Z1E2L0tnbWZrMXlhRDRCNU5ZWFk0M0MyTkpqNkZpa254NXBudk1qZk5uNytRZDN0NmFpN0FOdkFXTWRDYXNUd2gzRXJxeXNqaHJUaU1rRTJTMENiZVhsNHV6b1ZWbGUxTHJwTm1YQTEzUlozcmNrWU5mdFdYSjF3WDNINEtJWGdVREsvNTNFRzg5dHVKVGxqTmFILyt1ci9tOGNDYTYyVUk1eDB2ZUZCdEg3R3JHQmhtSWZyczkvS3diOHIwY2FwOWNISTdmWlhsK241Tmdib2UyZjlNM1o0RnhCOW5QdjRiL2t5cm1HVTlmR3BCek1mYnAyUkFRRWlmNlJqcjdTS3g2dmdUOCtvRjBWL28rcFhmOWVrV2ViV3ZkUHN4NVZuOXBIMzR4RStUQUxMTksyVnN0YjNBVnFBU1crb3pWUzA3TUpSVkJJN2RjYmxnWnUzMk95RE42b2tqc1ROdnFVRFpmRFZSU3BvaFIxOWkvS042WHh6NGlIQlRBSlBRNXJVV1pHL0ZRL2Nid3RxbmRkcjNHREd2bHlkTmFnMnUrYjhRc0FpWjhhNkx1d3JoUU5yYi9kYnNxSWllSnU1a3E5bmhCNU9mSS8xK08rZ3VLN0tsYWZYV0N0ZElqeFJ2TkNBNEhsVC9ocHAwaklIMHZGTkFjKzBuZEhrZzU4cW9TRzNNL0k3Z2puWDAyRWZoOHNaeXF1UHlOUHR6aTA1L1B1QVVWMXd3WC9ybGlQOCsyVGZRdFdDaXpsbElZbll1UVJzQ3lpQjBoaEx0cmNYbG5hdTV3bGpNSVZab1ZhSUltWXRBWnhGMVplVjVFZXNBNzMzM0dSZmx1YWErUmE2WlpnYU11WUR2VS9kU1ZPRFlVNWZMYkZkNVZtZXZLMnBSN2t2K28xVzBQbDh0ZU94MUN4VEE0VDRBU0MxSGdHc2htZjNWR1phbUlGcUtnQ0h2d1Q0cDEwUUFjM1cwQkZ4RzltWUN2YjdwSTBhcGxtYkp4a05rRG4yK3JwSERFY1A5TFRFNGpJUzBmZXZ2ZkdZWHRzcUdNaXk2QTJSbFMxdnZmOURobE5xdGdBRWtieFZjZnRFbThrWFdWa2xWaVpFSnFQOWg0NDZNWDlrOXdjQzFXS0lsUWt4T1pRWENpd246Ok07hUIWm2U5p0Q9mApuvuM=">
</div>
...
<div class="acf-field acf-field-text acf-field--validate-email" style="display:none !important;" data-name="_validate_email" data-type="text" data-key="_validate_email">
<div class="acf-label">
<label for="acf-_validate_email">Validate Email</label>
</div>
<div class="acf-input">
<div class="acf-input-wrap">
<input type="text" id="acf-_validate_email" name="acf[_validate_email]">
</div>
</div>
</div>
</form>
</div>
<div class="acf-form-submit">
<input type="submit" class="acf-button button button-primary button-large" value="Update">
</div>
</section>

When you didn't make changes in the fields of the form, ACF ignores the submitting. Normally the form has a hidden field with id _acf_changed and value 0. When you are editing a field this value changed to 1.
So try to add JS script AFTER YOUR FORM:
<script type="text/javascript">
var is_edit=document.getElementById('_acf_changed');
is_edit.value='1';
</script>

Related

How to add custom fields to WooCommerce product data panel

I have created a custom product type for events in WooCommerce. Now I want to add some custom fields to it.
This can be achieved with functions like woocommerce_wp_select(), woocommerce_wp_text_input() etc. However, as far as I know, whith these function you can only add text input fields, textarea's, select boxes and select dropdowns.
I want to add a date picker field, a file upload field and an url input field.
I have created these fields and they do render on the admin panel as they should, but the values are not saved (although I'm using the action hook 'woocommerce_process_product_meta'). Only the first 2 fields (event_type and event_location), which are created with the WooCommerce function, are stored properly.
What am I doing wrong here?
My code:
add_action('woocommerce_product_data_panels', 'okappi_add_custom_fields');
function okappi_add_custom_fields()
{ ?>
<div id="event_details" class="panel woocommerce_options_panel hidden">
<div class="options_group" class="show_if_event">
<? woocommerce_wp_select([
'id' => 'event_type',
'label' => __('Event type', 'custom'),
'wrapper_class' => 'show_if_event',
'value' => get_post_meta(get_the_ID(), 'event_type', true),
'options' => array('online' => 'Online', 'international' => 'International', 'internal' => 'Internal'),
]); ?>
<? woocommerce_wp_text_input([
'id' => 'event_location',
'label' => __('Event location', 'custom'),
'wrapper_class' => 'show_if_event',
'value' => get_post_meta(get_the_ID(), 'event_location', true),
]); ?>
<p class="show_if_event form-field event_start_date_field">
<label for="event_start_date">Start date</label>
<input type="date" id="event_start_date" name="event_start_date" class="date short">
</p>
<p class="show_if_event form-field event_end_date_field">
<label for="event_end_date">End date</label>
<input type="date" id="event_end_date" name="event_end_date" class="date short">
</p>
<p class="show_if_event form-field event_pdf_field">
<label for="event_pdf">PDF upload</label>
<input type="file" id="event_pdf" name="event_pdf" class="date short">
</p>
<p class="show_if_event form-field event_link_field">
<label for="event_link">Event link</label>
<input type="url" id="event_link" name="event_link" class="date short" placeholder="https://www.my-event.com/">
</p>
</div>
</div>'
<? }
add_action('woocommerce_process_product_meta', 'save_custom_fields');
function save_custom_fields($post_id)
{
$product = wc_get_product($post_id);
$event_type = isset($_POST['event_type']) ? $_POST['event_type'] : '';
$product->update_meta_data('event_type', sanitize_text_field($event_type));
$event_location = isset($_POST['event_location']) ? $_POST['event_location'] : '';
$product->update_meta_data('event_location', sanitize_text_field($event_location));
$event_start_date = isset($_POST['event_start_date']) ? $_POST['event_start_date'] : '';
$product->update_meta_data('event_start_date', sanitize_text_field($event_start_date));
$event_end_date = isset($_POST['event_end_date']) ? $_POST['event_end_date'] : '';
$product->update_meta_data('event_end_date', sanitize_text_field($event_end_date));
$event_pdf = isset($_POST['event_pdf']) ? $_POST['event_pdf'] : '';
$product->update_meta_data('event_pdf', sanitize_text_field($event_pdf));
$event_link = isset($_POST['event_link']) ? $_POST['event_link'] : '';
$product->update_meta_data('event_link', sanitize_text_field($event_link));
$product->save();
}

How to specify Symfony2 Bootstrap checkbox inline style?

The Symfony2 Boostrap template has a conditional switch on 'checkbox-inline'. How is this triggered?
{% if 'checkbox-inline' in parent_label_class %}
{{- form_label(form, null, { widget: parent() }) -}}
Since the conditional check is looking in parent_label_class, you can simply add to your form builder an option called label_attr, and there you can append your class.
Example:
$builder->add('checkbox', 'checkbox',
array(
'label_attr' => array(
'class' => 'checkbox-inline'
)
)
);
Which would give the following output:
<div class="checkbox">
<label class="checkbox-inline required">
<input type="checkbox" id="form_checkbox" name="form[checkbox]" required="required" value="1" />Checkbox
</label>
</div>

woocommerce product category search filter showing other category products

Any idea why this query is showing products inside a different parent category and it's children? http://botanicaevents.com/rentals/?s=white&product_cat=floral
It should only show the product "White Floral Product Test"
White this query works properly: http://botanicaevents.com/rentals/?s=white&product_cat=rentals
Notice how the working string above doesn't show "White Floral Product Test"
Here is the search form:
<form role="search" method="get" id="searchform" action="http://botanicaevents.com/rentals/">
<div>
<label class="screen-reader-text" for="s">Search for:</label>
<input type="text" value="" name="s" id="s" placeholder="Search for products" />
<input type="hidden" name="product_cat" value="floral" />
<input type="submit" id="searchsubmit" value="Search" />
</div>
</form>
The only variation in the form is name="product_cat" value="rentals"
The default behavior is that WordPress will search for the search term in the provided WooCommerce category and its child categories. To change that, you may have to use the pre_get_posts action to change the query itself not to include the child categories.
For example:
add_action('pre_get_posts', 'woo_alter_category_search');
function woo_alter_category_search($query) {
if (is_admin() || !is_search())
return false;
if ($product_cat = $query->get('product_cat')) {
$query->set('product_cat', '');
$query->set('tax_query', array(
array(
'taxonomy' => 'product_cat',
'field' => 'slug',
'terms' => $product_cat,
'include_children' => false,
)
));
}
}
Keep in mind that this code is not tested - it is just an example.

Formatting buttons in a form (CodeIgniter)

Just wondering how to go about giving a form in CodeIgniter a class? I've tried just formatting buttons, hoping that the submit button would change in the form, but it didn't.
echo form_open('User/feed' class='buttonClass');
echo form_submit('NF', 'News Feed');
echo form_close();
I couldn't find anything which seemed to help me online.
Thank you!
echo form_open('User/feed', array( 'class' => 'classname' ));
// will become:
<form method="post" accept-charset="utf-8" action="http:/example.com/index.php/User/feed" class="classname" />
echo form_submit('NF', 'News Feed');
// will become:
<input type="submit" name="NF" value="News Feed" />
echo form_close();
// will become:
</form></div></div>
Now keep in mind, adding classes and other attributes via the array in the first line up there only adds them to the Form line. I would recomend, if you're doing this in view, writing pure html and adding in the information needed. More like:
<form method="post" accept-charset="utf-8" action="<?= base_url('User/feed'); ?>" class="classname">
<div>
Something here for the form
<input type="text" name="stuff" />
</div>
<input type="submit" name="NF" value="News Feed" class="myButton" />
</form>
Also, of note, you can create buttons using an array and assign class and other attributes that way. Such as:
$myButton = array(
'class' => 'myButton',
'name' => 'NF',
'value' => 'News Feed',
);
echo form_button($myButton);
Lastly, and I think this is what you're aiming for, you can do the same with form_submit:
$myButton = array(
'class' => 'mySubmitButton',
'name' => 'nfSubmit',
'value' => 'Submit',
);
echo form_submit($data);
Per the documentation, the form helper accepts an array as the second parameter, allowing one to apply various options, such as a class. For example:
$attributes = array(
'class'=>'myClass'
);
echo form_open('User/feed', $attributes);
Documentation
Form Helper - http://ellislab.com/codeigniter/user-guide/helpers/form_helper.html

WordPress Radio Boxes - selects only the last one

So I have a form as shown bellow. its a bit long. It contains three radio boxes. Every time I select one, doesn't matter which, and then hit submit, the last radio element shows up as selected instead of the one I clicked. I var dump the option (in this case aisis_core['display_rows']) and it will say the value of the radio element i selected instead of the current on selected.
So I select lists, it will show lists but the radio box selected is no_posts. Can some one tell me what I am doing wrong?
<form action="options.php" method="post">
<input type='hidden' name='option_page' value='aisis_options' /><input type="hidden"
name="action" value="update" /><input type="hidden" id="_wpnonce" name="_wpnonce"
value="f0385965c6" /><input type="hidden" name="_wp_http_referer" value=
"/WordPressDev/wp-admin/admin.php?page=aisis-core-options&settings-updated=true" />
<fieldset>
<div class="control-group">
<label class="radio"><input type="radio" id="rows" class="display" name=
"aisis_core[display_rows]" value="display_rows" checked="checked" /> Display
posts as rows. </label>
<div class="control-group">
<label class="radio"><input type="radio" class="display" name=
"aisis_core[display_rows]" value="list" checked="checked" /> Display posts a
list. </label>
</div>
<div class="control-group">
<label class="radio"><input type="radio" id="noDisplay" class="display" name=
"aisis_core[display_rows]" value="no_posts" checked="checked" /> Display no
posts.</label>
<div class="no_posts_section borderBottom">
<div class="well headLine">
<h1>Display No Rows</h1>
<p>If you choose to display no rows please give me a url of the page or
content you would like to display instead.</p>
<p class="text-info"><strong>Note:</strong> Formatting of said content is
up you. All we do is display it.</p>
</div>
<div class="control-group">
<div class="controls">
<input type="url" name="aisis_core[index_page_no_posts]" value=
"http://google.ca" placeholder="Url" />
</div>
</div>
</div>
<div class="control-group">
<div class="form-actions">
<input type="submit" class="btn btn-primary btn-large" />
</div>
</div>
</div>
</div>
</fieldset>
</form>
The function I am using from wordpress is:
checked('radio_box_value', isset($options['display_rows']), false)
Note: radio_box_value is replaced with what ever the value of the radio box is.
In this case only the last radio box has the "checked" in it's tag, when it should be which ever one I chose.
How are the elements being created?
The following is how I create the elements, they print out what you see above in the html for the radio buttons. These are done similar to, but not exactly, zend framework.
Its pretty straight forward what were doing, create the element, add the options to the element and then return it.
I hope this gives a better picture as to how these are being created.
protected function _radio_rows_element(){
$options = get_option('aisis_core');
echo $options['display_rows'];
$radio_element = array(
'name' => 'aisis_core[display_rows]',
'value' => 'display_rows',
'class' => 'display',
'id' => 'rows',
'checked' => checked('display_rows', isset($options['display_rows']) && $options['display_rows'] == 'display_rows', false),
'label' => ' Display posts as rows. <a href="#radioRows" data-toggle="modal">
<i class="icon-info-sign"> </i></a>'
);
$radio = new CoreTheme_Form_Elements_Radio($radio_element, $this->sub_section_rows_array());
return $radio;
}
protected function _radio_list_element(){
$options = get_option('aisis_core');
echo $options['display_rows'];
$radio_element = array(
'name' => 'aisis_core[display_rows]',
'value' => 'list',
'class' => 'display',
'checked' => checked('list', isset($options['display_rows']) && $options['display_rows'] == 'list', false),
'label' => ' Display posts a list. <a href="#radioLists" data-toggle="modal">
<i class="icon-info-sign"> </i></a>'
);
$radio = new CoreTheme_Form_Elements_Radio($radio_element);
return $radio;
}
protected function _radio_no_posts_element(){
$options = get_option('aisis_core');
echo $options['display_rows'];
$radio_element = array(
'name' => 'aisis_core[display_rows]',
'value' => 'no_posts',
'class' => 'display',
'id' => 'noDisplay',
'checked' => checked('no_posts', isset($options['display_rows']) && $options['display_rows'] == 'no_posts', false),
'label' => ' Display no posts.</a>'
);
$radio = new CoreTheme_Form_Elements_Radio($radio_element, $this->_sub_section_now_posts_array());
return $radio;
}
"checked" function seems to need the value as second parameter as is explained here http://codex.wordpress.org/Function_Reference/checked
Try like this:
protected function _radio_rows_element(){
$options = get_option('aisis_core');
echo $options['display_rows'];
$radio_element = array(
'name' => 'aisis_core[display_rows]',
'value' => 'display_rows',
'class' => 'display',
'id' => 'rows',
'checked' => checked('display_rows', (isset($options['display_rows']))?$options['display_rows']:'', false),
'label' => ' Display posts as rows. <a href="#radioRows" data-toggle="modal">
<i class="icon-info-sign"> </i></a>'
);
$radio = new CoreTheme_Form_Elements_Radio($radio_element, $this->sub_section_rows_array());
return $radio;
}
protected function _radio_list_element(){
$options = get_option('aisis_core');
echo $options['display_rows'];
$radio_element = array(
'name' => 'aisis_core[display_rows]',
'value' => 'list',
'class' => 'display',
'checked' => checked('list',(isset($options['display_rows']))?$options['display_rows']:'', false),
'label' => ' Display posts a list. <a href="#radioLists" data-toggle="modal">
<i class="icon-info-sign"> </i></a>'
);
$radio = new CoreTheme_Form_Elements_Radio($radio_element);
return $radio;
}
protected function _radio_no_posts_element(){
$options = get_option('aisis_core');
echo $options['display_rows'];
$radio_element = array(
'name' => 'aisis_core[display_rows]',
'value' => 'no_posts',
'class' => 'display',
'id' => 'noDisplay',
'checked' => checked('no_posts', (isset($options['display_rows']))?$options['display_rows']:'', false),
'label' => ' Display no posts.</a>'
);
$radio = new CoreTheme_Form_Elements_Radio($radio_element, $this->_sub_section_now_posts_array());
return $radio;
}
This will not give warning when isn't declared the variable $options['display_rows'] (that as you said is a possibility in your case) and will pass the value to the WordPress function to compare with.
You'll want to check the value in the checked condition, not you're just checking if any value is being selected, which is always true after a submit
change
checked('display_rows', isset($options['display_rows']), false)
to:
checked('display_rows', isset($options['display_rows']) && $options['display_rows'] == 'display_rows', false),
and for the list to:
checked('display_rows', isset($options['display_rows']) && $options['display_rows'] == 'list', false),
I did manage to write this:
public function set_element_checked($value, $option, $key){
$options = get_option($option);
if(isset($options[$key]) && $options[$key] == $value){
return 'checked';
}
}
which does exactly what I want. compare the element value to that of the $option[$key] and if they match return checked. can be called via:
'checked' => set_element_checked('display_rows', 'aisis_core', 'display_rows');

Resources