Grilled Stuffed Thai Chicken Wings
4
servings
Appetizer
Course
Print Recipe
Ingredients
Directions
Ingredients
1 oz
dried glass noodles
Jump
2 tsp
coconut oil
Jump
4 oz
white button mushrooms, finely chopped
Jump
4 oz
ground pork
Jump
2 tbsp
oyster sauce
Jump
1 tbsp
fish sauce
Jump
3 lg
garlic cloves, minced
Jump
2 tbsp
finely chopped fresh cilantro leaves and stems
Jump
1 tsp
ground white or black pepper
Jump
16 lg
chicken wings
Jump
Glaze
2 tbsp
soy sauce
Jump
1 tbsp
honey
Jump
1 tsp
ground white or black pepper
Jump
¼ c
coconut oil, melted, or vegetable oil
Jump

Called “angel wings” at most Thai restaurants in the States, this dish has been a favorite among Southeast Asian immigrants in North America and Europe. Curiously, however, it’s rarely served in Thailand. The restaurant version is deep-fried, but I’ve always cooked these wings on the grill. They taste better this way, and they hark back to the more rustic version made with frogs, which is well loved in rural areas in Cambodia, Thailand, and Laos.

The most challenging part of the recipe is the removal of the wing bones. If this is your first time, buy a few extra wings as practice pieces. It should take no more than three or four wings to get you in the groove. Then you’ll whizz through the wings you need here in a matter of minutes. The recipe intentionally yields more stuffing than you need because it’s nearly impossible to be precise unless the wings are all exactly the same size to start and therefore have the same capacity once they are boned. It’s better to have too much than too little on hand. Besides, you can stir-fry what’s left over and have yourself a snack portion of stir-fried glass noodles.

Glass noodles, also called bean thread noodles, are made of mung bean starch. Once cooked, they become translucent and slightly chewy, adding a nice texture to this dish. Choose a brand that is made from 100 percent mung bean starch, with no potato starch mixed in. Kaset is my favorite brand.

Directions

  1. To stuff the chicken wings: In a medium bowl, soak the noodles in warm water to cover until softened, about 15 minutes. Drain, squeeze dry, and cut into 1⁄2-inch lengths. Return the noodles to the bowl.
  2. Line a small plate with a paper towel. In a small frying pan, heat the coconut oil over medium-high heat. When the oil is hot, add the mushrooms and sauté until they turn soft and release some moisture, about 2 minutes. Using a slotted spoon, transfer the mushrooms to the towel-lined plate and let the paper towel absorb all the moisture. Transfer the mushrooms to the noodle bowl and add the pork, oyster sauce, fish sauce, garlic, cilantro, and pepper. Mix until well blended and sticky, then cover and refrigerate.
  3. Take a chicken wing and cut through the joint connecting the drumette with the rest of the wing. Reserve the drumette for another use and put the partial wing—the wingette and wing tip—into a large bowl. Repeat with the remaining wings.
  4. Take a partial wing and use your hands to break it in two at the joint where the wingette meets the tip, without breaking through the skin. Using the tip of a very sharp paring knife, make a cut around the very top part where the meat is attached to the joint bone. Carefully pull down the wingette meat toward the wing tip to expose the bones that run through the wingette, inserting your finger inside the wingette to help loosen things up. Pull those bones out while keeping the meat, skin, and shape of the wingette intact; discard the bones. Repeat with the remaining partial wings. Now you have sixteen boned wings with empty pockets ready to be filled.
  5. Stuff the wings with the pork mixture and close each opening with a wooden toothpick. Put in as much of the stuffing as you can to create full pockets, but don’t overfill, as the filling will expand a little during cooking.
  6. Bring water in a steamer bottom to a gentle boil. Arrange the wings in a single layer in a steamer container, place over (not touching) the gently boiling water, cover, and steam until the juices run clear when a wing is tested with a knife tip, about 10 minutes. Remove the wings from the steamer, blot them dry, and leave them to cool on a sheet pan. Don’t remove the toothpicks just yet.
  7. Prepare a medium-high fire (400° to 450°F) in a charcoal grill using the two-zone method.
  8. Meanwhile, make the glaze: In a small bowl, whisk together the soy sauce, honey, pepper, and oil.
  9. When the coals are covered with white ash and the grate is hot, place the wings on the hold side of the grill, cover, and cook with the vents fully opened, removing the lid and brushing the wings with the glaze along the way. The wings are already fully cooked, so at this point you only need to grill them just until they’re heated through and golden brown, which should take anywhere between 10 and 12 minutes.
  10. Transfer the wings to a platter, remove the toothpicks, leave them to cool to slightly warmer than room temperature, and serve.

