AJAX Implementation

First, enqueue your script correctly, in functions.php:

function my_enqueue_scripts() {
   wp_enqueue_script('jquery');
}
add_action('wp_enqueue_scripts', 'my_enqueue_scripts');

Then, Authenticated users only (see https://codex.wordpress.org/Plugin_API/Action_Reference/wp_ajax_nopriv_(action))
(can also be in functions.php):

function fetchData(){

    // Not needed anymore, as you manage the case through the `add_action` method
    // if ( ! is_user_logged_in()  ) {
    //    return;
    // }

    // this can be improved
    $catId = isset($_REQUEST['catId']) ? $_REQUEST['catId'] : '';
    echo "<option>$catId</option>"; // there was a typo here: `<optio>`

    die();
}

// add your ajax action to authenticated users only
add_action('wp_ajax_fetch_data','fetchData');

// no need for the `nopriv_` action, this one is for anonymous users
// add_action('wp_ajax_nopriv_fetch_data','fetchData');?>

And finally, your JS script. You must add the action parameter, otherwise WordPress does not know which action to fire in the backend (the one used in wp_ajax_fetch_data -> fetch_data).
Also, for the url, try to use admin_url( 'admin-ajax.php' ); instead:

<script type="text/javascript">

jQuery(document).ready( function(){

  jQuery('#category').on('change',function (){
      console.log("start1");
      var catId = document.getElementById('category').value;
      console.log(catId);
      jQuery.ajax({
        type: 'POST',
        url: "<?php echo admin_url( 'admin-ajax.php' ); ?>",
        data: {
            'key':catId,
            'action': "fetch_data" // very important
        },
        cache: false,
        success : function (data) {
                 jQuery('#sub_cat').html(data); 
                    console.log(data);
                }
      });
  });
});

</script>

Leave a Comment