Saving multiple fields (dropdown and text) in custom metabox

It looks like the variable you’re using to set the selected item is not defined in that scope.

In your constructor:

    public function __construct() {
        if ( is_admin() ) {
            add_action( 'load-post.php',     array( $this, 'init_metabox' ) );
            add_action( 'load-post-new.php', array( $this, 'init_metabox' ) );            
        }

        $this->dropdown_args = [
            'show_option_none' => '- select a page -',
            'option_none_value' => 'no page selected',
            'id'               => 'landing_page',
            'name'             => 'landing_page',
            'value_field'      => 'landing_page',
            'selected'         => $landing_page
        ];
    }

$landing_page is not defined here.

I’m not completely familiar with all your code, but for the other field you use get_post_meta( $post->ID, 'description', true ) to get the current value for that field.

As $post isn’t available in your constructor you need to correctly set the selected argument in render_landing(). Perhaps something like:

Replace:

    <?php wp_dropdown_pages($this->dropdown_args); ?>

With:

    <?php 
    $args = $this->dropdown_args; 
    $args['selected'] = get_post_meta( $post->ID, 'landing_page', true );
    wp_dropdown_pages($args);
    ?>

As your code is nice and clean I guess you’d want to tidy up the constructor so it isn’t setting the selected field to an empty value, and you could make the string landing_page a class-level variable or constant so that it doesn’t get repeated in different places.

Let me know if that works