Support Forum
Support › MB Custom Table › Add Image To Advanced Select OptionResolved
Hey there! I've got something I have been struggling to figure out, and could use some guidance. The end goal for me, is simply just to be able display an image next to each of my advanced select options. I know it is possible using Select2s templating stuff, but I am struggling to get that to work using an actual select field through MetaBox. The only way I have been able to (sort of) achieve this so far, is with a Custom HTML field. The only problem with this, is that the value selected in this field is not being saved to the database. I wasn't sure if it would be better to try and convert what I have into an advanced select field, or just figure out how to save / display the values from a custom html field instead. Here is custom HTML field I currently have:
[
'name' => 'Alert Type',
'id' => $prefix . 'alert_type',
'type' => 'custom_html',
'std' => '<head>
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/select2/4.0.5/css/select2.css" />
</head>
<body>
<select id="alert_type" style="width: 100%">
<option value="Low" data-img_src="/wp-content/uploads/2022/12/Low.png">Low</option>
<option value="High" data-img_src="/wp-content/uploads/2022/12/High.png">High</option>
<option value="Usage" data-img_src="/wp-content/uploads/2022/12/Usage.png">Usage</option>
<option value="Non-Usage" data-img_src="/wp-content/uploads/2022/12/NonUsage.png">Non-Usage</option>
</select>
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/select2/4.0.5/js/select2.js"></script>
<script type="text/javascript">
function custom_template(obj){
var data = $(obj.element).data();
var text = $(obj.element).text();
if(data && data[\'img_src\']){
img_src = data[\'img_src\'];
template = $("<div><img src=\\"" + img_src + "\\" style=\\"vertical-align: middle; width: 25px; margin-right: 20px; \\">" + text + "</div>");
return template;
}
}
var options = {
\'templateSelection\': custom_template,
\'templateResult\': custom_template,
}
$(\'#alert_type\').select2(options);
$(\'.select2-container--default .select2-selection--single\').css({\'height\': \'100%\', \'padding\': \'10px 0px\'});
$(\'.select2-container--default .select2-selection--single .select2-selection__arrow\').css({\'height\': \'100%\'});
</script>
</body>',
'width' => '10px',
'admin_columns' => [
'sort' => true,
'searchable' => true,
'filterable' => true,
],
],
I would greatly appreciate any help I can get. Thanks in advance!
Hello Jeremy,
The field type custom_html does not save the field value so it does not work in your case. I think you can create a custom field type to accomplish the task. Please read more on the documentation
https://docs.metabox.io/creating-new-field-types/
I appreciate the quick response! I hadn't considered making my own field, so thanks for the suggestion! I'll play around with it a little and see what I am able to figure out. Thanks!
Hey Peter, another question for you. So I was able to get everything displaying correctly by using a custom field type like you suggested, but I am still having trouble getting the selected value to save. If you look, you will see that I have "value" properties set for each one of my options, which let me conditionally show / hide other fields in my form, which seem to be work. But after submitting, I noticed that the selected option is not being saved to the database, and when I go back into that model to "edit" that entry, the select menu just displays the first option in the list, instead of the actual choice that I had made. All of my other fields seem to saving correctly, while this custom field type remains blank. I am still very new to PHP, and MetaBox at that, so I would appreciate any help you'd be able to provide. Thanks!
/** Creating A Custom Field Type **/
add_action( 'init', 'prefix_load_alert_type' );
class RWMB_Alert_Type_Field extends RWMB_Field {
public static function html( $meta, $field ) {
return sprintf('
<head>
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/select2/4.0.5/css/select2.css" />
<link rel="stylesheet" href="/wp-content/themes/Divi Child Theme/style.css" />
</head>
<body>
<select id="alert_type">
<option value="Low" data-img_src="/wp-content/uploads/2022/12/Low.png">Low</option>
<option value="High" data-img_src="/wp-content/uploads/2022/12/High.png">High</option>
<option value="Usage" data-img_src="/wp-content/uploads/2022/12/Usage.png">Usage</option>
<option value="Non-Usage" data-img_src="/wp-content/uploads/2022/12/NonUsage.png">Non-Usage</option>
</select>
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/select2/4.0.5/js/select2.js"></script>
<script type="text/javascript">
function custom_template(obj){
var data = $(obj.element).data();
var text = $(obj.element).text();
if(data && data[\'img_src\']){
img_src = data[\'img_src\'];
template = $("<div><img src=\" "+ img_src +" \"> <p> "+ text +" </p> </div>");
return template;
}
}
var options = {
\'templateSelection\': custom_template,
\'templateResult\': custom_template,
}
$(\'#alert_type\').select2(options);
</script>
</body>
',
$field['Alert Type'],
$field['alert_type'],
$meta
);
}
}
Model Code:
[
'name' => 'Alert Type',
'id' => 'alert_type',
'type' => 'alert_type',
'admin_columns' => [
'sort' => true,
'searchable' => true,
'filterable' => true,
],
],
[
'name' => 'Alert Value (%)',
//'id' => $prefix . 'alert_value_percent',
'id' => $prefix . 'trigger_value',
'type' => 'slider',
'suffix' => __( '%', 'alerts' ),
'js_options' => [
'min' => 0,
'max' => 100,
'step' => 5,
],
'admin_columns' => [
'sort' => true,
'searchable' => true,
'filterable' => true,
],
'visible' => [
'when' => [['alert_type', '=', 'Low'], ['alert_type', '=', 'High']],
'relation' => 'or',
],
],
[
'name' => 'Alert Value (Gallons)',
//'id' => $prefix . 'alert_value_gallons',
'id' => $prefix . 'trigger_value',
'type' => 'slider',
'suffix' => __( ' gal', 'alerts' ),
'js_options' => [
'min' => 0,
'max' => 500,
'step' => 5,
],
'admin_columns' => [
'sort' => true,
'searchable' => true,
'filterable' => true,
],
'visible' => [
'when' => [['alert_type', '=', 'Usage'], ['alert_type', '=', 'Non-Usage']],
'relation' => 'or',
],
],
Quick Update:
Looks like I was able to get this value saving to the database correctly by adding name="alert_type" in my custom field select definition. The only thing I am still having issues with now, is having the correct option display when viewing / editing a record. Even though the correct value is captured to the database on submission, the selection being displayed does not match its actual value, and seems to switch to the first available option once the page refreshes.
Does anyone know if it is possible to display the selected value when viewing / editing an existing record with this? The value is saving to the database correctly, it is just not displaying that way after I create the record, and go back into it. It seems to be just defaulting to the first option in the list, and not the correct value. Any help would be appreciated. Thanks!
Hello,
To display the selected value you can use the attribute selected
for the select option, please read more here https://www.w3schools.com/tags/att_option_selected.asp
and to get the saved field value, please use the variable $meta
, you can see the sample code in the documentation to know how it works https://docs.metabox.io/creating-new-field-types/#adding-a-method-to-output-the-field
I don't believe this is quite what I am looking for, so I'll try to explain my issue a a little better. I think I am running into issues because this is custom field type trying to piggyback off of the way a select field works, and not an actual select field itself. When I am on the "Add New" form for this model, the alert type defaults to the "Low" option, (I'm guessing because it is the first choice in the list). This default option doesn't matter for the "Add New" form, but the "Edit" form needs to display its actual saved value, not just the first option in the list again. While on the "Add New" form, if I were to try and change this field to "High" and click save, the "High" option is correctly saved to the database, but since the view changes to the "Edit" screen upon submission, the field immediately switches back to showing "Low" as the selected option, instead of its actual saved value. I am trying to figure out how to get this "Edit" screen to display the value it has saved in the database for each appropriate record. Hopefully that makes a little more sense? Thanks!
Hello,
Thanks, I understand that you need to display the saved value when editing the post. I already said you need to use the selected
attribute of the <option>
tag to display the saved value first instead of Low
value. You can read more on this topic https://wordpress.stackexchange.com/questions/105471/how-to-mark-an-option-as-selected
For example:
<?php
if( $meta == 'High' ) {
$select = 'selected';
}
?>
<select id="alert_type">
<option value="Low" data-img_src="/wp-content/uploads/2022/12/Low.png">Low</option>
<option value="High" <?php echo $select ?> data-img_src="/wp-content/uploads/2022/12/High.png">High</option>
<option value="Usage" <?php echo $select ?> data-img_src="/wp-content/uploads/2022/12/Usage.png">Usage</option>
<option value="Non-Usage" data-img_src="/wp-content/uploads/2022/12/NonUsage.png">Non-Usage</option>
</select>
Then you can select High
and Usage
value to see how it works.
Please note that, supporting customization code is beyond our scope of support, you can read more here https://support.metabox.io/topic/support-policy/.
If it still does not work, you can request a customization service by submitting here https://metabox.io/contact/
I appreciate the quick reply. I will play around with that a bit, and see if I can get it figured out. Thank you so much for all your help!
Hey Peter,
Thanks again for your guidance on this. Like I mentioned before I am still pretty new to MetaBox, so I like to make sure I am not "running into a door that won't open" if that makes sense. I was able to make some progress on this thanks to your suggestion. I was having some weird issues trying to use the $meta variable inside of that return sprintf(' section though. The only way that I could get the code you provided me to work, is if I moved everything outside of that. Functionally, everything is working exactly how we were hoping. The correct value now displays by default. The only issue that I am running into now, is that our custom field is not displaying inside its appropriate field wrapper, so it is out of line with the rest of the fields. For some reason, this field is now showing up in between the "rwmb-field rwmb-select_advanced-wrapper" and the "rwmb-field rwmb-alert_type-wrapper", instead of being inside of the "rwmb-field rwmb-alert_type-wrapper". Is there an easy way to make this field display in its correct section, or am I going to have to try something different? Thank you again for all your help. Here is what my code currently looks like:
Custom Field Type Code:
/** Create A Custom Field Type **/
add_action( 'init', 'prefix_load_alert_type' );
class RWMB_Alert_Type_Field extends RWMB_Field {
public static function html( $meta, $field ) {
if( $meta == 'Low' ) {
$select1 = 'selected';
}
else if( $meta == 'High' ) {
$select2 = 'selected';
}
if( $meta == 'Usage' ) {
$select3 = 'selected';
}
else if( $meta == 'Non-Usage' ) {
$select4 = 'selected';
}
?>
<head>
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/select2/4.0.5/css/select2.css" />
<link rel="stylesheet" href="/wp-content/themes/Divi Child Theme/style.css" />
</head>
<body>
<select id="alert_type" name="alert_type">
<option value="Low" <?php echo $select1 ?> data-img_src="/wp-content/uploads/2022/12/Low.png">Low</option>
<option value="High" <?php echo $select2 ?> data-img_src="/wp-content/uploads/2022/12/High.png">High</option>
<option value="Usage" <?php echo $select3 ?> data-img_src="/wp-content/uploads/2022/12/Usage.png">Usage</option>
<option value="Non-Usage" <?php echo $select4 ?> data-img_src="/wp-content/uploads/2022/12/NonUsage.png">Non-Usage</option>
</select>
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/select2/4.0.5/js/select2.js"></script>
<script type="text/javascript">
function custom_template(obj){
var data = $(obj.element).data();
var text = $(obj.element).text();
if(data && data['img_src']){
img_src = data['img_src'];
template = $("<div><img src=\" "+ img_src +" \"> <p> "+ text +" </p> </div>");
return template;
}
}
var options = {
'templateSelection': custom_template,
//'templateResult': custom_template,
}
$('#alert_type').select2(options);
</script>
</body>
<?php
<em><strong>return sprintf('',</strong></em> // Everything used to be inside these quotes
$field['field_name'],
$field['id'],
$meta
);
}
}
Metabox Code
$meta_boxes[] = [
'title' => 'Alert Details',
'models' => ['alert'], // Model name
'storage_type' => 'custom_table', // Must be 'custom_table'
'table' => 'alert_table', // Custom table name
'fields' => [
[
'name' => 'User ID',
'id' => $prefix . 'user_id',
'type' => 'text',
'std' => $user->ID,
'admin_columns' => [
'sort' => true,
'searchable' => true,
'filterable' => true,
],
],
[
'name' => 'Alert Platform',
'id' => $prefix . 'alert_platform',
'type' => 'text',
'std' => 'LevelVision',
'admin_columns' => [
'sort' => true,
'searchable' => true,
'filterable' => true,
],
],
[
'name' => 'Monitor ID',
'id' => $prefix . 'monitor_id',
'type' => 'select_advanced',
//'multiple' => 'true',
//'select_all_none' => 'true',
// Use our array that we created earlier
'options' => $tankArray,
'placeholder' => 'Select A Device',
'admin_columns' => [
'sort' => true,
'searchable' => true,
'filterable' => true,
],
],
<strong>[
'name' => 'Alert Type',
'id' => $prefix . 'alert_type',
'type' => 'alert_type',
'admin_columns' => [
'sort' => true,
'searchable' => true,
'filterable' => true,
],
],</strong>
[
'name' => 'Alert Value (%)',
'id' => $prefix . 'alert_value_percent',
//'id' => $prefix . 'trigger_value',
'type' => 'slider',
'suffix' => __( '%', 'alerts' ),
'js_options' => [
'min' => 0,
'max' => 100,
'step' => 5,
],
'admin_columns' => [
'sort' => true,
'searchable' => true,
'filterable' => true,
],
'visible' => [
'when' => [['alert_type', '=', 'Low'], ['alert_type', '=', 'High']],
'relation' => 'or',
],
],
[
'name' => 'Alert Value (Gallons)',
'id' => $prefix . 'alert_value_gallons',
//'id' => $prefix . 'trigger_value',
'type' => 'slider',
'suffix' => __( ' gal', 'alerts' ),
'js_options' => [
'min' => 0,
'max' => 500,
'step' => 5,
],
'admin_columns' => [
'sort' => true,
'searchable' => true,
'filterable' => true,
],
'visible' => [
'when' => [['alert_type', '=', 'Usage'], ['alert_type', '=', 'Non-Usage']],
'relation' => 'or',
],
],
[
'name' => 'Email',
'id' => $prefix . 'alert_email',
'type' => 'email',
'std' => $user->user_email,
'admin_columns' => [
'sort' => true,
'searchable' => true,
'filterable' => true,
],
],
[
'name' => 'Status',
'id' => $prefix . 'alert_active',
'type' => 'switch',
'style' => 'rounded',
'on_label' => 'Active',
'off_label' => 'Inactive',
'std' => true,
'admin_columns' => [
'sort' => true,
'searchable' => true,
'filterable' => true,
],
],
],
];
return $meta_boxes;
}
In case anyone else is curious, I revisited this and ended up getting it to work with the following code:
/** Create A Custom Field Type **/
add_action( 'init', 'prefix_load_alert_type' );
class RWMB_Alert_Type_Field extends RWMB_Field {
public static function html( $meta, $field ) {
// Check to see if the current alert has a selected Alert Type. If it does, add a :selected tag so the HTML displays the correct option by default
if( $meta == 'Low' ) {
$select1 = 'selected';
}
else if( $meta == 'High' ) {
$select2 = 'selected';
}
if( $meta == 'Usage' ) {
$select3 = 'selected';
}
else if( $meta == 'Non-Usage' ) {
$select4 = 'selected';
}
// Used to capture following block of HTML as PHP variable
ob_start(); ?>
<head>
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/select2/4.0.5/css/select2.css" />
<link rel="stylesheet" href="/wp-content/themes/Divi Child Theme/style.css" />
</head>
<body>
<select id="alert_type" name="alert_type">
<option value="Low" <?php echo $select1 ?> data-img_src="/wp-content/uploads/2022/12/Low.png">Low</option>
<option value="High" <?php echo $select2 ?> data-img_src="/wp-content/uploads/2022/12/High.png">High</option>
<option value="Usage" <?php echo $select3 ?> data-img_src="/wp-content/uploads/2022/12/Usage.png">Usage</option>
<option value="Non-Usage" <?php echo $select4 ?> data-img_src="/wp-content/uploads/2022/12/NonUsage.png">Non-Usage</option>
</select>
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/select2/4.0.5/js/select2.js"></script>
<script type="text/javascript">
function custom_template(obj){
var data = $(obj.element).data();
var text = $(obj.element).text();
if(data && data['img_src']){
img_src = data['img_src'];
template = $("<div><img src=\" "+ img_src +" \"> <p> "+ text +" </p> </div>");
return template;
}
}
var options = {
'templateSelection': custom_template,
//'templateResult': custom_template,
}
$('#alert_type').select2(options);
</script>
</body>
<?php $html = ob_get_clean();
// End of HTML block, grab everything and assign it to a variable that we can user later
return sprintf($html,
$field['field_name'],
$field['id'],
$meta
);
}
}
My only problem now, is that I can't use any of this on the front-end like I was thinking I could. Is there another way that I can achieve this? Ultimately, I want my front-end users to only see rows assigned to them, and be able to add new / edit existing entries. Thanks!
Unfortunately, we weren't able to achieve exactly what we wanted with this, since Models do not have the front-end functionality that we thought they did. We ended up creating some custom forms / field types that save directly to our database using Gravity Forms, so we will be going that route instead. This ticket can be closed. Thanks!