How to build widget with arrays inside arrays?

enter image description here

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 here. 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).

// 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).

Read more here:: How to build widget with arrays inside arrays?

Leave a Reply

Your email address will not be published. Required fields are marked *