Preqin Territory Guide: ASEAN 2022

 

 

The ASEAN private equity and venture capital industry entered a new phase of growth in 2021, with venture capital deal activity reaching a record $20bn, and is attempting to sustain the momentum despite headwinds. While macro tailwinds supporting long-term growth in the region over the past few years remain intact (particularly given its rapidly emerging middle class and increasing digital adoption), macro headwinds such as geopolitical tensions, rising oil prices, inflation, and interest rates have prompted investors to be selective in identifying companies that can tap on the region’s growth while maintaining strong balance sheets.

Key ASEAN Territory Guide 2022 facts:

  • Venture capital deal activity in ASEAN soared in 2021, reaching a record $20bn
  • The aggregate deal value for ASEAN in 2021 was 35% higher than the 2019 and 2020 levels combined, and 85% higher than the last peak of $11bn in 2018. Most of the deals in 2021 were in Singapore and Indonesia, which accounted for 46% and 37% of the aggregate deal value in ASEAN respectively
  • Information technology, as a sector, continues to dominate the venture capital deals made in ASEAN. There were 379 deals made with an aggregate deal value of $6.7bn in this sector in 2021

Download our report to discover the sectors and regions where deal-making is strongest.

Don't miss Cameron Joyce, SVP Deputy Head of Research Insights on BFM89.9, where he shares the outlook of ASEAN PEVC landscape.

 

