Loungeborde

Error executing template "/Designs/Swift/Paragraph/Custom_ProductListGridView.cshtml"
System.NullReferenceException: Object reference not set to an instance of an object.
   at CompiledRazorTemplates.Dynamic.RazorEngine_b40dea6b07ae47dcb94eac8e3978929d.<RenderProductList>b__7_0(TextWriter __razor_helper_writer) in D:\dynamicweb.net\Solutions\Skabertrang\thorsdesign.dw9.dynamicweb-cms.com\Files\Templates\Designs\Swift\Paragraph\Custom_ProductListGridView.cshtml:line 445
   at CompiledRazorTemplates.Dynamic.RazorEngine_b40dea6b07ae47dcb94eac8e3978929d.Execute() in D:\dynamicweb.net\Solutions\Skabertrang\thorsdesign.dw9.dynamicweb-cms.com\Files\Templates\Designs\Swift\Paragraph\Custom_ProductListGridView.cshtml:line 48
   at RazorEngine.Templating.TemplateBase.RazorEngine.Templating.ITemplate.Run(ExecuteContext context, TextWriter reader)
   at RazorEngine.Templating.RazorEngineService.RunCompile(ITemplateKey key, TextWriter writer, Type modelType, Object model, DynamicViewBag viewBag)
   at RazorEngine.Templating.RazorEngineServiceExtensions.<>c__DisplayClass16_0.<RunCompile>b__0(TextWriter writer)
   at RazorEngine.Templating.RazorEngineServiceExtensions.WithWriter(Action`1 withWriter)
   at Dynamicweb.Rendering.RazorTemplateRenderingProvider.Render(Template template)
   at Dynamicweb.Rendering.TemplateRenderingService.Render(Template template)
   at Dynamicweb.Rendering.Template.RenderRazorTemplate()

1 @inherits Dynamicweb.Rendering.ViewModelTemplate<Dynamicweb.Frontend.ParagraphViewModel> 2 @using Dynamicweb.Ecommerce.ProductCatalog 3 @using Dynamicweb.Ecommerce.CustomerExperienceCenter.Favorites 4 @using System.Linq 5 @using Dynamicweb.Core 6 7 @functions 8 { 9 bool useCrop = true; 10 11 bool isLazyLoadingForProductInfoEnabled = Dynamicweb.Ecommerce.DynamicwebLiveIntegration.TemplatesHelper.IsLazyLoadingForProductInfoEnabled; 12 string liveInfoClass = ""; 13 string productInfoFeed = ""; 14 15 string showPricesWithVat = ""; 16 bool neverShowVat = false; 17 18 ProductListViewModel productList = new ProductListViewModel(); 19 } 20 @{ 21 if (Dynamicweb.Context.Current.Items.Contains("ProductList")) { 22 productList = (ProductListViewModel)Dynamicweb.Context.Current.Items["ProductList"]; 23 } 24 25 showPricesWithVat = Pageview.Area.EcomPricesWithVat.ToLower(); 26 neverShowVat = string.IsNullOrEmpty(showPricesWithVat); 27 28 if (isLazyLoadingForProductInfoEnabled) { 29 if (Dynamicweb.Context.Current.Items.Contains("ProductInfoFeed")) { 30 productInfoFeed = Dynamicweb.Context.Current.Items["ProductInfoFeed"]?.ToString(); 31 if (!string.IsNullOrEmpty(productInfoFeed)) { 32 productInfoFeed = $"data-product-info-feed=\"{productInfoFeed}\""; 33 } 34 } 35 liveInfoClass = "js-live-info"; 36 } 37 38 string theme = !string.IsNullOrWhiteSpace(Model.Item.GetRawValueString("Theme")) ? " theme " + Model.Item.GetRawValueString("Theme").Replace(" ", "").Trim().ToLower() : ""; 39 string themePadding = theme != string.Empty ? "p-3" : string.Empty; 40 } 41 42 @if (!string.IsNullOrEmpty(theme)) { 43 <div class="h-100@(theme) @themePadding item_@Model.Item.SystemName.ToLower()" @productInfoFeed> 44 @RenderProductList() 45 </div> 46 } else { 47 <div class="pt-3 item_@Model.Item.SystemName.ToLower()" @productInfoFeed> 48 @RenderProductList() 49 </div> 50 } 51 52 @helper RenderProductList() { 53 string anonymousUsersLimitations = Pageview.AreaSettings.GetRawValueString("AnonymousUsers", ""); 54 bool anonymousUser = Pageview.User == null; 55 bool hidePrice = anonymousUsersLimitations.Contains("price") && anonymousUser || Pageview.AreaSettings.GetBoolean("ErpDownHidePrices") && !Dynamicweb.Ecommerce.DynamicwebLiveIntegration.TemplatesHelper.IsWebServiceConnectionAvailable(); 56 57 string detailsPageLink = Dynamicweb.Context.Current.Items["DetailsPageLink"] != null ? Dynamicweb.Context.Current.Items["DetailsPageLink"].ToString() : ""; 58 string productTheme = !string.IsNullOrWhiteSpace(Model.Item.GetRawValueString("ProductTheme")) ? " theme " + Model.Item.GetRawValueString("ProductTheme").Replace(" ", "").Trim().ToLower() : ""; 59 string productThemePadding = productTheme != string.Empty ? "p-3" : string.Empty; 60 61 string url = Dynamicweb.Context.Current.Request.RawUrl; 62 bool hideFavoritesSelector = !string.IsNullOrEmpty(Model.Item.GetString("HideFavoritesSelector")) ? Model.Item.GetBoolean("HideFavoritesSelector") : false; 63 string staticVariantsLayout = Model.Item.GetRawValueString("StaticVariantsLayout", "hide"); 64 65 string groupId = !string.IsNullOrEmpty(Dynamicweb.Context.Current.Request.QueryString.Get("GroupID")) ? Dynamicweb.Context.Current.Request.QueryString.Get("GroupID") : ""; 66 67 var badgeParms = new Dictionary<string, object>(); 68 badgeParms.Add("saleBadgeType", Model.Item.GetRawValue("SaleBadgeType")); 69 badgeParms.Add("saleBadgeCssClassName", Model.Item.GetRawValue("SaleBadgeDesign")); 70 badgeParms.Add("newBadgeCssClassName", Model.Item.GetRawValue("NewBadgeDesign")); 71 badgeParms.Add("newPublicationDays", Model.Item.GetInt32("NewPublicationDays")); 72 badgeParms.Add("campaignBadgesValues", Model.Item.GetRawValueString("CampaignBadges")); 73 74 bool saleBadgeEnabled = !string.IsNullOrWhiteSpace(Model.Item.GetRawValueString("SaleBadgeDesign")) && Model.Item.GetRawValueString("SaleBadgeDesign") != "none" ? true : false; 75 bool newBadgeEnabled = !string.IsNullOrWhiteSpace(Model.Item.GetRawValueString("NewBadgeDesign")) && Model.Item.GetRawValueString("NewBadgeDesign") != "none" ? true : false; 76 77 var favoriteParameters = new Dictionary<string, object>(); 78 if (!anonymousUser && !hideFavoritesSelector) { 79 int defaultFavoriteListId = 0; 80 81 IEnumerable<FavoriteList> favoreiteLists = Pageview.User.GetFavoriteLists(); 82 if (favoreiteLists.Count() == 1) { 83 foreach (FavoriteList list in favoreiteLists) { 84 defaultFavoriteListId = list.ListId; 85 } 86 } 87 88 favoriteParameters.Add("ListId", defaultFavoriteListId); 89 } 90 91 if (productList.TotalProductsCount > 0) { 92 int pageSizeSetting = 30; 93 int pageSize = productList.PageSize; 94 pageSize += pageSizeSetting; 95 96 int loadedProducts = productList.PageSize > productList.TotalProductsCount ? productList.TotalProductsCount : productList.PageSize; 97 98 //REMOVE BEFORE RELEASE 99 Dynamicweb.Ecommerce.Common.Context.CartContext = Dynamicweb.Ecommerce.Orders.OrderContext.GetOrderContextById("ORDERCONTEXT2"); 100 101 @*<div class="grid grid-2 grid-lg-4">*@ 102 <div class="grid grid-2 grid-sm-2 grid-md-3 grid-lg-3 grid-xl-4"> 103 @foreach (ProductViewModel product in productList.Products) { 104 105 106 var defaultGroupId = product.PrimaryOrDefaultGroup.Id; 107 var selectedDetailPage = Dynamicweb.Ecommerce.Services.ProductGroups.GetGroup(defaultGroupId)?.Meta.PrimaryPage ?? string.Empty; 108 109 string link = string.IsNullOrEmpty(selectedDetailPage) ? $"{detailsPageLink}&groupid={defaultGroupId}" : selectedDetailPage; 110 link += "&productid=" + product.Id; 111 link += !string.IsNullOrEmpty(product.VariantId) ? "&variantid=" + product.VariantId : ""; 112 //link += !string.IsNullOrEmpty(product.DefaultVariantId) ? "&variantid=" + product.DefaultVariantId : ""; 113 114 string imagePath = product?.DefaultImage?.Value ?? ""; 115 imagePath = Dynamicweb.Context.Current.Server.UrlEncode(imagePath); 116 117 string ratio = Model.Item.GetRawValueString("ImageAspectRatio", ""); 118 ratio = ratio != "0" ? ratio : ""; 119 string ratioCssClass = ratio != "" ? " ratio" : ""; 120 string ratioVariable = ratio != "" ? "--bs-aspect-ratio: " + ratio : ""; 121 string imgQuality = "&Quality=75"; 122 123 string imagePathXs = "/Admin/Public/GetImage.ashx?width=" + 300 + "&image=" + imagePath + "&format=webp" + imgQuality; 124 string imagePathS = "/Admin/Public/GetImage.ashx?width=" + 300 + "&image=" + imagePath + "&format=webp" + imgQuality; 125 string imagePathFallBack = "/Admin/Public/GetImage.ashx?width=" + 300 + "&image=" + imagePath + "&format=webp" + imgQuality; 126 127 128 string imageTheme = !string.IsNullOrWhiteSpace(Model.Item.GetRawValueString("ImageTheme")) ? " theme " + Model.Item.GetRawValueString("ImageTheme").Replace(" ", "").Trim().ToLower() : ""; 129 string imageThemePadding = imageTheme != string.Empty ? "p-3" : string.Empty; 130 string imageOutlineStyle = imageTheme == string.Empty ? "style=\"border: 1px solid transparent\"" : string.Empty; 131 132 string imageId = "ProductImage_" + product.Id + product.VariantId; 133 string priceId = "ProductPrice_" + product.Id + product.VariantId; 134 135 @* Alternative image *@ 136 var supportedImageFormats = new string[] { ".jpg", ".webp", ".png", ".gif" }; 137 string defaultImage = product.DefaultImage != null ? product.DefaultImage.Value : ""; 138 var selectedAssetCategories = Model.Item.GetRawValueString("AlternativeImageAssets"); 139 IEnumerable<MediaViewModel> alternativeImagesList = product.AssetCategories.Where(x => selectedAssetCategories.Contains(x.SystemName)).SelectMany(x => x.Assets); 140 141 if (alternativeImagesList.FirstOrDefault() != null) { 142 alternativeImagesList = alternativeImagesList.OrderByDescending(x => x.Value.Equals(defaultImage)); 143 144 if (alternativeImagesList.First().Value == defaultImage) { 145 alternativeImagesList = alternativeImagesList.Skip(1); 146 } 147 } 148 149 string alternativeImage = alternativeImagesList.FirstOrDefault() != null ? alternativeImagesList.FirstOrDefault().Value : ""; 150 alternativeImage = !string.IsNullOrEmpty(alternativeImage) ? "/Admin/Public/GetImage.ashx?width=" + 300 + "&image=" + alternativeImage + "&format=webp" + imgQuality : ""; 151 if (useCrop) { 152 imagePathXs = imagePathXs + "&height=450&crop=7"; 153 imagePathS = imagePathS + "&height=450&crop=7"; 154 imagePathFallBack = imagePathFallBack + "&height=450&crop=7"; 155 if (!string.IsNullOrWhiteSpace(alternativeImage)) { 156 alternativeImage = alternativeImage + "&height=450&crop=7"; 157 } 158 159 } 160 161 @* Badges *@ 162 DateTime createdDate = product.Created.Value; 163 bool showBadges = saleBadgeEnabled && product.Discount.Price != 0 ? true : false; 164 showBadges = (newBadgeEnabled && Model.Item.GetInt32("NewPublicationDays") == 0) || (newBadgeEnabled && (createdDate.AddDays(Model.Item.GetInt32("NewPublicationDays")) > DateTime.Now)) ? true : showBadges; 165 showBadges = !string.IsNullOrEmpty(Model.Item.GetRawValueString("CampaignBadges")) ? true : showBadges; 166 167 @* Main features *@ 168 IEnumerable<string> selectedDisplayGroups = Model.Item.GetRawValueString("MainFeatures").Split(',').ToList(); 169 List<CategoryFieldViewModel> mainFeatures = new List<CategoryFieldViewModel>(); 170 171 foreach (var selection in selectedDisplayGroups) { 172 foreach (CategoryFieldViewModel group in product.FieldDisplayGroups.Values) { 173 if (selection == group.Id) { 174 mainFeatures.Add(group); 175 } 176 } 177 } 178 179 <article class="position-relative@(productTheme) product-list-item product @liveInfoClass" data-product-id="@product.Id" itemscope itemtype="https://schema.org/Product"> 180 @if (!anonymousUser && !hideFavoritesSelector && product.VariantInfo.VariantInfo == null) { 181 <div class="position-absolute top-0 end-0 my-3" style="z-index: 2"> 182 @RenderPartial("Components/ToggleFavorite.cshtml", product, favoriteParameters) 183 </div> 184 } 185 186 @if (showBadges) { 187 <div class="position-absolute top-0 left-0 p-1 p-lg-2 ps-0 ps-lg-0" style="z-index: 2"> 188 @RenderPartial("Components/EcommerceBadge.cshtml", product, badgeParms) 189 </div> 190 } 191 192 <div class="d-flex flex-column d-block h-100"> 193 194 <a href="@link" class="text-decoration-none"> 195 <div class="overflow-hidden@(imageTheme)" @imageOutlineStyle> 196 <div> 197 <div class="d-flex justify-content-center align-items-center"> 198 @if (string.IsNullOrEmpty(alternativeImage)) { 199 <img id="@imageId" 200 srcset=" 201 @imagePathXs 480w, 202 @imagePathS 640w" 203 sizes="(min-width: 992px) 33vw, 50vw" 204 src="@imagePathFallBack" 205 loading="lazy" 206 decoding="async" 207 class="mw-100 mh-100 w-100 @imageThemePadding" 208 alt="@product.Name"> 209 } else { 210 <img id="@imageId" 211 src="@imagePathFallBack" 212 loading="lazy" 213 decoding="async" 214 class="mw-100 mh-100 w-100 @imageThemePadding" 215 alt="@product.Name" 216 onmouseover="this.src='@alternativeImage'" 217 onmouseout="this.src='@imagePathFallBack'"> 218 } 219 </div> 220 </div> 221 222 223 <div class="position-relative"> 224 @if (product.VariantInfo.VariantInfo != null && staticVariantsLayout == "images") { 225 int variantGroupCount = 0; 226 int showMaxVariantGroups = 2; 227 int showMaxVariants = 3; 228 var productVariantTheme = productTheme != "" ? productTheme : "bg-white"; 229 230 <div class="static-variants w-100 d-none d-lg-block position-absolute left-0 bottom-0 @productTheme" 231 id="StaticVariants_@product.Id" 232 style="pointer-events: none;"> 233 234 @foreach (var variantGroup in product.VariantGroups()) { 235 int variantsCount = 0; 236 237 <div class="d-flex gap-2 mb-2"> 238 @foreach (var variant in variantGroup.Options) { 239 if (variantGroupCount < showMaxVariantGroups) { 240 var optionsCount = variantGroup.Options.Count(); 241 242 if (variantsCount < showMaxVariants) { 243 string optionWidth = !string.IsNullOrEmpty(variant.Color) ? "w-25" : ""; 244 245 <article class="static-variants-option @optionWidth @(productVariantTheme)" title="@product.Name @variant.Name" style="pointer-events: initial;"> 246 @if (!string.IsNullOrEmpty(variant.Color)) { 247 string defaultProductImage = Dynamicweb.Context.Current.Server.UrlEncode(product.DefaultImage.Value); 248 string variantImage = Dynamicweb.Context.Current.Server.UrlEncode(variant.Image.Value); 249 string defaultPrice = !hidePrice ? product.Price.PriceFormatted : "0"; 250 string variantPrice = !hidePrice ? product.Price.PriceFormatted : "0"; 251 252 if (isLazyLoadingForProductInfoEnabled) { 253 <figure class="figure w-100 d-block m-0" data-price-formatted="" onmouseover="switchVariantProduct('@product.Id', this.getAttribute('data-price-formatted'), '@variantImage')" onmouseout="switchVariantProduct('@product.Id', this.getAttribute('data-price-formatted'), '@defaultProductImage')"> 254 <div class="d-flex align-items-center justify-content-center"> 255 <img src="/admin/public/GetImage.ashx?image=@variantImage&width=75&height=75&crop=5&FillCanvas=true&format=webp&Quality=70" height="75" width="75" class="p-1 text-small" loading="lazy" decoding="async" alt="@product.Name, @variant.Name"> 256 </div> 257 </figure> 258 } else { 259 <figure class="figure w-100 d-block m-0" onmouseover="switchVariantProduct('@product.Id', '@defaultPrice', '@variantImage')" onmouseout="switchVariantProduct('@product.Id', '@variantPrice', '@defaultProductImage')"> 260 <div class="d-flex align-items-center justify-content-center"> 261 <img src="/admin/public/GetImage.ashx?image=@variantImage&width=75&height=75&crop=5&FillCanvas=true&format=webp&Quality=70" height="75" width="75" class="p-1 text-small" loading="lazy" decoding="async" alt="@product.Name, @variant.Name"> 262 </div> 263 </figure> 264 } 265 } else { 266 <div class="d-flex align-items-center justify-content-center"> 267 @variant.Name 268 </div> 269 } 270 <div class="visually-hidden"> 271 <h4>@Translate("Variant Name")</h4> 272 <p>@product.Name, @variant.Name</p> 273 @if (!hidePrice) { 274 <h4>@Translate("Variant Price")</h4> 275 if (isLazyLoadingForProductInfoEnabled) { 276 <p><span class="text-price js-text-price"></span></p> 277 } else { 278 <p><span class="text-price">@product.Price.PriceFormatted</span></p> 279 } 280 } 281 </div> 282 </article> 283 } 284 285 variantsCount++; 286 287 if (variantsCount == showMaxVariants && optionsCount != showMaxVariants) { 288 int left = optionsCount - showMaxVariants; 289 <div class="variant-option ms-1 d-flex justify-content-center align-items-center"> 290 <span>+@left</span> 291 </div> 292 } 293 } 294 } 295 296 </div> 297 298 variantGroupCount++; 299 } 300 </div> 301 } 302 </div> 303 </div> 304 <div class="pt-3 pb-3"> 305 <div class="flex-grow-1"> 306 <h3 class="h6 mb-0 text-break ff-primary fw-500">@product.Name @if (!string.IsNullOrEmpty(product.VariantName)) {<text>(@product.VariantName)</text>}</h3> 307 @if (!Model.Item.GetBoolean("HideProductNumber")) { 308 <p class="fs-7 opacity-85 mb-2">@product.Number</p> 309 } 310 @if (mainFeatures.Count > 0) { 311 <ul class="p-0 lh-sm opacity-75" style="list-style-position: inside"> 312 @foreach (CategoryFieldViewModel mainFeatureGroup in mainFeatures) { 313 foreach (var field in mainFeatureGroup.Fields) { 314 @RenderField(field.Value) 315 } 316 } 317 </ul> 318 } 319 </div> 320 321 @if (!hidePrice) { 322 string priceMin = ""; 323 string priceMax = ""; 324 325 <div> 326 <div> 327 <span itemprop="priceCurrency" content="@product.Price.CurrencyCode" class="d-none"></span> 328 329 @if (showPricesWithVat == "false" && !neverShowVat) { 330 if (isLazyLoadingForProductInfoEnabled) { 331 <span itemprop="price" content="" class="d-none"></span> 332 <span class="text-decoration-line-through js-text-decoration-line-through opacity-75 me-3 text-price js-text-price d-none" data-show-if="LiveProductInfo.product.Price.Price != LiveProductInfo.product.PriceBeforeDiscount.Price"></span> 333 } else { 334 string beforePrice = product.PriceBeforeDiscount.PriceWithoutVatFormatted; 335 <span itemprop="price" content="@product.Price.PriceWithoutVat" class="d-none"></span> 336 if (product.Price.Price != product.PriceBeforeDiscount.Price) { 337 <span class="text-decoration-line-through opacity-75 me-3 text-price">@beforePrice</span> 338 } 339 } 340 341 } else { 342 343 if (isLazyLoadingForProductInfoEnabled) { 344 <span itemprop="price" content="" class="d-none"></span> 345 <span class="text-decoration-line-through js-text-decoration-line-through opacity-75 me-3 text-price js-text-price d-none" data-show-if="LiveProductInfo.product.Price.Price != LiveProductInfo.product.PriceBeforeDiscount.Price"></span> 346 } else { 347 string beforePrice = product.PriceBeforeDiscount.PriceFormatted; 348 349 <span itemprop="price" content="@product.Price.Price" class="d-none"></span> 350 if (product.Price.Price != product.PriceBeforeDiscount.Price) { 351 <span class="text-decoration-line-through opacity-75 me-3 text-price">@beforePrice</span> 352 } 353 } 354 } 355 356 @if (showPricesWithVat == "false" && !neverShowVat) { 357 if (isLazyLoadingForProductInfoEnabled) { 358 <span class="text-price js-text-price"><div class="spinner-border" role="status"></div></span> 359 } else { 360 string price = product.Price.PriceWithoutVatFormatted; 361 if (product?.VariantInfo?.VariantInfo != null) { 362 priceMin = product?.VariantInfo?.PriceMin?.PriceWithoutVatFormatted != null ? product.VariantInfo.PriceMin.PriceWithoutVatFormatted : ""; 363 priceMax = product?.VariantInfo?.PriceMax?.PriceWithoutVatFormatted != null ? product.VariantInfo.PriceMax.PriceWithoutVatFormatted : ""; 364 } 365 if (priceMin != priceMax) { 366 //price = priceMin + " - " + priceMax; 367 368 price = "<span class= \"d-inline-block text-nowrap\">" + priceMin + " -</span>" + "&nbsp;" + "<span class= \"d-inline-block text-nowrap\">" + priceMax + "</span>"; 369 } 370 @*<span class="text-price">@price</span>*@ 371 372 <div class="text-price">@price</div> 373 } 374 } else { 375 if (isLazyLoadingForProductInfoEnabled) { 376 <span class="text-price js-text-price"><div class="spinner-border" role="status"></div></span> 377 } else { 378 string price = product.Price.PriceFormatted; 379 if (product?.VariantInfo?.VariantInfo != null) { 380 priceMin = product?.VariantInfo?.PriceMin?.PriceFormatted != null ? product.VariantInfo.PriceMin.PriceFormatted : ""; 381 priceMax = product?.VariantInfo?.PriceMax?.PriceFormatted != null ? product.VariantInfo.PriceMax.PriceFormatted : ""; 382 } 383 if (priceMin != priceMax) { 384 //price = priceMin + " - " + priceMax; 385 386 price = "<span class= \"d-inline-block text-nowrap\">" + priceMin + " -</span>" + "&nbsp;" + "<span class= \"d-inline-block text-nowrap\">" + priceMax + "</span>"; 387 } 388 @*<span class="text-price">@price</span>*@ 389 390 <div class="text-price">@price</div> 391 392 } 393 } 394 </div> 395 @if (showPricesWithVat == "false" && !neverShowVat) { 396 if (isLazyLoadingForProductInfoEnabled) { 397 <div class="fs-7 opacity-85 text-price js-text-price-with-vat d-none" data-suffix="@Translate("Incl. VAT")"></div> 398 } else { 399 string price = product.Price.PriceWithVatFormatted; 400 if (product?.VariantInfo?.VariantInfo != null) { 401 priceMin = product?.VariantInfo?.PriceMin?.PriceWithVatFormatted != null ? product.VariantInfo.PriceMin.PriceWithVatFormatted : ""; 402 priceMax = product?.VariantInfo?.PriceMax?.PriceWithVatFormatted != null ? product.VariantInfo.PriceMax.PriceWithVatFormatted : ""; 403 } 404 if (priceMin != priceMax) { 405 price = priceMin + " - " + priceMax; 406 } 407 <div class="fs-7 opacity-85 text-price">@price @Translate("Incl. VAT")</div> 408 } 409 } 410 </div> 411 } 412 413 @if (product.VariantInfo.VariantInfo != null && staticVariantsLayout == "swatches") { 414 var optionCount = product.VariantInfo.VariantInfo.Count(); 415 var showMaxVariants = 5; 416 417 <div class="d-flex flex-row gap-1 align-items-center"> 418 @foreach (VariantInfoViewModel variant in product.VariantInfo.VariantInfo.Take(showMaxVariants)) { 419 <span class="colorbox colorbox-sm rounded-circle border me-1" style="background-color: @variant.OptionColor"></span> 420 } 421 @if (optionCount > showMaxVariants) { 422 int left = optionCount - showMaxVariants; 423 <span class="ms-2">+@left</span> 424 } 425 </div> 426 } 427 </div> 428 </a> 429 </div> 430 </article> 431 } 432 </div> 433 434 <div class="my-3 d-none" id="LoadMoreButton"> 435 <div class="text-center d-flex flex-column gap-3"> 436 <div class="opacity-85">@loadedProducts @Translate("out of") @productList.TotalProductsCount @Translate("products")</div> 437 @if (productList.PageCount != 1) { 438 string sortBySelection = Dynamicweb.Context.Current.Request?.Form["SortBy"] ?? "NameForSort"; 439 sortBySelection = !string.IsNullOrEmpty(Dynamicweb.Context.Current.Request.QueryString.Get("SortBy")) ? Dynamicweb.Context.Current.Request.QueryString.Get("SortBy") : sortBySelection; 440 441 string searchQuery = !string.IsNullOrEmpty(Dynamicweb.Context.Current.Request.QueryString.Get("q")) ? Dynamicweb.Context.Current.Request.QueryString.Get("q") : ""; 442 string searchLayout = !string.IsNullOrEmpty(Dynamicweb.Context.Current.Request.QueryString.Get("SearchLayout")) ? Dynamicweb.Context.Current.Request.QueryString.Get("SearchLayout") : ""; 443 444 <form method="get" action="@url" data-response-target-element="content" class="w-100"> 445 @foreach (FacetGroupViewModel facetGroup in productList.FacetGroups) { 446 foreach (FacetViewModel facetItem in facetGroup.Facets) { 447 foreach (FacetOptionViewModel facetOption in facetItem.Options) { 448 if (facetOption.Selected) { 449 <input type="hidden" name="@facetItem.QueryParameter" value="[@facetOption.Value]" /> 450 } 451 } 452 } 453 } 454 455 @if (productList?.Group?.Id != null) { 456 <input type="hidden" name="GroupId" value="@productList.Group.Id" /> 457 } 458 459 <input type="hidden" name="PageSize" value="@pageSize" /> 460 <input type="hidden" name="SortBy" value="@sortBySelection" /> 461 <input type="hidden" name="RequestType" value="UpdateList" /> 462 463 @if (!string.IsNullOrEmpty(searchQuery)) { 464 <input type="hidden" name="q" value="@searchQuery" /> 465 <input type="hidden" name="SearchLayout" value="@searchLayout" /> 466 } 467 468 @{ 469 string nextPageLink = "/Default.aspx?ID=" + Pageview.Page.ID + "&PageSize=" + pageSize + "&SortBy=" + sortBySelection; 470 471 foreach (FacetGroupViewModel facetGroup in productList.FacetGroups) { 472 foreach (FacetViewModel facetItem in facetGroup.Facets) { 473 foreach (FacetOptionViewModel facetOption in facetItem.Options) { 474 if (facetOption.Selected) { 475 nextPageLink += "&" + facetItem.QueryParameter + "=[" + facetOption.Value + "]"; 476 } 477 } 478 } 479 } 480 481 nextPageLink += productList?.Group?.Id != null ? "&GroupID=" + productList.Group.Id : ""; 482 nextPageLink += !string.IsNullOrEmpty(searchQuery) ? "&q=" + searchQuery : ""; 483 } 484 485 <a href="@nextPageLink" class="btn btn-primary" type="button" onclick="swift.ProductList.Update(event)" id="LoadMoreButton_@Model.ID">@Translate("Load more products")</a> 486 </form> 487 } 488 </div> 489 </div> 490 491 <script> 492 function switchVariantProduct(id, price, imagesrc) { 493 var productImageElement = document.querySelector("#ProductImage_" + id); 494 var productPriceElement = document.querySelector("#ProductPrice_" + id + " .text-price"); 495 496 if (productPriceElement) { 497 productPriceElement.innerText = price; 498 } 499 500 if (productImageElement) { 501 productImageElement.src = imagesrc; 502 503 var imageSrcset = productImageElement.srcset; 504 imageSrcset = imageSrcset.replace(/image=.*?&/g, 'image=' + imagesrc + "&"); 505 506 productImageElement.srcset = imageSrcset; 507 } 508 } 509 </script> 510 } else { 511 if (!Pageview.IsVisualEditorMode) { 512 <div class="alert alert-dark m-0"> 513 @Translate("We did not find anything matching your search result") 514 </div> 515 } else { 516 <div class="alert alert-dark m-0" role="alert"> 517 <span>@Translate("Product list: The list will be shown here, if any")</span> 518 </div> 519 } 520 } 521 } 522 523 @helper RenderField(FieldValueViewModel field) { 524 string fieldValue = field?.Value != null ? field.Value.ToString() : ""; 525 526 if (fieldValue != "") { 527 fieldValue = fieldValue == "False" ? Translate("No") : fieldValue; 528 fieldValue = fieldValue == "True" ? Translate("Yes") : fieldValue; 529 530 if (field.Value.GetType() == typeof(System.Collections.Generic.List<FieldOptionValueViewModel>)) { 531 fieldValue = ""; 532 533 foreach (FieldOptionValueViewModel option in field.Value as System.Collections.Generic.List<FieldOptionValueViewModel>) { 534 fieldValue = option.Name; 535 } 536 } 537 538 bool isColor = false; 539 if (fieldValue.Contains("#") && (Translate(field.Name) == Translate("Color") || Translate(field.Name) == Translate("Colour"))) { 540 isColor = true; 541 } 542 543 if (!string.IsNullOrEmpty(fieldValue)) { 544 if (!isColor) { 545 <li>@(field.Name): @fieldValue</li> 546 } else { 547 <li class="position-relative"> 548 <span class="colorbox-sm" style="background-color: @fieldValue"></span> 549 </li> 550 } 551 } 552 } 553 } 554

Besøg vores showrooms

Besøg os i vores showrooms og oplev vores møbler og unikke råmateriale.
Find vores adresse og åbningstider her:

Jylland 

Møltrupvej 29, Timring
7480 Vildbjerg

Det Gamle Mejeri

København 

Århusgade 131
2150 Nordhavn

Edda studio

Nyhedsbrev

Tilmeld dig vores nyhedsbrev og følg med i nyheder og events fra Thors Design, få inspiration til din indretning og meget mere.