Dynamic Lists?
-
Hi,
This is the first time using your plugin, and I like the look of it so far. A quick question:- is it possible to have a dynamic list?
I’m looking to have a list of WooCommerce products in a form, and it would be great to have this be dynamic so the products don’t need to be added to the form manually when entering a product in WooCommerce.
Is there a hook I can use to generate the list items on the fly?
Thanks in advance
-
Hey,
You can absolutely do that. We have tried to make Ninja Forms as extensible and flexible as possible. Almost every aspect of display, admin, and processing can be modified without ever touching the core plugin code.
There are two ways you could handle your use case: the first would be to create a list field and then filter the options values before it is displayed. To do this, you would use the ninja_forms_field WordPress filter. This filter is sent an array named $data that has every piece of information required to display the field. The list options are stored inside this array like: $data[‘data’][‘list’][‘options’]. The options array should look like this: array( ‘name’ => ‘Option 1’, ‘value’ => ‘option1’). The value is optional, and if it’s not sent the ‘name’ will be used for the ‘value’ as well. In this approach you would create an empty list field in the back-end, and then you would check the field ID in your filter to make sure you only changed the empty field. We are still working on documentation for the plugin, so I apologize that I can’t just point you to a doc with an example.
The second method is to register your own custom field. This field could then be re-used in any forms you wanted; you could even add some options to the backend to make it even more dynamic. I think if I were doing it, I would use this method. To register a new field, you create an array with some field options, a display function, back-end field options (if you need them), custom processing function(s) (if you need them), and Ninja Forms takes care of the rest.
There is a doc related to this: https://wpninjas.com/ninja-forms/docs/ninja_forms_register_field-2/
If you want more examples, all of the fields within ninja-forms/includes/fields/ are added with this method. The field will then behave like any other Ninja Forms field: it will get emailed, saved in the submission database, etc.
I hope that helps. If you have any other questions, please let me know.
Ooops, forgot to mention that the ‘ninja_forms_field’ filter is sent $data (which is the thing being filtered) and $field_id (which is the ID of the field currently being displayed). Apologies for forgetting to throw that in there.
That’s great, and thanks for the quick and comprehensive reply. This will also help me with something else I’m working on as we speak – to pre-populate a form based on data posted to a page.
Thanks again!
No problem! Glad I could help. If, in your trials, you find that you need a specific hook or filter and can’t find it, let me know and we’ll try to throw it in there. I know that I can’t come up with every use-case and hook or filter that might be needed.
Yup. If you are pre-populating the data, you’ll definitely need the filter.
Sigh. If I could remember to type my whole message before I click “Post,” that would be awesome. Anyway, I was just going to say that to change the pre-populated value, you’ll want to modify $data[‘data’][‘default_value’].
Yes the filter just saved having to mess around with jquery and is already done – the filter is a much more robust way of pre-populating.
If it helps anyone else, add this to your functions file to pre-populate your values. The example below pre-populates a dropdown and three text fields. Just remove/duplicate as needed and change the references to the form items:
// filter runs every time a form element is rendered add_filter('ninja_forms_field','apply_prepop'); function apply_prepop($data) { // check which form element is being displayed, and if we have a value being posted, select/replace it if($data['label']=='Title' && $_POST['apply-title']) { foreach ($data['list']['options'] as $key => $value) { if($value['label'] == $_POST['apply-title']) { $data['list']['options'][$key]['selected'] = 1; } } } if($data['label']=='First name' && $_POST['apply-name']) { $data['default_value'] = $_POST['apply-name']; } if($data['label']=='Last name' && $_POST['apply-surname']) { $data['default_value'] = $_POST['apply-surname']; } if($data['label']=='Email Address' && $_POST['apply-email']) { $data['default_value'] = $_POST['apply-email']; } return $data; }
Hi Kevin,
Further to my original query, and thanks to the link you posted, I have been able to create a custom field and populate it with woocommerce products.
My new field shows in admin, and displays the products correctly, and I’m able to add it to my form, but I can’t get it to display on the front-end.
The example on the link you posted is for a text field only, so I tried to copy from the examples within the plugin /includes/fields/ directory, but I’m not able to get it to work – it just displays an empty dropdown. If I just print out the data, it only shows the first product in my list. Do you have any ideas how I can display the list on the front-end? I thought you might have a quick pointer to help?
Kind thanks
// create a new field type for woocommerce products // get a list of woo products $woo_args = array ( 'post_type' => 'product', 'posts_per_page' => 5 ); $woo_products = get_posts($woo_args); $woo_products_select = array(); foreach($woo_products as $woo_product) { $woo_products_select_item = array( 'name' => $woo_product->post_title, 'value' => 'product-'. $woo_product->ID .'-'. $woo_product->post_name ); array_push($woo_products_select, $woo_products_select_item); } // create the custom ninja field using the woo products $args = array( 'name' => 'Product List', 'edit_options' => array( array( 'type' => 'select', 'name' => 'select_woo_products', 'label' => 'WooCommerce Products', 'options' => $woo_products_select, ), ), 'display_function' => 'select_woo_products_display', 'sidebar' => 'template_fields' ); if( function_exists( 'ninja_forms_register_field' ) ) { ninja_forms_register_field('select_woo_products', $args); } /* * This function only has to output the specific field element. The wrap is output automatically. * * $field_id is the id of the field currently being displayed. * $data is an array the possibly modified field data for the current field. * */ function select_woo_products_display( $field_id, $data ){ // should output the list within here print_r($data); // just outputs the first item in the list - how do I get all of the items? }
Hey,
In the code above, you’re adding the Woo products as a select option on the back-end. The “edit_options” array is a collection of back-end, field editing settings. The code as you have it at the moment pulls a list of products into a select element, but it’s a select dropdown on the back-end field editor. That select option can only have one value, so in the display function, you’re seeing that one value.
If you want to get a list of all the products and output them as a select list, you’ll need to move your options generation code down into your display function. Something like:
function select_woo_products_display( $field_id, $data ){ // Get the default_value if( isset( $data['default_value'] ) ){ $default_value = $data['default_value']; }else{ $default_value = ''; } // should output the list within here // get a list of woo products $woo_args = array ( 'post_type' => 'product', 'posts_per_page' => 5 ); $woo_products = get_posts($woo_args); $woo_products_select = array(); foreach($woo_products as $woo_product) { $woo_products_select_item = array( 'name' => $woo_product->post_title, 'value' => 'product-'. $woo_product->ID .'-'. $woo_product->post_name ); array_push($woo_products_select, $woo_products_select_item); } // Now that $woo_products_select is populated with the options, output a select box for the user to select from. <select name="ninja_forms_field_<?php echo $field_id;?>"> <?php // Loop through your products and output the options here. ?> </select> // just outputs the first item in the list - how do I get all of the items? }
I hope that helps. If doesn’t, just let me know.
My bad, I didn’t fully understand how the functions worked for registering a ninja field. It of course makes much more sense to generate the list on the display function, rather than when creating the form.
OK, I’ve tweaked what we both wrote, and this seems to work (copied here for the benefit of others).
- I tested adding a new woo product, and it added the product to the form
- I submitted the form, the product was stored correctly
- I tested editing the submission, this worked fine
- I downloaded the submissions, and the product selection was included
// Create a new custom field type for Ninja Forms that lists woocommerce products // Register the custom WooCommerce Products Ninja Forms field $args = array( 'name' => 'Product List', 'edit_options' => array( array( 'type' => 'select', 'name' => 'select_woo_products', 'label' => 'WooCommerce Product List', 'options' => array( array('name' => 'Products are added to the form automatically', 'value' => '') ) ), ), 'display_function' => 'select_woo_products_display', 'edit_function' => 'select_woo_products_edit', 'sidebar' => 'template_fields' ); if( function_exists( 'ninja_forms_register_field' ) ) { ninja_forms_register_field('select_woo_products', $args); } // Display of the custom WooCommerce Products Ninja Forms field function select_woo_products_display( $field_id, $data ){ // Get the default_value if( isset( $data['default_value'] ) ){ $default_value = $data['default_value']; }else{ $default_value = ''; } // Get the list of WooCommerce products $woo_products_select = get_woo_product_select_values(); // Now that $woo_products_select is populated with the options, output a select box for the user to select from. ?> <select name="ninja_forms_field_<?php echo $field_id;?>"> <option value="">Please select...</option> <?php foreach($woo_products_select as $woo_products_select_option) { ?> <option value="<?php echo $woo_products_select_option['value']; ?>"<?php echo ($woo_products_select_option['value']==$default_value) ? ' selected' : ''; ?>><?php echo $woo_products_select_option['name']; ?></option> <?php } ?> </select> <?php } // Edit of the custom WooCommerce Products Ninja Forms field function select_woo_products_edit( $field_id, $data ){ // Get the default_value if( isset( $data['default_value'] ) ){ $default_value = $data['default_value']; }else{ $default_value = ''; } // Get the list of WooCommerce products $woo_products_select = get_woo_product_select_values(); // Now that $woo_products_select is populated with the options, output a select box for the user to select from. ?> <select name="ninja_forms_field_<?php echo $field_id;?>"> <?php foreach($woo_products_select as $woo_products_select_option) { ?> <option value="<?php echo $woo_products_select_option['value']; ?>"<?php echo ($woo_products_select_option['value']==$default_value) ? ' selected' : ''; ?>><?php echo $woo_products_select_option['name']; ?></option> <?php } ?> </select> <?php } // Function that generates a dynamic list of woocommerce products to be used in a select list function get_woo_product_select_values() { $woo_args = array ( 'post_type' => 'product', 'posts_per_page' => -1, 'order' => 'ASC', 'orderby' => 'title' ); $woo_products = get_posts($woo_args); $woo_products_select = array(); foreach($woo_products as $woo_product) { $woo_products_select_item = array( 'name' => $woo_product->post_title, 'value' => 'product-'. $woo_product->ID .'-'. $woo_product->post_name ); array_push($woo_products_select, $woo_products_select_item); } return $woo_products_select; }
Thanks for your help Kevin – this is the first time I’ve used Ninja Forms, I’m a convert already ??
Ha! Thanks for the kind words. I apologize that you had to write here instead of just looking at some docs. We are working on it, but sadly, docs have the lowest priority behind client work and plugin support.
You actually don’t need the “Edit” function unless you have settings that you want to save on the backend. Those are there so that you can add settings to the back-end editor. If your front-end display is the same every time, you don’t need an edit function or “edit_options.”
Again, if you find that you need some hooks or filters that aren’t there, we’re more than happy to listen to developers! ??
Just wanted to post two links that I’ve put together since this question was asked:
This is an example of registering a new custom field type for capturing user IP addresses: https://wpninjas.com/ninja-forms/docs/capturing-the-ip-address-of-a-form-submitter/
This is a document that does a better job of explaining the extra field values I mentioned a few posts above: https://wpninjas.com/ninja-forms/docs/using-extra-field-values/
Fantastik post. Thanks a lot. I’ve been looking for something like this for a long time.
Thanks for all the posts here, very helpful, and made me realise that there’s a lot I don’t know about global variables.
I have Ninja form ‘Donate Box’ with a text input to take ‘amount’ string which posts to a page called ‘monthly-donation’ with a ninja form ‘monthly donation’ this has several fields such as ‘name and address’ and an ‘amount’ which I want to pre populate with ‘Donate Box’ value of amount.
Using crdunst tips I’ve managed to pre populate ‘monthly donation’ (with a string I manually insert into the functions file (to so I half way there)) with this function:
$user_value = 'donate box value amount';//how do I get this value? // filter runs every time a form element is rendered add_filter('ninja_forms_field','apply_prepop'); function apply_prepop($data) { if($data['label']=='Pay the sum of') { $data['default_value'] = $GLOBALS['user_value'];//and pop it in here } return $data; //this returns 'donate box value amount' literally }
but I can’t find a way to change $user_value to ‘Donate Box’ value of amount.
Basically, how do I get a value from a posted form and put it into a global variable. Or not even put in in a global variable and inject it straight into the pre pop function.
Hi jon,
Instead of creating a variable first, just pull the value in within your function, but only if you have a value being posted.
Try the following assuming the input of your first donate box being posted to your second form is called ‘user-value’:
// filter runs every time a form element is rendered add_filter('ninja_forms_field','apply_prepop'); function apply_prepop($data) { // if this is the field you want to pre-pop, and we have a value being posted from the previous form... if($data['label']=='Pay the sum of' && $_POST['user-value']) { $data['default_value'] = $_POST['user-value']; } return $data; //this returns 'donate box value amount' literally }
HI all,
interesting stuff, I wonder if there is simple way to create a field for NinjaForms that can get the price (normal or sale) of a WooCommerce product when the form is place on a product page? That way I can create a real easy form for visitor to quickly calculate what a certain amount of that product costs without leaving the page. Any help would be appreciated…Kind regards,
Menno Borst
- The topic ‘Dynamic Lists?’ is closed to new replies.