'); // Wrap in a container $inputField.after('' + decodeURI('%3Csvg xmlns="http://www.w3.org/2000/svg" width="20" height="20" fill="none" viewBox="0 0 20 20" class="search-icon">')) // Find the container (assuming it's the direct parent with the class) const $container = $inputField.closest('#formField--companyName'); // Demo display element const $idDisplaySpan = $('#selected-id-display span'); let $resultsContainer = null; let $resultsList = null; let valueWasSelected = false; // Flag to track if the current value is from selection let responseData = null; // Store the response data // --- Helper Functions --- function ensureResultsListExists() { if(!$resultsContainer || $resultsContainer.length === 0) { $resultsContainer = $container.find('.autocomplete-results'); if($resultsContainer.length === 0) { $resultsContainer = $('
').addClass('autocomplete-results').hide(); $resultsList = $('
    '); $resultsContainer.append($resultsList); $container.append($resultsContainer); } else { $resultsList = $resultsContainer.find('ul'); if($resultsList.length === 0) { $resultsList = $('
      '); $resultsContainer.append($resultsList); } } } $resultsList.empty(); return $resultsList; } function hideResults() { if($resultsContainer && $resultsContainer.length) { $resultsContainer.hide(); if($resultsList) { $resultsList.empty(); } } if(currentRequest) { currentRequest.abort(); currentRequest = null; } } // Function to clear the stored ID function clearSelectedId() { $hiddenFirmIdInput.val(''); valueWasSelected = false; $idDisplaySpan?.text('(None)'); // Update demo display // Clear company type field when ID is cleared $companyTypeField.val(''); // console.log("Hidden ID cleared"); } // Function to perform quick search API request function performQuickSearch(searchTerm, options = {}) { const { autoSelectFirst = false } = options; // Clear any existing timer and request clearTimeout(debounceTimer); if(currentRequest) { currentRequest.abort(); currentRequest = null; } const $currentResultsList = ensureResultsListExists(); $currentResultsList.html('
    • Searching...
    • '); $resultsContainer.show(); currentRequest = $.ajax({ url: `${apiUrl}?size=10&term=${encodeURIComponent(searchTerm)}`, method: 'GET', dataType: 'json', success: function(responsePayload) { $currentResultsList.empty(); responseData = []; let hasResults = false; if(responsePayload && Array.isArray(responsePayload) && responsePayload.length > 0) { responseData = responsePayload; $.each(responsePayload, function(index, item) { if(item && item.name && item.id) { $('
    • ') .text(item.name) .data('company-id', item.id) .data('company-data', item) .appendTo($currentResultsList); hasResults = true; } }); } if(hasResults) { $resultsContainer.show(); // Automatically select the first item if requested if (autoSelectFirst) { const $items = $resultsList.find('li:not(.autocomplete-message)'); if ($items.length > 0) { $items.first().addClass('active'); } } } else { $currentResultsList.html('
    • Not found in database. Click Enter to submit.
    • '); $resultsContainer.show(); } currentRequest = null; }, error: function(jqXHR, textStatus) { if(textStatus !== 'abort') { console.error('Autocomplete API Error:', textStatus, jqXHR); ensureResultsListExists().html('
    • Error fetching results.
    • '); $resultsContainer.show(); } currentRequest = null; } }); } // Function to match company type from API to dropdown option function setCompanyTypeFromAPI(apiCompanyType) { if (!apiCompanyType || !$companyTypeField.length) { return; } // First try exact match (most API types match dropdown options exactly) let matchedOption = $companyTypeField.find('option').filter(function() { return $(this).text().trim() === apiCompanyType; }); // If no exact match, check for specific mappings for the differences if (matchedOption.length === 0) { const specificMappings = { 'Non-sponsor backed': 'Other', // API type not in dropdown 'Professional Services': 'Other', // API type not in dropdown 'Infrastructure - Other': 'Infrastructure - Other', // Check if this exact match works 'Natural Resources - Other': 'Natural Resources - Other', // Check if this exact match works 'Real Estate - Other': 'Real Estate - Other' // Check if this exact match works }; if (specificMappings[apiCompanyType]) { const mappedType = specificMappings[apiCompanyType]; matchedOption = $companyTypeField.find('option').filter(function() { return $(this).text().trim() === mappedType; }); } } // Set the matched option or clear if no match found if (matchedOption.length > 0) { $companyTypeField.val(matchedOption.first().val()); } else { $companyTypeField.val(''); console.log(`No matching dropdown option found for API company type: "${apiCompanyType}"`); } } // Function to handle selection (from click or Enter key) function handleSelection($selectedItem) { if(!$selectedItem || $selectedItem.length === 0 || $selectedItem.hasClass('autocomplete-message')) { return; // Do nothing if no valid item or it's a message } const selectedText = $selectedItem.text(); const selectedId = $selectedItem.data('company-id'); // Retrieve stored ID const selectedCompanyData = $selectedItem.data('company-data'); // Retrieve complete company data if(selectedId) { $inputField.val(selectedText); // Update visible input $hiddenFirmIdInput.val(selectedId); // Update hidden input // Update company type field if type exists in company data if(selectedCompanyData && selectedCompanyData.typeRaw) { setCompanyTypeFromAPI(selectedCompanyData.typeRaw); } else { $companyTypeField.val(''); // Clear if no type available } valueWasSelected = true; // Mark that selection occurred $idDisplaySpan?.text(selectedId); // Update demo display // console.log("Selected:", selectedText, "ID:", selectedId); hideResults(); $inputField.trigger('change'); // Optional: Trigger change event for other listeners } else { console.warn('Selected item missing company ID data:', $selectedItem); hideResults(); // Hide results even if ID is missing } } // --- Event Handlers --- $inputField.on('input', function() { const currentInputValue = $(this).val(); const searchTerm = currentInputValue.trim(); // CRITICAL: If the user types anything, clear the previously selected ID // Only clear if the flag 'valueWasSelected' is true, meaning the last change // wasn't already a manual input modification. if(valueWasSelected) { clearSelectedId(); } // We always set valueWasSelected to false here, because *any* input // event means the current value is potentially manual, until a selection happens again. valueWasSelected = false; clearTimeout(debounceTimer); if(currentRequest) { currentRequest.abort(); currentRequest = null; } if(searchTerm.length === 0) { hideResults(); clearSelectedId(); // Also clear ID if input is emptied return; } debounceTimer = setTimeout(() => { performQuickSearch(searchTerm); }, debounceDelay); }); // Handle click on a suggestion item (delegated to container) $container.on('click', '.autocomplete-results li', function(e) { handleSelection($(this)); // Pass the clicked LI to the handler }); // Keyboard navigation and selection/dismissal $inputField.on('keydown', function(e) { // Handle arrow-down when results are not visible - trigger search if (e.key === 'ArrowDown' && (!$resultsContainer || !$resultsContainer.is(':visible'))) { e.preventDefault(); const searchTerm = $(this).val().trim(); // If there's text in the input, trigger a search if (searchTerm.length > 0) { performQuickSearch(searchTerm, { autoSelectFirst: true }); } return; } // Handle TAB key when results are not visible - allow normal focus movement if (e.key === 'Tab' && (!$resultsContainer || !$resultsContainer.is(':visible'))) { // Don't prevent default - allow normal tab navigation to next field return; } if(!$resultsContainer || !$resultsContainer.is(':visible')) { // If results not visible, ESC shouldn't do anything special here return; } const $items = $resultsList.find('li:not(.autocomplete-message)'); if(!$items.length && e.key !== 'Escape') { return; } // No items to navigate (but allow ESC) let $currentActive = $items.filter('.active'); let currentIndex = $items.index($currentActive); switch(e.key) { case 'ArrowDown': e.preventDefault(); currentIndex = ($currentActive.length === 0) ? 0: (currentIndex + 1) % $items.length; $items.removeClass('active'); $items.eq(currentIndex).addClass('active'); break; case 'ArrowUp': e.preventDefault(); currentIndex = ($currentActive.length === 0) ? $items.length - 1: (currentIndex - 1 + $items.length) % $items.length; $items.removeClass('active'); $items.eq(currentIndex).addClass('active'); break; case 'Enter': e.preventDefault(); // IMPORTANT: Prevent form submission if($currentActive.length) { handleSelection($currentActive); // Use the selection handler } else { // Optional: Hide results if Enter is pressed without a selection hideResults(); } break; case 'Escape': // ESC key dismisses e.preventDefault(); hideResults(); break; case 'Tab': // Tab key dismisses and allows normal focus movement hideResults(); // Don't prevent default - allow normal tab navigation to next field break; } }); // Hide results when clicking outside $(document).on('click', function(e) { // Check if the click is outside the input AND outside the results container if(!$inputField.is(e.target) && !$container.is(e.target) && $container.has(e.target).length === 0) { if($resultsContainer && $resultsContainer.is(':visible')) { hideResults(); } } }); // Initial state check (optional) if($hiddenFirmIdInput.val()) { $idDisplaySpan?.text($hiddenFirmIdInput.val()); valueWasSelected = true; // Assume pre-filled value was selected } });

       

 

test