I've started building a widget that needs to have an array inside an array. I'm trying to get the widget to have the ability to create multiple elements that will display on the site, but also has multiple fields inside each element...but after a couple days of searching and trying various things, I haven't had much luck getting it sorted out. I'm hoping someone can help straighten out the errors in my code here. It isn't saving the field data to the database, so I don't have the update command finding the values properly. If I adjust "$this->get_field_id('inner_elements')" and "$this->get_field_name('inner_elements')" in the first $fields['icontxt'] element and change "inner_elements" to "elements", it does save, but only the data for the last array element (to all three values, since I haven't figured out how to specify it in the update function). However, if I change all three from "inner_elements" to "elements", it doesn't work at all. In this code, I'm just trying to display 3 fields, then save the results, but I plan on building in a drop down list and other controls once this is working (so they won't all be the same input tag).
From what I can guess, it seems the majority of my problems are in the way I'm naming the "id" and "name" in the input tags (inside $fields) and I need to save each specifically in the update function.
// Widget Backend
public function form( $instance ) {
$title = isset ($instance['title']) ? $instance['title'] : 'New Title';
$elements = isset ($instance['elements']) ? $instance['elements'] : array();
$elements_num = count($elements);
$elements[$element_num + 1] = '';
$elements_counter = 0;
$inner_elements_counter = 0;
foreach($elements as $element){
$inner_elements = isset($instance['elements']['inner_elements']) ? $instance['elements']['inner_elements'] : array(
'icontxt' => 'The Icon Text',
'iconlnk' => 'The Icon Link',
'iconlnktrgt' => 'Link Target'
);
$fields = array();
$fields['icontxt'] = sprintf(
'<input class="widefat" id="%1$s" name="%2$s[%3$s]" value="%4$s">',
$this->get_field_id('inner_elements'),
$this->get_field_name('inner_elements'),
$elements_counter,
esc_attr($inner_elements['icontxt'])
);
$fields['iconlnk'] = sprintf(
'<input class="widefat" id="%1$s" name="%2$s[%3$s]" value="%4$s">',
$this->get_field_id('inner_elements'),
$this->get_field_name('inner_elements'),
$elements_counter,
esc_attr($inner_elements['iconlnk'])
);
$fields['iconlnktrgt'] = sprintf(
'<input class="widefat" id="%1$s" name="%2$s[%3$s]" value="%4$s">',
$this->get_field_id('inner_elements'),
$this->get_field_name('inner_elements'),
$elements_counter,
esc_attr($inner_elements['iconlnktrgt'])
);
$elements_counter += 1;
}
//displays the widget in admin
print 'Elements<br />' . join('<br />', $fields);
}
// Updating widget replacing old instances with new
public function update( $new_instance, $old_instance ) {
$instance = $old_instance;
$instance['title'] = esc_html($new_instance['title']);
$instance['elements'] = array();
$instance['elements']['inner_elements'] = array();
if(isset($new_instance['elements'])){
foreach($new_instance['elements'] as $element){
if('' !== trim($element)){
//$instance['inner_elements'] = array();
foreach($new_instance['inner_elements'] as $inner_element){
//$instance['elements']['inner_elements'][] = $inner_element;
$instance['elements']['inner_elements']['icontxt'] = $inner_element;
$instance['elements']['inner_elements']['iconlnk'] = $inner_element;
$instance['elements']['inner_elements']['iconlnktrgt'] = $inner_element;
}
}
}
}
return $instance;
}
Here's a general idea of where I'm headed:
The button will allow someone to select an image/icon, then the other fields will be additional values to that image/icon. Clicking the plus symbol will allow the user to create a new image/icon (array) and related fields (inner array).