we have done it in Our Nopcommerce 2.70 Site
These are the Steps required to complete this task
(1)Add the following fields in Nop=>Core=>Domain=>Catalog=>ProductPicture
using Nop.Core.Domain.Media;
namespace Nop.Core.Domain.Catalog
{
public partial class ProductPicture : BaseEntity
{
/*----------Existing code----------*/
/// <summary>
/// Gets or sets the product variant attribute mapping identifier
/// </summary>
public virtual int ProductVariantAttributeId { get; set; }
/// <summary>
/// Gets the product variant attribute
/// </summary>
public virtual ProductVariantAttribute ProductVariantAttribute { get; set; }
}
}
(2)Add the following fields Nop=>Admin=>Models=>Catalog=>ProductModel
public partial class ProductPictureModel : BaseNopEntityModel
{
public ProductPictureModel()
{
AvailableProductAttributes = new List<SelectListItem>();
}
/*----------Existing Code----------*/
public int ProductVariantAttributeId { get; set; }
[NopResourceDisplayName("Admin.Catalog.Products.Pictures.Fields.ProductAttribute")]
[UIHint("ProductVariantAttribute")]
public string ProductVariantAttribute { get; set; }
public IList<SelectListItem> AvailableProductAttributes { get; set; }
}
(3)In Nop=>Admin=>Views=>Product=>Editor Templates Add New Editor Template
@using Telerik.Web.Mvc.UI;
@using Nop.Core.Domain.Catalog;
@using Nop.Services.Catalog;
@{
var _productAttributeService = EngineContext.Current.Resolve<IProductAttributeService>();
var allProductAttributes = _productAttributeService.GetAllProductAttributes();
var productAttributesList = new List<SelectListItem>();
foreach (var pa in allProductAttributes)
{
var item = new SelectListItem()
{
Text = pa.Name,
Value = pa.Id.ToString()
};
productAttributesList.Add(item);
}
}
@Html.Telerik().DropDownList().Name("ProductAttribute").BindTo(productAttributesList)
(4)Nop=>Admin=>Views=>Product=>_CreateOrUpdate.cshtml find the @helper TabPictures() then change it with following code
@helper TabPictures()
{
if (Model.Id > 0)
{
<div>
@(Html.Telerik().Grid<ProductModel.ProductPictureModel>()
.Name("productpictures-grid")
.DataKeys(x =>
{
x.Add(y => y.Id).RouteKey("Id");
})
.Columns(columns =>
{
/*----------Existing Code----------*/
columns.Bound(x=> x.ProductVariantAttribute).Width(75).Centered();
columns.Command(commands =>
{
/*----------Existing Code----------*/
});
})
.Editable(x =>
{
x.Mode(GridEditMode.InLine);
})
.DataBinding(dataBinding =>
{
/*----------Existing Code----------*/
})
.ClientEvents(events=> events.OnEdit("onPictureListEdit"))
.ClientEvents(events=> events.OnSave("onPictureListSave"))
.EnableCustomBinding(true))
</div>
<p>
<strong>@T("Admin.Catalog.Products.Pictures.AddNew")</strong>
</p>
<script type="text/javascript">
$(document).ready(function () {
$('#addProductPicture').click(function () {
/*----------Existing Code----------*/
var attributeId = $('#ProductAttributes').val();
if(attributeId == null)
attributeId = 0;
/*----------Existing Code----------*/
$.ajax({
cache:false,
type: "POST",
url: "@(Url.Action("ProductPictureAdd", "Product"))",
data: { "pictureId": pictureId, "displayOrder": displayOrder,"attributeId":attributeId,"productId": @Model.Id },
success: function (data) {
/*----------Existing Code----------*/
},
error:function (xhr, ajaxOptions, thrownError){
/*----------Existing Code----------*/
}
});
});
});
function onPictureListEdit(e) {
var value = $("#@Html.FieldIdFor(model => model.Id)").val();
if (value != 0) {
$.getJSON("/Admin/Product/GetProductVariantAttributes?productId=" + value, function (data) {
$("#ProductAttribute").data("tDropDownList").dataBind(data);
$("#ProductAttribute").data("tDropDownList").reload();
});
}
}
function onPictureListSave(e)
{
var values = e.values;
values.ProductVariantAttribute = $("#ProductAttribute").data('tDropDownList').value();
}
</script>
<table class="adminContent">
<tr>
/*----------Existing Code----------*/
</tr>
@if(Model.AddPictureModel.AvailableProductAttributes.Count() > 0)
{
<tr>
<td class="adminTitle">
@Html.NopLabelFor(model => model.AddPictureModel.ProductVariantAttribute):
</td>
<td class="adminData">
@Html.DropDownList("ProductAttributes",Model.AddPictureModel.AvailableProductAttributes)
</td>
</tr>
}
<tr>
/*----------Existing Code----------*/
</tr>
<tr>
/*----------Existing Code----------*/
</tr>
</table>
}
else
{
/*----------Existing Code----------*/
}
}
(5)Then In Nop=>Admin=>Controllers=> ProductController.cs update the following
public ActionResult ProductPictureAdd(int pictureId, int displayOrder,int attributeId, int productId)
{
/*----------Existing Code----------*/
_productService.InsertProductPicture(new ProductPicture()
{
/*----------Existing Code----------*/
ProductVariantAttributeId = attributeId,
});
/*----------Existing Code----------*/
return Json(new { Result = true }, JsonRequestBehavior.AllowGet);
}
[HttpPost, GridAction(EnableCustomBinding = true)]
public ActionResult ProductPictureList(GridCommand command, int productId)
{
/*----------Existing Code----------*/
var productPicturesModel = productPictures
.Select(x =>
{
return new ProductModel.ProductPictureModel()
{
/*----------Existing Code----------*/
ProductVariantAttributeId = x.ProductVariantAttributeId,
ProductVariantAttribute = _productAttributeService.GetProductVariantAttributeValueById(x.ProductVariantAttributeId) != null ?_productAttributeService.GetProductVariantAttributeValueById(x.ProductVariantAttributeId).Name :"none"
};
})
.ToList();
var model = new GridModel<ProductModel.ProductPictureModel>
{
/*----------Existing Code----------*/
};
return new JsonResult
{
/*----------Existing Code----------*/
};
}
[GridAction(EnableCustomBinding = true)]
public ActionResult ProductPictureUpdate(ProductModel.ProductPictureModel model, GridCommand command)
{
/*----------Existing Code----------*/
productPicture.ProductVariantAttributeId = Int32.Parse(model.ProductVariantAttribute) != 0 ? Int32.Parse(model.ProductVariantAttribute) : 0;
/*----------Existing Code----------*/
}
then add this One For Admin ProductList Grid Product Attribute Dropdown
#region Product Attribute Dropdown
public JsonResult GetProductVariantAttributes(int productId)
{
var attributeList = new List<SelectListItem>();
var productvariant = _productService.GetProductVariantsByProductId(productId).FirstOrDefault();
var productvariantattribute = productvariant.ProductVariantAttributes.FirstOrDefault();
if (productvariantattribute != null)
{
int productvariantattributeId = productvariant.ProductVariantAttributes
.Where(p => (p.TextPrompt == "Color") || (p.ProductAttribute.Name == "Color") || (p.TextPrompt == "color") || (p.ProductAttribute.Name == "color"))
.FirstOrDefault().Id;
var allAttributes = _productAttributeService.GetProductVariantAttributeValues(productvariantattributeId);
attributeList.Add(new SelectListItem()
{
Text = "--Select--",
Value = "0",
Selected = true
});
foreach (var cr in allAttributes)
{
var item = new SelectListItem()
{
Text = cr.Name,
Value = cr.Id.ToString(),
};
attributeList.Add(item);
}
if (attributeList != null)
{
return Json(attributeList, JsonRequestBehavior.AllowGet);
}
else
{
attributeList.Add(new SelectListItem()
{
Text = "--Select--",
Value = "0"
});
return Json(attributeList, JsonRequestBehavior.AllowGet);
}
}
else
{
attributeList.Add(new SelectListItem()
{
Text = "--Select--",
Value = "0"
});
return Json(attributeList, JsonRequestBehavior.AllowGet);
}
}
#endregion
(6)In Nop=>Web=>Views=>Catalog=>_ProductAttributes.cshtml
@model IList<ProductDetailsModel.ProductVariantModel.ProductVariantAttributeModel>
/*----------Existing code----------*/
@{
/*----------Existing code----------*/
//Productvariant
string attributeTableName = "";
string attributeFuncName = "";
if (dynamicPriceUpdate && !hidePrices)
{
/*----------Existing code----------*/
}
//Added For Image Change Based On Product Color Attribute Dropdown ...
foreach (var attribute in Model)
{
string controlId = string.Format("product_attribute_{0}_{1}_{2}", attribute.ProductVariantId, attribute.ProductAttributeId, attribute.Id);
attributeTableName = string.Format("attributeTable_{0}", attribute.ProductVariantId);
attributeFuncName = string.Format("attributeFuncName_{0}", attribute.ProductVariantId);
if( attribute.TextPrompt =="Color" || attribute.TextPrompt =="color" || attribute.Name == "Color" || attribute.Name == "color")
{
switch (attribute.AttributeControlType)
{
case AttributeControlType.DropdownList:
{
attributeTableScripts.AppendFormat("{0}['{1}'] = new Array(", attributeTableName, controlId);
attributeScripts.AppendFormat("$('#{0}').change(function(){{{1}();}});\n", controlId,attributeFuncName);
int numberOfJsArrayItems = 0;
if (!attribute.IsRequired)
{
attributeTableScripts.AppendFormat(CultureInfo.InvariantCulture, "{0},", decimal.Zero);
numberOfJsArrayItems++;
}
foreach (var pvaValue in attribute.Values)
{
//attributeTableScripts.AppendFormat(CultureInfo.InvariantCulture, "{0}['{1}_{2}'] = '{3}';\n", attributeTableName, controlId, pvaValue.Id, (string)pvaValue.PictureThumbnailUrl);
attributeTableScripts.AppendFormat(CultureInfo.InvariantCulture, "'{0}',",pvaValue.PictureThumbnailUrl, pvaValue.Id);
//attributeScripts.AppendFormat("$('#{0}').change(function(){{{1}['{2}_{3}']}});\n", controlId, attributeFuncName,controlId,pvaValue.Id);
//attributeScripts.AppendFormat("$('#{0}').change(function(){{{1}();}});\n", controlId,attributeFuncName,pvaValue.Id);
numberOfJsArrayItems++;
}
//If you create an array with a single numeric parameter, that number is used for specifying the number of elements in this array.
//so have a little hack here (we need at least two elements)
if (numberOfJsArrayItems == 1)
{
attributeTableScripts.AppendFormat(CultureInfo.InvariantCulture, "{0},", decimal.Zero);
}
attributeTableScripts.Length -= 1;
attributeTableScripts.Append(");\n");
}
break;
case AttributeControlType.RadioList:
{
foreach (var pvaValue in attribute.Values)
{
attributeTableScripts.AppendFormat(CultureInfo.InvariantCulture, "{0}['{1}_{2}'] = '{3}';\n", attributeTableName, controlId, pvaValue.Id, (string)pvaValue.PictureThumbnailUrl);
attributeScripts.AppendFormat("$('#{0}_{1}').click(function(){{{2}();}});\n", controlId, pvaValue.Id, attributeFuncName);
}
}
break;
case AttributeControlType.Checkboxes:
{
foreach (var pvaValue in attribute.Values)
{
attributeTableScripts.AppendFormat(CultureInfo.InvariantCulture, "{0}['{1}_{2}'] = '{3}';\n", attributeTableName, controlId, pvaValue.Id, (string)pvaValue.PictureThumbnailUrl);
attributeScripts.AppendFormat("$('#{0}_{1}').click(function(){{{2}();}});\n", controlId, pvaValue.Id, attributeFuncName);
}
}
break;
default:
break;
}
}
}
}
@if (Model.Count > 0)
{
if (dynamicPriceUpdate && !hidePrices)
{
/*----------Existing code----------*/
}
/*Newly Added */
<script type="text/javascript">
var mainImagePath = '';
// Adjustment table
var @(attributeTableName) = new Array();
// Adjustment table initialize
@Html.Raw(attributeTableScripts.ToString())
// Adjustment function
function @(attributeFuncName)() {
var sum = 0;
var imageString = '';
for(var i in @(attributeTableName)) {
var ctrl = $('#' + i);
if((ctrl.is(':radio') && ctrl.is(':checked')) || (ctrl.is(':checkbox') && ctrl.is(':checked'))) {
sum += @(attributeTableName)[i];
imageString = imageString + @(attributeTableName)[i];
}
else if(ctrl.is('select')) {
var idx = $('#' + i + " option").index($('#' + i + " option:selected"));
if(idx != -1) {
sum += @(attributeTableName)[i][idx];
imageString = imageString + @(attributeTableName)[i][idx];
}
}
mainImagePath = imageString.substring(0,imageString.length);
if(mainImagePath != null)
$("#thumb").attr('href',mainImagePath);
$("#thumb").trigger('click');
$("#mainImage").attr('src',mainImagePath);
}
}
// Attributes handlers
$(document).ready(function() {
@* @(attributeFuncName)();*@
@Html.Raw(attributeScripts.ToString())
});
</script>
<div class="attributes">
/*----------Existing code----------*/
</div>
}
(7) Nop=>Web=>Views=>Catalog=>_ProductDetailPictures.cshtml
<div class="picture">
@if (Model.DefaultPictureZoomEnabled)
{
<a href="@Model.DefaultPictureModel.FullSizeImageUrl" data-gallery="lightbox-pd" title="@Model.Name">
<img alt="@Model.DefaultPictureModel.AlternateText" src="@Model.DefaultPictureModel.ImageUrl" title="@Model.DefaultPictureModel.Title" id="mainImage"/>
</a>
}
else
{
<img alt="@Model.DefaultPictureModel.AlternateText" src="@Model.DefaultPictureModel.ImageUrl" title="@Model.DefaultPictureModel.Title" id="mainImage"/>
}
@if (Model.PictureModels.Count > 1)
{
<table class="picture-thumbs">
@for (int i = 0; i < Model.PictureModels.Count; i++)
{
/*----------Existing code----------*/
<td class="a-left">
<a href="@picture.FullSizeImageUrl" data-gallery="lightbox-p" title="@Model.Name" id="thumb">
<img src="@picture.ImageUrl" alt="@picture.AlternateText" title="@picture.Title"/>
</a>
</td>
/*----------Existing code----------*/
}
</table>
}
</div>