I have tried a similar approach, but in the end for some reason when I changed the attribute for one product the price would also change for the other products. The way I did it was to add the product id to the form id. Then add the below code within the foreach loop.
<script type="text/x-magento-init">
{
"#product_addtocart_form<?php echo $_product->getId();?>": {
"configurable": {
"spConfig": <?php /* @escapeNotVerified */ echo $matrixConfigurableBlock->getJsonConfigForProdList($_product, $configProdOptFrontend) ?>,
"onlyMainImg": <?php /* @escapeNotVerified */ echo $matrixConfigurableBlock->getVar('change_only_base_image', 'Magento_ConfigurableProduct') ?: 'false'; ?>
}
}
}
</script>
Basically the product_id is passed through to the getJsonConfigForProdList function along with a flag to state whether we are in grid or list mode. The getJsonConfigForProdList is below.
public function getJsonConfigForProdList($product, $configProdOptFrontend)
{
$store = $this->getCurrentStore();
$currentProduct = $product;
$regularPrice = $currentProduct->getPriceInfo()->getPrice('regular_price');
$finalPrice = $currentProduct->getPriceInfo()->getPrice('final_price');
if($configProdOptFrontend == 'matrix'){
$options = $this->helper->getOptionsForMatrix($currentProduct, $this->getAllowProductsForProdList($product));
}else{
$options = $this->helper->getOptions($currentProduct, $this->getAllowProductsForProdList($product));
}
$attributesData = $this->configurableAttributeData->getAttributesData($currentProduct, $options);
$config = [
'attributes' => $attributesData['attributes'],
'template' => str_replace('%s', '<%- data.price %>', $store->getCurrentCurrency()->getOutputFormat()),
'optionPrices' => $this->getOptionPrices(),
'currencySymbol'=>str_replace('%s','', $store->getCurrentCurrency()->getOutputFormat()),
'prices' => [
'oldPrice' => [
'amount' => $this->_registerJsPrice($regularPrice->getAmount()->getValue()),
],
'basePrice' => [
'amount' => $this->_registerJsPrice(
$finalPrice->getAmount()->getBaseAmount()
),
],
'finalPrice' => [
'amount' => $this->_registerJsPrice($finalPrice->getAmount()->getValue()),
],
],
'productId' => $currentProduct->getId(),
'chooseText' => __('Choose an Option ...'),
'images' => isset($options['images']) ? $options['images'] : [],
'index' => isset($options['index']) ? $options['index'] : [],
];
if ($currentProduct->hasPreconfiguredValues() && !empty($attributesData['defaultValues'])) {
$config['defaultValues'] = $attributesData['defaultValues'];
}
$config = array_merge($config, $this->_getAdditionalConfig());
return $this->jsonEncoder->encode($config);
}
You will also need to create a few other functions, one of which for the price
public function getPriceJsonConfigProdList($currentProduct)
{
/* @var $product \Magento\Catalog\Model\Product */
$product = $currentProduct;
if (!$this->hasOptions()) {
$config = [
'productId' => $product->getId(),
'priceFormat' => $this->_localeFormat->getPriceFormat()
];
return $this->_jsonEncoder->encode($config);
}
$tierPrices = [];
$tierPricesList = $product->getPriceInfo()->getPrice('tier_price')->getTierPriceList();
foreach ($tierPricesList as $tierPrice) {
$tierPrices[] = $this->priceCurrency->convert($tierPrice['price']->getValue());
}
$config = [
'productId' => $product->getId(),
'priceFormat' => $this->_localeFormat->getPriceFormat(),
'prices' => [
'oldPrice' => [
'amount' => $this->priceCurrency->convert(
$product->getPriceInfo()->getPrice('regular_price')->getAmount()->getValue()
),
'adjustments' => []
],
'basePrice' => [
'amount' => $this->priceCurrency->convert(
$product->getPriceInfo()->getPrice('final_price')->getAmount()->getBaseAmount()
),
'adjustments' => []
],
'finalPrice' => [
'amount' => $this->priceCurrency->convert(
$product->getPriceInfo()->getPrice('final_price')->getAmount()->getValue()
),
'adjustments' => []
]
],
'idSuffix' => '_clone',
'tierPrices' => $tierPrices
];
$responseObject = new \Magento\Framework\DataObject();
$this->_eventManager->dispatch('catalog_product_view_config', ['response_object' => $responseObject]);
if (is_array($responseObject->getAdditionalOptions())) {
foreach ($responseObject->getAdditionalOptions() as $option => $value) {
$config[$option] = $value;
}
}
return $this->_jsonEncoder->encode($config);
}`