We love it!!!
I’ve started to dive into the source and try and solve some of the wishes of our clients and 1 of the wishes is/was to have product attributes (size for example) to display an ‘Out of stock’ notification (and disable the item) in the dropdown, for example:
Small
Medium (out of stock)
Large
Extra large
After many hours/days of searching I think I’ve found the solutions and would like to share this with you all so that you to can use (and improve on it) for your site.
This solution was done using the NopCommerce 4.2 source code.
Please, if there is a better solution or improvements please contribute to this solution to help others!
There are only 2 files in the source that need to be changed and only 1 view file:
The first file you need to change is the ‘ProductDetailsModel.cs’, found here: ‘\Nop.Web\Models\Catalog\’
Add the following line to the code:
public string Name { get; set; }
public int StockQuantity { get; set; }
public string ColorSquaresRgb { get; set; }
This variable (‘StockQuantity’) will be used in the view file so that you can disable and/or display an ‘Out of stock’ notification message next to the attribute.
The next thing is to edit the ‘ProductModelFactory.cs’ file found here: ‘\Nop.Web\Factories\’
Add the following line of code, you should find the code around line 765
var valueModel = new ProductDetailsModel.ProductAttributeValueModel
{
Id = attributeValue.Id,
Name = _localizationService.GetLocalized(attributeValue, x => x.Name),
StockQuantity = GetAttributeStock(product, attributeValue.Id),//Added
ColorSquaresRgb = attributeValue.ColorSquaresRgb,
IsPreSelected = attributeValue.IsPreSelected,
CustomerEntersQty = attributeValue.CustomerEntersQty,
Quantity = attributeValue.Quantity
};
Now add the following function to retrieve the StockQuantity of the attribute:
/// <summary>
/// Get the product attribute stock value
/// </summary>
/// <param name="product">Product</param>
/// <param name="attributeId">Attribute Id</param>
/// <returns>STock Quantity value</returns>
private int GetAttributeStock(Product product, int attributeId) {
var allAttributesXml = _productAttributeParser.GenerateAllCombinations(product, true);
var stockVal = -1;
foreach (var attributesXml in allAttributesXml)
{
var combination = _productAttributeParser.FindProductAttributeCombination(product, attributesXml);
if (combination != null)
{
try {
var xmlDoc = new XmlDocument();
xmlDoc.LoadXml(attributesXml);
var attrIdNode = (XmlElement)xmlDoc.SelectSingleNode(@"//Attributes/ProductAttribute/ProductAttributeValue/Value");
var attrId = int.Parse(attrIdNode.InnerText);
if (attrId == attributeId)
stockVal = combination.StockQuantity;
} catch { }
}
}
return stockVal;
}
Now that you have the attribute stock quantity you can now use this in the ‘_ProductAttributes.chtml’, found here: ‘/Nop.Web/Views/Product/’
For an example I added some extra functionality for the dropdown:
case AttributeControlType.DropdownList:
{
<select name="@(controlId)" id="@(controlId)" @(attribute.Values.Any(value => value.CustomerEntersQty) ? Html.Raw($"onchange=\"showHideDropdownQuantity('{controlId}')\"") : null)>
@if (!attribute.IsRequired)
{
<option value="0">--- </option>
}
@foreach (var attributeValue in attribute.Values)
{
//Changed attribute stock notification
var isDisabled = false;
var isInStockNotification = string.Empty;
if (@attributeValue.StockQuantity == 0)
{
isDisabled = true;
isInStockNotification = “(Out of Stock)”;
}
//Changed attribute stock notification
var attributeName = string.IsNullOrEmpty(attributeValue.PriceAdjustment) ?
attributeValue.Name :
T("Products.ProductAttributes.PriceAdjustment", attributeValue.Name, attributeValue.PriceAdjustment,
attributeValue.CustomerEntersQty ? T("Products.ProductAttributes.PriceAdjustment.PerItem").Text : string.Empty).Text;
<!-- Changed attribute stock notification -->
<option disabled="@isDisabled" selected="@attributeValue.IsPreSelected" value="@attributeValue.Id">@attributeName @isInStockNotification</option>
<!-- Changed attribute stock notification -->
}
</select>
Enjoy and hope this helps others!
Geoff