Reprinted with permission from Flavors of the Southeast Asian Grill: Classic Recipes for Seafood and Meats Cooked Over Charcoal by Leela Punyaratabandhu. Copyright© 2020 shesimmers.com. Photographs copyright ©2020 by David Loftus. Published by Ten Speed Press, an imprint of Penguin Random House.

[email_signup id="3"]
<div class="email-subscribe exp-subscribe subscribe"> <div class="alert alert-success exp-success ga-etembed-success" style="display:none;"> Great! You've signed up successfully! </div> <div class="alert alert-danger exp-error" style="display:none;"> We are experiencing an error, please try again. </div> <form name="subscribe" id="email-signup" class="email-signup-form" action="https://www.tastecooking.com/wp-admin/admin-ajax.php" method="POST" target="_top" data-event-assigned="false"> <fieldset class="form-group form-inline email-submit-group"> <label for="email-address" class="sr-only">Email Address</label> <input id="email-newsletter" type="email" placeholder="your@email.com" class="email-newsletter text email form-control" name="email" value=""> <button type="submit" value="Subscribe" name="subscribe" class="btn btn-primary email-submit-btn ga-etembed-success"> <i class="fa fa-envelope"></i> Subscribe </button> </fieldset> <small class="exp-small terms" style=""> By clicking Subscribe, I acknowledge that I have read and agree to the Penguin Random House <a href="http://www.penguinrandomhouse.com/privacy/" target="_blank">Privacy Policy</a> and <a href="http://www.penguinrandomhouse.com/terms/" target="_blank">Terms of Use</a> and agree to receive news and updates from TASTE and Penguin Random House. </small> <fieldset class="field-group checkboxes" style="display:none"> <div class="checkbox"> <label> <input type="checkbox" name="programs[]" value="505,50501,1" class="exp-checkbox" checked="checked"> <span><strong>Tastebook General</strong></span> </label> </div> <div class="checkbox"> <label> <input type="checkbox" name="programs[]" value="505,50502,1" class="exp-checkbox" checked="checked"> <span><strong>Tastebook Promo</strong></span> </label> </div> </fieldset><!-- /.checkboxes --> <input type="hidden" name="data_acq_code" value="TASTE_POPUP_STATIC_ONGOING" /> <input type="hidden" name="data_programs" value="50501|505,50502|505" /> <input type="hidden" name="form_id" value="3" /> <input type="hidden" name="partner" value="" /> <input type="hidden" name="action" value="crown_email_signup_submit" /> <input type="hidden" name="ref_url" value="" /> </form> </div> <script> jQuery(document).ready(function () { var unassigned_forms; setInterval( function() { //Check for unassigned forms var forms = jQuery( '.email-signup-form' ); unassigned_forms = false; forms.each( function( index ) { if ( jQuery( this ).attr( 'data-event-assigned' ) === 'false' ) { unassigned_forms = true; } }); if ( unassigned_forms ) { forms.off( 'submit' ).on( 'submit', function ( e ) { forms.attr( 'data-event-assigned', 'true' ); e.preventDefault(); // Basic email validation var email = jQuery(e.target).find('.email-newsletter').val(), valid_email = false, groupEl = jQuery(e.target).closest('.email-subscribe'); if ( !!email && typeof(email) === "string" ) { var email_array = email.split('@'); if ( email_array.length === 2 ) { if ( email_array[1].split('.').length > 1 ) { valid_email = true; } } } if ( valid_email ) { jQuery('.alert-danger').hide(); // Show loading gif groupEl.find('.email-signup-form').hide(); groupEl.find('.email-submit-loading').show(); // Populate ref_url jQuery(this).find('input[name="ref_url"]').val(window.location.href); // Generate Payload var payload = jQuery(this).serializeArray(); jQuery.ajax({ url: jQuery(this).attr('action'), type: 'POST', data: payload, success: function (data) { // Hide loading spinner groupEl.find('.email-signup-form').show(); groupEl.find('.email-submit-loading').hide(); // Display success msg var target = jQuery(e.target); jQuery(e.target).hide(); jQuery(e.target).parent().find('.alert-success').show(); jQuery(e.target).parent().find('#downloadbtn').show(); }, fail: function (err) { // Hide loading spinner groupEl.find('.email-signup-form').show(); groupEl.find('.email-submit-loading').hide(); // Display failure msg var target = jQuery(e.target); jQuery(e.target).hide(); jQuery(e.target).parent().find('.alert-danger').show(); } }); } else { groupEl.find('.alert-danger').html('Please enter a valid email address.').show(); } }); forms.off( 'keypress' ).on( 'keypress', function ( e ) { if ( e.which === 13 ) { e.preventDefault(); jQuery( this ).submit(); } }); } }, 100); }); </script>
[email_signup id="3"]
<div class="email-subscribe exp-subscribe subscribe"> <div class="alert alert-success exp-success ga-etembed-success" style="display:none;"> Great! You've signed up successfully! </div> <div class="alert alert-danger exp-error" style="display:none;"> We are experiencing an error, please try again. </div> <form name="subscribe" id="email-signup" class="email-signup-form" action="https://www.tastecooking.com/wp-admin/admin-ajax.php" method="POST" target="_top" data-event-assigned="false"> <fieldset class="form-group form-inline email-submit-group"> <label for="email-address" class="sr-only">Email Address</label> <input id="email-newsletter" type="email" placeholder="your@email.com" class="email-newsletter text email form-control" name="email" value=""> <button type="submit" value="Subscribe" name="subscribe" class="btn btn-primary email-submit-btn ga-etembed-success"> <i class="fa fa-envelope"></i> Subscribe </button> </fieldset> <small class="exp-small terms" style=""> By clicking Subscribe, I acknowledge that I have read and agree to the Penguin Random House <a href="http://www.penguinrandomhouse.com/privacy/" target="_blank">Privacy Policy</a> and <a href="http://www.penguinrandomhouse.com/terms/" target="_blank">Terms of Use</a> and agree to receive news and updates from TASTE and Penguin Random House. </small> <fieldset class="field-group checkboxes" style="display:none"> <div class="checkbox"> <label> <input type="checkbox" name="programs[]" value="505,50501,1" class="exp-checkbox" checked="checked"> <span><strong>Tastebook General</strong></span> </label> </div> <div class="checkbox"> <label> <input type="checkbox" name="programs[]" value="505,50502,1" class="exp-checkbox" checked="checked"> <span><strong>Tastebook Promo</strong></span> </label> </div> </fieldset><!-- /.checkboxes --> <input type="hidden" name="data_acq_code" value="TASTE_POPUP_STATIC_ONGOING" /> <input type="hidden" name="data_programs" value="50501|505,50502|505" /> <input type="hidden" name="form_id" value="3" /> <input type="hidden" name="partner" value="" /> <input type="hidden" name="action" value="crown_email_signup_submit" /> <input type="hidden" name="ref_url" value="" /> </form> </div> <script> jQuery(document).ready(function () { var unassigned_forms; setInterval( function() { //Check for unassigned forms var forms = jQuery( '.email-signup-form' ); unassigned_forms = false; forms.each( function( index ) { if ( jQuery( this ).attr( 'data-event-assigned' ) === 'false' ) { unassigned_forms = true; } }); if ( unassigned_forms ) { forms.off( 'submit' ).on( 'submit', function ( e ) { forms.attr( 'data-event-assigned', 'true' ); e.preventDefault(); // Basic email validation var email = jQuery(e.target).find('.email-newsletter').val(), valid_email = false, groupEl = jQuery(e.target).closest('.email-subscribe'); if ( !!email && typeof(email) === "string" ) { var email_array = email.split('@'); if ( email_array.length === 2 ) { if ( email_array[1].split('.').length > 1 ) { valid_email = true; } } } if ( valid_email ) { jQuery('.alert-danger').hide(); // Show loading gif groupEl.find('.email-signup-form').hide(); groupEl.find('.email-submit-loading').show(); // Populate ref_url jQuery(this).find('input[name="ref_url"]').val(window.location.href); // Generate Payload var payload = jQuery(this).serializeArray(); jQuery.ajax({ url: jQuery(this).attr('action'), type: 'POST', data: payload, success: function (data) { // Hide loading spinner groupEl.find('.email-signup-form').show(); groupEl.find('.email-submit-loading').hide(); // Display success msg var target = jQuery(e.target); jQuery(e.target).hide(); jQuery(e.target).parent().find('.alert-success').show(); jQuery(e.target).parent().find('#downloadbtn').show(); }, fail: function (err) { // Hide loading spinner groupEl.find('.email-signup-form').show(); groupEl.find('.email-submit-loading').hide(); // Display failure msg var target = jQuery(e.target); jQuery(e.target).hide(); jQuery(e.target).parent().find('.alert-danger').show(); } }); } else { groupEl.find('.alert-danger').html('Please enter a valid email address.').show(); } }); forms.off( 'keypress' ).on( 'keypress', function ( e ) { if ( e.which === 13 ) { e.preventDefault(); jQuery( this ).submit(); } }); } }, 100); }); </script>