Error executing template "Designs/Swift/Paragraph/Swift_ProductListFacets.cshtml"
System.NullReferenceException: Object reference not set to an instance of an object.
   at CompiledRazorTemplates.Dynamic.RazorEngine_b5776fe0eeed45b7b0b0fba763b2bb33.<>c__DisplayClass0_0.<RenderForm>b__0(TextWriter __razor_helper_writer) in D:\dynamicweb.net\Solutions\FlexMedia\siso2021.cloud.dynamicweb-cms.com\files\Templates\Designs\Swift\Paragraph\Swift_ProductListFacets.cshtml:line 300
   at CompiledRazorTemplates.Dynamic.RazorEngine_b5776fe0eeed45b7b0b0fba763b2bb33.Execute() in D:\dynamicweb.net\Solutions\FlexMedia\siso2021.cloud.dynamicweb-cms.com\files\Templates\Designs\Swift\Paragraph\Swift_ProductListFacets.cshtml:line 94
   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.Frontend.Navigation 4 @using Dynamicweb.Environment 5 @using Dynamicweb.Core.Encoders 6 @using System.Web 7 @using Dynamicweb.Core 8 @using System.Linq 9 10 @{ 11 ProductListViewModel productList = new ProductListViewModel(); 12 13 if (Dynamicweb.Context.Current.Items.Contains("ProductList")) 14 { 15 productList = (ProductListViewModel)Dynamicweb.Context.Current.Items["ProductList"]; 16 } 17 18 string url = Pageview.SearchFriendlyUrl; 19 20 21 url = url.LastIndexOf("?") != -1 ? url.Substring(0, url.LastIndexOf("?")) : url; 22 23 24 25 //Fix for non-friendly urls 26 if (Dynamicweb.Context.Current.Request.QueryString.Get("GroupID") != null) 27 { 28 string groupId = Dynamicweb.Context.Current.Request.QueryString.Get("GroupID"); 29 url += "?GroupID=" + groupId; 30 31 32 } 33 34 35 if (!url.Contains("LayoutTemplate")) 36 { 37 url += url.Contains("?") ? "&LayoutTemplate=Designs/Swift/Swift_PageClean.cshtml" : "?LayoutTemplate=Designs/Swift/Swift_PageClean.cshtml"; 38 } 39 40 bool facetsFound = false; 41 int selectedFacetsCount = 0; 42 43 44 45 if (productList.FacetGroups != null) 46 { 47 foreach (FacetGroupViewModel facetGroup in productList.FacetGroups) 48 { 49 foreach (FacetViewModel facet in facetGroup.Facets) 50 { 51 if (facet.Options.Count() > 0) 52 { 53 facetsFound = true; 54 55 foreach (FacetOptionViewModel option in facet.Options) 56 { 57 if (option.Selected) 58 { 59 selectedFacetsCount++; 60 } 61 } 62 } 63 } 64 } 65 } 66 string contentPadding = Model.Item.GetRawValueString("ContentPadding", ""); 67 contentPadding = Model.Item.GetRawValueString("ContentPadding", "") == "none" ? " px-0 py-2" : contentPadding; 68 contentPadding = Model.Item.GetRawValueString("ContentPadding", "") == "small" ? " px-3 py-2" : contentPadding; 69 70 bool enableSorting = Model.Item.GetBoolean("SortByNameAZ"); 71 enableSorting = Model.Item.GetBoolean("SortByNameZA") || enableSorting == true ? true : false; 72 enableSorting = Model.Item.GetBoolean("SortByNewest") || enableSorting == true ? true : false; 73 enableSorting = Model.Item.GetBoolean("SortByLowestPrice") || enableSorting == true ? true : false; 74 enableSorting = Model.Item.GetBoolean("SortByHighestPrice") || enableSorting == true ? true : false; 75 76 string layout = Model.Item.GetRawValueString("Layout", "vertical"); 77 78 79 80 } 81 82 83 84 @if (productList.TotalProductsCount > 0 && (facetsFound || Model.Item.GetBoolean("EnableGroupNavigation") || enableSorting)) 85 { 86 string theme = !string.IsNullOrWhiteSpace(Model.Item.GetRawValueString("Theme")) ? " theme " + Model.Item.GetRawValueString("Theme").Replace(" ", "").Trim().ToLower() : ""; 87 string modalTheme = !string.IsNullOrWhiteSpace(Model.Item.GetRawValueString("ModalTheme")) ? " theme " + Model.Item.GetRawValueString("ModalTheme").Replace(" ", "").Trim().ToLower() : ""; 88 string iconPath = "/Files/Templates/Designs/Swift/Assets/icons/"; 89 string selectedFacetsLabel = selectedFacetsCount > 0 ? "(" + selectedFacetsCount + ")" : ""; 90 91 //Desktop 92 if (layout == "vertical") { 93 <form method="post" action="@url" data-response-target-element="content" id="FacetsForm_Desktop_@Model.ID" class="d-none d-lg-block h-100 @theme item_@Model.Item.SystemName.ToLower()"> 94 @RenderForm(productList, "desktop", enableSorting, layout) 95 </form> 96 97 <script> 98 99 function lastOpened (e){ 100 101 102 if (e.classList.contains('collapsed')){ 103 setCookie("LastOpenedFacet", 0, 0); 104 } else { 105 setCookie("LastOpenedFacet", e.innerText, 10); 106 } 107 108 109 } 110 111 function setCookie(name, value, maxAgeSeconds) { 112 var maxAgeSegment = "; max-age=" + maxAgeSeconds; 113 document.cookie = encodeURI(name) + "=" + encodeURI(value) + maxAgeSegment; 114 } 115 116 window.onscroll = function() {fixedFacets(facetsTopPosOriginal)}; 117 118 let facetsTopPosOriginal = document.getElementById("FacetsForm_Desktop_@Model.ID").getBoundingClientRect().top; 119 120 121 122 function fixedFacets(facetsTopPosOriginal){ 123 124 let scrollPosition = window.pageYOffset; 125 126 let headerBottomPos = document.getElementsByClassName("page-header")[0].getBoundingClientRect().bottom; 127 let footerTopPos = document.getElementsByClassName("page-footer")[0].getBoundingClientRect().top; 128 129 let facetsTop = document.getElementById("FacetsForm_Desktop_@Model.ID"); 130 let facetsTopPos = facetsTop.getBoundingClientRect().top; 131 let facetsBottomPos = facetsTop.getBoundingClientRect().bottom; 132 let facetsTopParent = facetsTop.parentElement; 133 134 let horizontalFacets; 135 let horizontalFacetsParent; 136 137 if (document.getElementsByClassName("sticky-facets-horizontal").length > 0 ){ 138 139 horizontalFacets = document.getElementsByClassName("sticky-facets-horizontal")[0]; 140 horizontalFacetsParent = document.getElementsByClassName("sticky-facets-horizontal")[0].parentElement; 141 142 } else { 143 144 horizontalFacets = document.getElementsByClassName("sticky-facets-horizontal-mobile")[0].parentElement; 145 horizontalFacetsParent = horizontalFacets.parentElement; 146 147 horizontalFacets.classList.add("sticky-mobile"); 148 149 } 150 151 152 if (facetsTopPosOriginal < scrollPosition + headerBottomPos ) { 153 facetsTop.classList.add("sticky"); 154 facetsTop.style.cssText = '--bs-columns:12; --sticky-top:' + headerBottomPos + 'px; width:' + facetsTopParent.offsetWidth + 'px'; 155 156 horizontalFacets.classList.add("sticky"); 157 horizontalFacets.style.cssText = '--sticky-top:' + headerBottomPos + 'px; width:' + horizontalFacetsParent.offsetWidth + 'px'; 158 159 160 } else { 161 facetsTop.classList.remove("sticky"); 162 horizontalFacets.classList.remove("sticky"); 163 } 164 } 165 166 </script> 167 168 } 169 if (layout == "horizontal") { 170 contentPadding = Model.Item.GetRawValueString("ContentPadding", "") == "small" ? " p-3" : contentPadding; 171 172 173 <div class="@theme @contentPadding h-100"> 174 <form method="post" action="@url" data-response-target-element="content" id="FacetsForm_Desktop_@Model.ID" class="d-none d-lg-flex gap-3 flex-row flex-wrap item_@Model.Item.SystemName.ToLower()"> 175 @RenderForm(productList, "desktop", enableSorting, layout) 176 177 @if (selectedFacetsCount > 0) { 178 <button type="button" class="btn btn-sm me-sm-1 me-lg-2" onclick="swift.ProductList.ResetFacets(event)"><span class="icon-2">@ReadFile(iconPath + "rotate-ccw.svg")</span> @Translate("Clear filters")</button> 179 } 180 </form> 181 </div> 182 } 183 184 bool showFiltersForThisGroup = false; 185 186 string groupId = !string.IsNullOrEmpty(Dynamicweb.Context.Current.Request.QueryString.Get("GroupID")) ? Dynamicweb.Context.Current.Request.QueryString.Get("GroupID") : ""; 187 188 189 if (!string.IsNullOrEmpty(groupId)){ 190 191 var group = Dynamicweb.Ecommerce.Services.ProductGroups.GetGroup(groupId); 192 193 194 foreach (var customfield in group.ProductGroupFieldValues) { 195 if (customfield.ProductGroupField.SystemName == "ShowProductFilters"){ 196 if (customfield.Value.ToString() == "True"){ 197 showFiltersForThisGroup = true; 198 } 199 } 200 201 } 202 } 203 204 if (showFiltersForThisGroup){ 205 206 207 //Mobile 208 <div class="d-block d-lg-none mt-lg-0 @(contentPadding)@(theme) sticky-facets-horizontal-mobile FacetsForm_Mobile_@Model.Item.SystemName.ToLower()_@Model.ID"> 209 210 211 212 <button type="button" class="btn btn-primary w-100" data-bs-toggle="modal" data-bs-target="#FacetsModal"> 213 <span class="d-flex align-items-center"> 214 <span class="flex-grow-1 text-start"> 215 @Translate("Filter") @selectedFacetsLabel 216 </span> 217 <span class="icon-2"> 218 @ReadFile(iconPath + "sliders.svg") 219 </span> 220 </span> 221 </button> 222 223 <form method="post" action="@url" data-response-target-element="content" class="modal" id="FacetsModal" tabindex="-1" aria-hidden="false"> 224 <div class="modal-dialog modal-fullscreen"> 225 <div class="modal-content"> 226 227 <div class="modal-header@(modalTheme)"> 228 <h5 class="modal-title">@Translate("Filters and sorting")</h5> 229 <button type="button" class="btn-close" data-bs-dismiss="modal" aria-label="Close" onclick="document.querySelector('body').style = ''"></button> 230 </div> 231 <div class="modal-body@(modalTheme)"> 232 @RenderForm(productList, "mobile", enableSorting) 233 </div> 234 <div class="modal-footer d-flex@(modalTheme)"> 235 @if (selectedFacetsCount != 0) 236 { 237 <button type="button" class="btn btn-secondary flex-fill" onclick="swift.ProductList.ResetFacets(event)">@Translate("Clear") (@selectedFacetsCount)</button> 238 } 239 <button type="button" class="btn btn-primary flex-fill" onclick="location.reload();">@Translate("Update")</button> 240 </div> 241 </div> 242 </div> 243 </form> 244 </div> 245 246 } 247 } 248 else 249 { 250 if (Pageview.IsVisualEditorMode) 251 { 252 <div class="alert alert-dark m-0" role="alert"> 253 <span>@Translate("Facets: The facets selectors will be shown here, if any")</span> 254 </div> 255 } 256 else if (productList.TotalProductsCount > 0) 257 { 258 @*<div class="alert alert-dark m-0" id="NoFiltersAlert_@Model.ID"> 259 @Translate("No filters are available") 260 </div>*@ 261 262 } 263 } 264 265 266 @helper RenderForm(ProductListViewModel productList, string deviceType, bool enableSorting, string layout = "vertical") 267 { 268 string groupId = !string.IsNullOrEmpty(Dynamicweb.Context.Current.Request.QueryString.Get("GroupID")) ? Dynamicweb.Context.Current.Request.QueryString.Get("GroupID") : ""; 269 270 string iconPath = "/Files/Templates/Designs/Swift/Assets/icons/"; 271 string pageSize = !string.IsNullOrEmpty(Dynamicweb.Context.Current.Request.QueryString.Get("PageSize")) ? Dynamicweb.Context.Current.Request.QueryString.Get("PageSize") : productList.PageSize.ToString(); 272 273 string searchQuery = !string.IsNullOrEmpty(Dynamicweb.Context.Current.Request.QueryString.Get("q")) ? Dynamicweb.Context.Current.Request.QueryString.Get("q") : ""; 274 string searchLayout = !string.IsNullOrEmpty(Dynamicweb.Context.Current.Request.QueryString.Get("SearchLayout")) ? Dynamicweb.Context.Current.Request.QueryString.Get("SearchLayout") : ""; 275 276 string groupsTheme = ""; 277 string extraBottomMargin = ""; 278 if (deviceType != "mobile") 279 { 280 groupsTheme = !string.IsNullOrWhiteSpace(Model.Item.GetRawValueString("FacetGroupsTheme")) ? " theme " + Model.Item.GetRawValueString("FacetGroupsTheme").Replace(" ", "").Trim().ToLower() : ""; 281 extraBottomMargin = !string.IsNullOrEmpty(groupsTheme) ? "mb-3" : ""; 282 } 283 284 string contentPadding = Model.Item.GetRawValueString("ContentPadding", ""); 285 contentPadding = contentPadding == "none" ? " px-0 py-2" : contentPadding; 286 contentPadding = contentPadding == "small" ? " px-3 py-2" : contentPadding; 287 288 bool showFiltersForThisGroup = false; 289 290 291 if (!string.IsNullOrEmpty(groupId)){ 292 293 var group = Dynamicweb.Ecommerce.Services.ProductGroups.GetGroup(groupId); 294 295 @*if (group.Id == "14.01"){ 296 showFiltersForThisGroup = true; 297 }*@ 298 299 300 foreach (var customfield in group.ProductGroupFieldValues) { 301 if (customfield.ProductGroupField.SystemName == "ShowProductFilters"){ 302 if (customfield.Value.ToString() == "True"){ 303 showFiltersForThisGroup = true; 304 } 305 } 306 307 } 308 309 310 @* if (group.ParentGroups.Count() > 0){ 311 foreach (var parentGroups in group.ParentGroups){ 312 if (parentGroups.Id == "14.01"){ 313 showFiltersForThisGroup = true; 314 } 315 if (parentGroups.Id == "14.02"){ 316 showFiltersForThisGroup = true; 317 } 318 if (parentGroups.Id == "14.03"){ 319 showFiltersForThisGroup = true; 320 } 321 322 if (parentGroups.ParentGroups.Count() > 0){ 323 foreach (var parentParentGroups in parentGroups.ParentGroups){ 324 325 if (parentParentGroups.Id == "14.01"){ 326 showFiltersForThisGroup = true; 327 } 328 329 } 330 } 331 332 } 333 } *@ 334 } 335 336 337 338 339 340 341 @*<input type="hidden" name="PageSize" value="@pageSize">*@ 342 343 344 if (!string.IsNullOrEmpty(searchQuery)) { 345 <input type="hidden" name="q" value="@searchQuery"> 346 <input type="hidden" name="SearchLayout" value="@searchLayout"> 347 } 348 349 350 if (Model.Item.GetBoolean("EnableGroupNavigation")) 351 { 352 int startLevel = Convert.ToInt32(Model.Item.GetRawValueString("GroupNavigationStartLevel", "2")); 353 int stopLevel = Convert.ToInt32(Model.Item.GetRawValueString("GroupNavigationStopLevel", "9")); 354 355 var navigationSettings = new NavigationSettings(); 356 navigationSettings.StartLevel = startLevel; 357 navigationSettings.StopLevel = stopLevel; 358 navigationSettings.Parameters.Add("ID", deviceType); 359 navigationSettings.Parameters.Add("HideTexts", false); 360 navigationSettings.Parameters.Add("HideIcons", true); 361 navigationSettings.Parameters.Add("ContentPadding", contentPadding); 362 navigationSettings.ExpandMode = ExpandMode.All; 363 364 if (layout == "vertical") { 365 <div class="border-bottom py-2@(@groupsTheme)"> 366 <div class="d-flex@(contentPadding)" data-bs-toggle="collapse" data-bs-target="#ProductGroupNavigation_@(deviceType)_@Model.ID" role="button" aria-expanded="true" aria-controls="ProductGroupNavigation_@(deviceType)_@Model.ID"> 367 <h2 class="opacity-85 m-0 flex-fill h6">@Translate("Navigation")</h2> 368 <div class="my-auto collapse-chevron-icon"></div> 369 </div> 370 <div class="collapse show" id="ProductGroupNavigation_@(deviceType)_@Model.ID"> 371 @Navigation.RenderNavigation("Navigation/Vertical.cshtml", navigationSettings) 372 </div> 373 </div> 374 } 375 376 } 377 378 379 int groupCount = 0; 380 int maxGroups = 999; 381 int totalGroups = productList?.FacetGroups != null ? productList.FacetGroups.Count() : 0; 382 383 var lastOpenedFacetCookie = HttpContext.Current.Request.Cookies["LastOpenedFacet"]; 384 385 386 if (productList.FacetGroups != null && showFiltersForThisGroup) { 387 <div class="facets-options"> 388 @if (showFiltersForThisGroup){ 389 foreach (FacetGroupViewModel facetGroup in productList.FacetGroups) 390 { 391 string border = groupCount != totalGroups ? "border-bottom" : ""; 392 393 foreach (FacetViewModel facet in facetGroup.Facets) 394 { 395 string collapseClass = string.Empty; 396 string showClass = " show"; 397 string ariaExpanded = "true"; 398 var expandedFacetGroups = Model.Item.GetRawValueString("ExpandFacetGroups", "all"); 399 400 401 if (expandedFacetGroups != "all" && System.Text.RegularExpressions.Regex.IsMatch(expandedFacetGroups, "([0-9])")) 402 { 403 if (groupCount >= Dynamicweb.Core.Converter.ToInt32(expandedFacetGroups)) 404 { 405 collapseClass = " collapsed"; 406 showClass = string.Empty; 407 ariaExpanded = "false"; 408 } 409 410 } 411 412 if(lastOpenedFacetCookie != null){ 413 if (Translate(facet.Name) == lastOpenedFacetCookie.Value.Replace("%20", " ")){ 414 collapseClass = string.Empty; 415 showClass = " show"; 416 ariaExpanded = "true"; 417 } 418 419 } 420 421 if (facet.Options.Count() > 0) 422 { 423 if (layout == "vertical") { 424 <div class="@border@(contentPadding)@(@groupsTheme)"> 425 <div class="d-flex@(collapseClass)" data-bs-toggle="collapse" data-bs-target="#FacetGroup_@facet.Name.Replace(" ", "").Replace(".", "")_@(deviceType)_@Model.ID" role="button" aria-expanded="@ariaExpanded" aria-controls="FacetGroup_@facet.Name.Replace(" ", "").Replace(".", "")_@(deviceType)_@Model.ID" onclick="lastOpened(this)"> 426 <h2 class="opacity-85 m-0 flex-fill h6 my-2">@Translate(facet.Name)</h2> 427 <div class="my-auto collapse-chevron-icon"></div> 428 </div> 429 <div class="collapse@(showClass)" id="FacetGroup_@facet.Name.Replace(" ", "").Replace(".", "")_@(deviceType)_@Model.ID"> 430 @foreach (FacetOptionViewModel facetOption in facet.Options) 431 { 432 string renderType = facet.RenderType; 433 434 if (renderType == "Colors") 435 { 436 @RenderColorOption(facet, facetOption) 437 } 438 else 439 { 440 @RenderCheckboxOption(facet, facetOption) 441 } 442 } 443 </div> 444 </div> 445 } 446 if (layout == "horizontal") { 447 string hideSelector = groupCount < maxGroups ? "" : "d-none"; 448 int selectedFacetsInGroup = 0; 449 450 foreach (FacetOptionViewModel option in facet.Options) 451 { 452 if (option.Selected) 453 { 454 selectedFacetsInGroup++; 455 } 456 } 457 458 string label = selectedFacetsInGroup > 0 ? @Translate(facet.Name) + "<span class=\"badge bg-dark opacity-50 text-white ms-2\">" + selectedFacetsInGroup + "</span>" : @Translate(facet.Name); 459 460 <div class="dropdown @hideSelector js-facets-selector"> 461 <button class="btn @(groupsTheme) dropdown-toggle" type="button" id="FacetGroup_@facet.Name.Replace(" ", "")_@(deviceType)_@Model.ID" data-bs-toggle="dropdown" aria-expanded="false"> 462 @label 463 </button> 464 <div class="dropdown-menu p-3 @(groupsTheme)" aria-labelledby="FacetGroup_@facet.Name.Replace(" ", "")_@(deviceType)_@Model.ID" style="min-width: 280px"> 465 @foreach (FacetOptionViewModel facetOption in facet.Options) 466 { 467 string translation = Translate(facetOption?.Value.ToString()); // 468 string renderType = facet.RenderType; 469 470 if (renderType == "Colors") 471 { 472 @RenderColorOption(facet, facetOption) 473 } 474 else 475 { 476 @RenderCheckboxOption(facet, facetOption) 477 } 478 } 479 </div> 480 </div> 481 } 482 483 groupCount++; 484 } 485 } 486 } 487 } 488 489 </div> 490 } 491 492 if (enableSorting) 493 { 494 <div class="right"> 495 @if (layout == "vertical") { 496 <div class="border-bottom@(contentPadding)@(groupsTheme)"> 497 <h2 class="opacity-85 m-0 my-2 flex-fill h6">@Translate("Sort by")</h2> 498 <div class="d-flex flex-column gap-2" id="SortBy_@(deviceType)_@Model.ID"> 499 @RenderSorting(deviceType) 500 </div> 501 </div> 502 } 503 @if (layout == "horizontal") { 504 505 <button class="btn @(groupsTheme) dropdown-toggle sort-button" type="button" id="SortBy_@(deviceType)_@Model.ID" data-bs-toggle="dropdown" aria-expanded="false"> 506 @Translate("Sort by") 507 <svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 32 32"><g data-name="81-Arrow Exchange"><path d="m16.71 7.29-7-7a1 1 0 0 0-1.41 0l-7 7 1.41 1.42L8 3.41V32h2V3.41l5.29 5.29zM29.29 23.29 24 28.59V0h-2v28.59l-5.29-5.29-1.41 1.41 7 7a1 1 0 0 0 1.41 0l7-7z"/></g></svg> 508 </button> 509 <div class="dropdown-menu p-3 @(groupsTheme)" aria-labelledby="SortBy_@(deviceType)_@Model.ID" style="min-width: 280px"> 510 <div class="d-flex flex-column gap-2"> 511 @RenderSorting(deviceType) 512 </div> 513 </div> 514 } 515 <button class="btn @(groupsTheme) dropdown-toggle" type="button" id="PageSize_@Model.ID" data-bs-toggle="dropdown" aria-expanded="false"> 516 @Translate("Show product per page") 517 </button> 518 <div class="dropdown-menu p-3 @(groupsTheme)" aria-labelledby="PageSize_@Model.ID" style="min-width: 280px"> 519 <div class="d-flex flex-column gap-2"> 520 @RenderChoosePageSize(pageSize) 521 </div> 522 </div> 523 </div> 524 } 525 526 527 if ((groupCount > maxGroups) && layout == "horizontal") { 528 <button type="button" class="btn @(groupsTheme)" onclick="this.closest('form').querySelectorAll('.js-facets-selector').forEach(function (selector) { selector.classList.remove('d-none'); }); this.classList.add('d-none');"><span class="icon-2">@ReadFile(iconPath + "sliders.svg")</span> @Translate("All filters")</button> 529 } 530 } 531 532 @helper RenderChoosePageSize(string pageSize ){ 533 534 //int originalPageSize = Converter.ToInt32(Dynamicweb.Context.Current.Request.QueryString.Get("OriginalPageSize")) > 0 ? Converter.ToInt32(Dynamicweb.Context.Current.Request.QueryString.Get("OriginalPageSize")) : 12; 535 536 537 <div class="form-check"> 538 <input @if (pageSize == "12") { <text> checked="checked" </text> } 539 class="form-check-input" onchange="swift.ProductList.Update(event)" type="radio" name="PageSize" value="12" id="PageSize_12_@Model.ID"> 540 <label class="form-check-label" for="PageSize_12_@Model.ID"> 541 12 542 </label> 543 </div> 544 <div class="form-check"> 545 <input @if (pageSize == "24") { <text> checked="checked" </text> } 546 class="form-check-input" onchange="swift.ProductList.Update(event)" type="radio" name="PageSize" value="24" id="PageSize_24_@Model.ID"> 547 <label class="form-check-label" for="PageSize_24_@Model.ID"> 548 24 549 </label> 550 </div> 551 <div class="form-check"> 552 <input @if (pageSize == "48") { <text> checked="checked" </text> } 553 class="form-check-input" onchange="swift.ProductList.Update(event)" type="radio" name="PageSize" value="48" id="PageSize_48_@Model.ID"> 554 <label class="form-check-label" for="PageSize_48_@Model.ID"> 555 48 556 </label> 557 </div> 558 <div class="form-check"> 559 <input @if (pageSize == "96") { <text> checked="checked" </text> } 560 class="form-check-input" onchange="swift.ProductList.Update(event)" type="radio" name="PageSize" value="96" id="PageSize_96_@Model.ID"> 561 <label class="form-check-label" for="PageSize_96_@Model.ID"> 562 96 563 </label> 564 </div> 565 } 566 567 @helper RenderSorting(string deviceType) { 568 string sortBySelection = Dynamicweb.Context.Current.Request?.Form["SortBy"] ?? ""; 569 sortBySelection = !string.IsNullOrEmpty(Dynamicweb.Context.Current.Request.QueryString.Get("SortBy")) ? Dynamicweb.Context.Current.Request.QueryString.Get("SortBy") : sortBySelection; 570 string sortNameSelectedRelevance = sortBySelection.ToLower() == "" || sortBySelection.ToLower() == "relevance" ? "checked" : ""; 571 string sortNameSelectedAZ = sortBySelection.ToLower() == "nameforsort" ? "checked" : ""; 572 string sortNameSelectedZA = sortBySelection.ToLower() == "-nameforsort" ? "checked" : ""; 573 string sortPriceLowSelected = sortBySelection.ToLower() == "price" ? "checked" : ""; 574 string sortPriceHighSelected = sortBySelection.ToLower() == "-price" ? "checked" : ""; 575 string sortNewSelected = sortBySelection.ToLower() == "-created" ? "checked" : ""; 576 string sortMostSoldSelected = sortBySelection.ToLower() == "-ordercount" ? "checked" : ""; 577 578 string sortProductNr = sortBySelection.ToLower() == "productnumbersort" ? "checked" : ""; 579 string sortProductNrZA = sortBySelection.ToLower() == "-productnumbersort" ? "checked" : ""; 580 581 string anonymousUsersLimitations = Pageview.AreaSettings.GetRawValueString("AnonymousUsers", ""); 582 bool anonymousUser = Pageview.User == null; 583 bool hidePrice = anonymousUsersLimitations.Contains("price") && anonymousUser; 584 585 if (Model.Item.GetBoolean("SortByRelevance")) 586 { 587 <div class="form-check"> 588 <input class="form-check-input" onchange="swift.ProductList.Update(event)" type="radio" name="SortBy" value="" id="SortByRelevance_@(deviceType)_@Model.ID" @sortNameSelectedRelevance> 589 <label class="form-check-label" for="SortByRelevance_@(deviceType)_@Model.ID"> 590 @Translate("Relevance") 591 </label> 592 </div> 593 } 594 if (Model.Item.GetBoolean("SortByNameAZ")) 595 { 596 <div class="form-check"> 597 <input class="form-check-input" onchange="swift.ProductList.Update(event)" type="radio" name="SortBy" value="NameForSort" id="SortByNameAZ_@(deviceType)_@Model.ID" @sortNameSelectedAZ> 598 <label class="form-check-label" for="SortByNameAZ_@(deviceType)_@Model.ID"> 599 @Translate("Name (A-Z)") 600 </label> 601 </div> 602 } 603 if (Model.Item.GetBoolean("SortByNameZA")) 604 { 605 <div class="form-check"> 606 <input class="form-check-input" onchange="swift.ProductList.Update(event)" type="radio" name="SortBy" value="-NameForSort" id="SortByNameZA_@(deviceType)_@Model.ID" @sortNameSelectedZA> 607 <label class="form-check-label" for="SortByNameZA_@(deviceType)_@Model.ID"> 608 @Translate("Name (Z-A)") 609 </label> 610 </div> 611 } 612 if (Model.Item.GetBoolean("SortByNewest")) 613 { 614 <div class="form-check"> 615 <input class="form-check-input" onchange="swift.ProductList.Update(event)" type="radio" name="SortBy" value="-created" id="SortByNew_@(deviceType)_@Model.ID" @sortNewSelected> 616 <label class="form-check-label" for="SortByNew_@(deviceType)_@Model.ID"> 617 @Translate("Newest") 618 </label> 619 </div> 620 } 621 if (!hidePrice) 622 { 623 if (Model.Item.GetBoolean("SortByLowestPrice")) 624 { 625 <div class="form-check"> 626 <input class="form-check-input" onchange="swift.ProductList.Update(event)" type="radio" name="SortBy" value="Price" id="SortByPriceLow_@(deviceType)_@Model.ID" @sortPriceLowSelected> 627 <label class="form-check-label" for="SortByPriceLow_@(deviceType)_@Model.ID"> 628 @Translate("Lowest price") 629 </label> 630 </div> 631 } 632 if (Model.Item.GetBoolean("SortByHighestPrice")) 633 { 634 <div class="form-check"> 635 <input class="form-check-input" onchange="swift.ProductList.Update(event)" type="radio" name="SortBy" value="-Price" id="SortByPriceHigh_@(deviceType)_@Model.ID" @sortPriceHighSelected> 636 <label class="form-check-label" for="SortByPriceHigh_@(deviceType)_@Model.ID"> 637 @Translate("Highest price") 638 </label> 639 </div> 640 } 641 } 642 if (Model.Item.GetBoolean("SortByMostSold")) 643 { 644 <div class="form-check"> 645 <input class="form-check-input" onchange="swift.ProductList.Update(event)" type="radio" name="SortBy" value="-OrderCount" id="SortByMostSold_@(deviceType)_@Model.ID" @sortMostSoldSelected> 646 <label class="form-check-label" for="SortByMostSold_@(deviceType)_@Model.ID"> 647 @Translate("Most sold") 648 </label> 649 </div> 650 } 651 <div class="form-check"> 652 <input class="form-check-input" onchange="swift.ProductList.Update(event)" type="radio" name="SortBy" value="ProductNumberSort" id="ProductNumberSort_@(deviceType)_@Model.ID" @sortProductNr> 653 <label class="form-check-label" for="ProductNumberSort_@(deviceType)_@Model.ID"> 654 @Translate("Product No. (Low)") 655 </label> 656 </div> 657 658 <div class="form-check"> 659 <input class="form-check-input" onchange="swift.ProductList.Update(event)" type="radio" name="SortBy" value="-ProductNumberSort" id="ProductNumberSortZA_@(deviceType)_@Model.ID" @sortProductNrZA> 660 <label class="form-check-label" for="ProductNumberSortZA_@(deviceType)_@Model.ID"> 661 @Translate("Product No. (High)") 662 </label> 663 </div> 664 } 665 666 @helper RenderCheckboxOption(FacetViewModel facet, FacetOptionViewModel facetOption) 667 { 668 string facetLabel = HtmlEncoder.HtmlEncode(facetOption.Label); 669 string disabled = facetOption.Count <= 0 ? "disabled" : ""; 670 string selected = facetOption.Selected ? "checked" : ""; 671 672 if (facetLabel.ToLower() == "true") 673 { 674 facetLabel = Translate("Yes"); 675 } 676 677 if (facetLabel.ToLower() == "false") 678 { 679 facetLabel = Translate("No"); 680 } 681 682 <label class="form-check mt-1" @disabled> 683 <input type="checkbox" onclick="swift.ProductList.Update(event)" class="form-check-input" name="@facet.QueryParameter" value="[@facetOption.Value]" data-filter-value="@facetLabel" @selected> 684 <span class="form-check-label d-flex align-items-center"> 685 <span class="flex-fill">@Translate(facetLabel) </span> 686 @if (facet.FacetType.ToLower() == "field") { 687 <small class="opacity-85">@facetOption.Count</small> 688 } 689 </span> 690 </label> 691 } 692 693 @helper RenderColorOption(FacetViewModel facet, FacetOptionViewModel facetOption) 694 { 695 string facetLabel = HtmlEncoder.HtmlEncode(facetOption.Label); 696 string disabled = facetOption.Count <= 0 ? "disabled" : ""; 697 string selected = facetOption.Selected ? "checked" : ""; 698 699 string image = facetOption.Value; 700 string colorCode = facetOption.Value; 701 702 var variantOption = Dynamicweb.Ecommerce.Services.VariantOptions.GetVariantOption(facetOption.Value.ToString(), Dynamicweb.Ecommerce.Common.Context.LanguageID); 703 if (variantOption != null) 704 { 705 image = variantOption.LargeImage; 706 colorCode = variantOption.Color; 707 } 708 709 <div class="colorbox"> 710 <label> 711 <input type="checkbox" onclick="swift.ProductList.Update(event)" class="@disabled @selected" name="@facet.QueryParameter" value="[@facetOption.Value]" data-filter-value="@facetLabel" @selected title="@facetOption.Label"> 712 @if (colorCode.Contains("#")) 713 { 714 <span class="colorbox-background" style="background-color: @colorCode"></span> 715 <span class="visually-hidden">@Translate(facetOption.Label)</span> 716 } 717 else 718 { 719 <img class="colorbox-background" src="/Admin/Public/GetImage.ashx?width=25&height=25&image=@image"> 720 <span class="visually-hidden">@Translate(facetOption.Label)</span> 721 } 722 </label> 723 </div> 724 } 725 726
Error executing template "Designs/Swift/Paragraph/Swift_ProductListFacets.cshtml"
System.NullReferenceException: Object reference not set to an instance of an object.
   at CompiledRazorTemplates.Dynamic.RazorEngine_b5776fe0eeed45b7b0b0fba763b2bb33.<>c__DisplayClass0_0.<RenderForm>b__0(TextWriter __razor_helper_writer) in D:\dynamicweb.net\Solutions\FlexMedia\siso2021.cloud.dynamicweb-cms.com\files\Templates\Designs\Swift\Paragraph\Swift_ProductListFacets.cshtml:line 300
   at CompiledRazorTemplates.Dynamic.RazorEngine_b5776fe0eeed45b7b0b0fba763b2bb33.Execute() in D:\dynamicweb.net\Solutions\FlexMedia\siso2021.cloud.dynamicweb-cms.com\files\Templates\Designs\Swift\Paragraph\Swift_ProductListFacets.cshtml:line 175
   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.Frontend.Navigation 4 @using Dynamicweb.Environment 5 @using Dynamicweb.Core.Encoders 6 @using System.Web 7 @using Dynamicweb.Core 8 @using System.Linq 9 10 @{ 11 ProductListViewModel productList = new ProductListViewModel(); 12 13 if (Dynamicweb.Context.Current.Items.Contains("ProductList")) 14 { 15 productList = (ProductListViewModel)Dynamicweb.Context.Current.Items["ProductList"]; 16 } 17 18 string url = Pageview.SearchFriendlyUrl; 19 20 21 url = url.LastIndexOf("?") != -1 ? url.Substring(0, url.LastIndexOf("?")) : url; 22 23 24 25 //Fix for non-friendly urls 26 if (Dynamicweb.Context.Current.Request.QueryString.Get("GroupID") != null) 27 { 28 string groupId = Dynamicweb.Context.Current.Request.QueryString.Get("GroupID"); 29 url += "?GroupID=" + groupId; 30 31 32 } 33 34 35 if (!url.Contains("LayoutTemplate")) 36 { 37 url += url.Contains("?") ? "&LayoutTemplate=Designs/Swift/Swift_PageClean.cshtml" : "?LayoutTemplate=Designs/Swift/Swift_PageClean.cshtml"; 38 } 39 40 bool facetsFound = false; 41 int selectedFacetsCount = 0; 42 43 44 45 if (productList.FacetGroups != null) 46 { 47 foreach (FacetGroupViewModel facetGroup in productList.FacetGroups) 48 { 49 foreach (FacetViewModel facet in facetGroup.Facets) 50 { 51 if (facet.Options.Count() > 0) 52 { 53 facetsFound = true; 54 55 foreach (FacetOptionViewModel option in facet.Options) 56 { 57 if (option.Selected) 58 { 59 selectedFacetsCount++; 60 } 61 } 62 } 63 } 64 } 65 } 66 string contentPadding = Model.Item.GetRawValueString("ContentPadding", ""); 67 contentPadding = Model.Item.GetRawValueString("ContentPadding", "") == "none" ? " px-0 py-2" : contentPadding; 68 contentPadding = Model.Item.GetRawValueString("ContentPadding", "") == "small" ? " px-3 py-2" : contentPadding; 69 70 bool enableSorting = Model.Item.GetBoolean("SortByNameAZ"); 71 enableSorting = Model.Item.GetBoolean("SortByNameZA") || enableSorting == true ? true : false; 72 enableSorting = Model.Item.GetBoolean("SortByNewest") || enableSorting == true ? true : false; 73 enableSorting = Model.Item.GetBoolean("SortByLowestPrice") || enableSorting == true ? true : false; 74 enableSorting = Model.Item.GetBoolean("SortByHighestPrice") || enableSorting == true ? true : false; 75 76 string layout = Model.Item.GetRawValueString("Layout", "vertical"); 77 78 79 80 } 81 82 83 84 @if (productList.TotalProductsCount > 0 && (facetsFound || Model.Item.GetBoolean("EnableGroupNavigation") || enableSorting)) 85 { 86 string theme = !string.IsNullOrWhiteSpace(Model.Item.GetRawValueString("Theme")) ? " theme " + Model.Item.GetRawValueString("Theme").Replace(" ", "").Trim().ToLower() : ""; 87 string modalTheme = !string.IsNullOrWhiteSpace(Model.Item.GetRawValueString("ModalTheme")) ? " theme " + Model.Item.GetRawValueString("ModalTheme").Replace(" ", "").Trim().ToLower() : ""; 88 string iconPath = "/Files/Templates/Designs/Swift/Assets/icons/"; 89 string selectedFacetsLabel = selectedFacetsCount > 0 ? "(" + selectedFacetsCount + ")" : ""; 90 91 //Desktop 92 if (layout == "vertical") { 93 <form method="post" action="@url" data-response-target-element="content" id="FacetsForm_Desktop_@Model.ID" class="d-none d-lg-block h-100 @theme item_@Model.Item.SystemName.ToLower()"> 94 @RenderForm(productList, "desktop", enableSorting, layout) 95 </form> 96 97 <script> 98 99 function lastOpened (e){ 100 101 102 if (e.classList.contains('collapsed')){ 103 setCookie("LastOpenedFacet", 0, 0); 104 } else { 105 setCookie("LastOpenedFacet", e.innerText, 10); 106 } 107 108 109 } 110 111 function setCookie(name, value, maxAgeSeconds) { 112 var maxAgeSegment = "; max-age=" + maxAgeSeconds; 113 document.cookie = encodeURI(name) + "=" + encodeURI(value) + maxAgeSegment; 114 } 115 116 window.onscroll = function() {fixedFacets(facetsTopPosOriginal)}; 117 118 let facetsTopPosOriginal = document.getElementById("FacetsForm_Desktop_@Model.ID").getBoundingClientRect().top; 119 120 121 122 function fixedFacets(facetsTopPosOriginal){ 123 124 let scrollPosition = window.pageYOffset; 125 126 let headerBottomPos = document.getElementsByClassName("page-header")[0].getBoundingClientRect().bottom; 127 let footerTopPos = document.getElementsByClassName("page-footer")[0].getBoundingClientRect().top; 128 129 let facetsTop = document.getElementById("FacetsForm_Desktop_@Model.ID"); 130 let facetsTopPos = facetsTop.getBoundingClientRect().top; 131 let facetsBottomPos = facetsTop.getBoundingClientRect().bottom; 132 let facetsTopParent = facetsTop.parentElement; 133 134 let horizontalFacets; 135 let horizontalFacetsParent; 136 137 if (document.getElementsByClassName("sticky-facets-horizontal").length > 0 ){ 138 139 horizontalFacets = document.getElementsByClassName("sticky-facets-horizontal")[0]; 140 horizontalFacetsParent = document.getElementsByClassName("sticky-facets-horizontal")[0].parentElement; 141 142 } else { 143 144 horizontalFacets = document.getElementsByClassName("sticky-facets-horizontal-mobile")[0].parentElement; 145 horizontalFacetsParent = horizontalFacets.parentElement; 146 147 horizontalFacets.classList.add("sticky-mobile"); 148 149 } 150 151 152 if (facetsTopPosOriginal < scrollPosition + headerBottomPos ) { 153 facetsTop.classList.add("sticky"); 154 facetsTop.style.cssText = '--bs-columns:12; --sticky-top:' + headerBottomPos + 'px; width:' + facetsTopParent.offsetWidth + 'px'; 155 156 horizontalFacets.classList.add("sticky"); 157 horizontalFacets.style.cssText = '--sticky-top:' + headerBottomPos + 'px; width:' + horizontalFacetsParent.offsetWidth + 'px'; 158 159 160 } else { 161 facetsTop.classList.remove("sticky"); 162 horizontalFacets.classList.remove("sticky"); 163 } 164 } 165 166 </script> 167 168 } 169 if (layout == "horizontal") { 170 contentPadding = Model.Item.GetRawValueString("ContentPadding", "") == "small" ? " p-3" : contentPadding; 171 172 173 <div class="@theme @contentPadding h-100"> 174 <form method="post" action="@url" data-response-target-element="content" id="FacetsForm_Desktop_@Model.ID" class="d-none d-lg-flex gap-3 flex-row flex-wrap item_@Model.Item.SystemName.ToLower()"> 175 @RenderForm(productList, "desktop", enableSorting, layout) 176 177 @if (selectedFacetsCount > 0) { 178 <button type="button" class="btn btn-sm me-sm-1 me-lg-2" onclick="swift.ProductList.ResetFacets(event)"><span class="icon-2">@ReadFile(iconPath + "rotate-ccw.svg")</span> @Translate("Clear filters")</button> 179 } 180 </form> 181 </div> 182 } 183 184 bool showFiltersForThisGroup = false; 185 186 string groupId = !string.IsNullOrEmpty(Dynamicweb.Context.Current.Request.QueryString.Get("GroupID")) ? Dynamicweb.Context.Current.Request.QueryString.Get("GroupID") : ""; 187 188 189 if (!string.IsNullOrEmpty(groupId)){ 190 191 var group = Dynamicweb.Ecommerce.Services.ProductGroups.GetGroup(groupId); 192 193 194 foreach (var customfield in group.ProductGroupFieldValues) { 195 if (customfield.ProductGroupField.SystemName == "ShowProductFilters"){ 196 if (customfield.Value.ToString() == "True"){ 197 showFiltersForThisGroup = true; 198 } 199 } 200 201 } 202 } 203 204 if (showFiltersForThisGroup){ 205 206 207 //Mobile 208 <div class="d-block d-lg-none mt-lg-0 @(contentPadding)@(theme) sticky-facets-horizontal-mobile FacetsForm_Mobile_@Model.Item.SystemName.ToLower()_@Model.ID"> 209 210 211 212 <button type="button" class="btn btn-primary w-100" data-bs-toggle="modal" data-bs-target="#FacetsModal"> 213 <span class="d-flex align-items-center"> 214 <span class="flex-grow-1 text-start"> 215 @Translate("Filter") @selectedFacetsLabel 216 </span> 217 <span class="icon-2"> 218 @ReadFile(iconPath + "sliders.svg") 219 </span> 220 </span> 221 </button> 222 223 <form method="post" action="@url" data-response-target-element="content" class="modal" id="FacetsModal" tabindex="-1" aria-hidden="false"> 224 <div class="modal-dialog modal-fullscreen"> 225 <div class="modal-content"> 226 227 <div class="modal-header@(modalTheme)"> 228 <h5 class="modal-title">@Translate("Filters and sorting")</h5> 229 <button type="button" class="btn-close" data-bs-dismiss="modal" aria-label="Close" onclick="document.querySelector('body').style = ''"></button> 230 </div> 231 <div class="modal-body@(modalTheme)"> 232 @RenderForm(productList, "mobile", enableSorting) 233 </div> 234 <div class="modal-footer d-flex@(modalTheme)"> 235 @if (selectedFacetsCount != 0) 236 { 237 <button type="button" class="btn btn-secondary flex-fill" onclick="swift.ProductList.ResetFacets(event)">@Translate("Clear") (@selectedFacetsCount)</button> 238 } 239 <button type="button" class="btn btn-primary flex-fill" onclick="location.reload();">@Translate("Update")</button> 240 </div> 241 </div> 242 </div> 243 </form> 244 </div> 245 246 } 247 } 248 else 249 { 250 if (Pageview.IsVisualEditorMode) 251 { 252 <div class="alert alert-dark m-0" role="alert"> 253 <span>@Translate("Facets: The facets selectors will be shown here, if any")</span> 254 </div> 255 } 256 else if (productList.TotalProductsCount > 0) 257 { 258 @*<div class="alert alert-dark m-0" id="NoFiltersAlert_@Model.ID"> 259 @Translate("No filters are available") 260 </div>*@ 261 262 } 263 } 264 265 266 @helper RenderForm(ProductListViewModel productList, string deviceType, bool enableSorting, string layout = "vertical") 267 { 268 string groupId = !string.IsNullOrEmpty(Dynamicweb.Context.Current.Request.QueryString.Get("GroupID")) ? Dynamicweb.Context.Current.Request.QueryString.Get("GroupID") : ""; 269 270 string iconPath = "/Files/Templates/Designs/Swift/Assets/icons/"; 271 string pageSize = !string.IsNullOrEmpty(Dynamicweb.Context.Current.Request.QueryString.Get("PageSize")) ? Dynamicweb.Context.Current.Request.QueryString.Get("PageSize") : productList.PageSize.ToString(); 272 273 string searchQuery = !string.IsNullOrEmpty(Dynamicweb.Context.Current.Request.QueryString.Get("q")) ? Dynamicweb.Context.Current.Request.QueryString.Get("q") : ""; 274 string searchLayout = !string.IsNullOrEmpty(Dynamicweb.Context.Current.Request.QueryString.Get("SearchLayout")) ? Dynamicweb.Context.Current.Request.QueryString.Get("SearchLayout") : ""; 275 276 string groupsTheme = ""; 277 string extraBottomMargin = ""; 278 if (deviceType != "mobile") 279 { 280 groupsTheme = !string.IsNullOrWhiteSpace(Model.Item.GetRawValueString("FacetGroupsTheme")) ? " theme " + Model.Item.GetRawValueString("FacetGroupsTheme").Replace(" ", "").Trim().ToLower() : ""; 281 extraBottomMargin = !string.IsNullOrEmpty(groupsTheme) ? "mb-3" : ""; 282 } 283 284 string contentPadding = Model.Item.GetRawValueString("ContentPadding", ""); 285 contentPadding = contentPadding == "none" ? " px-0 py-2" : contentPadding; 286 contentPadding = contentPadding == "small" ? " px-3 py-2" : contentPadding; 287 288 bool showFiltersForThisGroup = false; 289 290 291 if (!string.IsNullOrEmpty(groupId)){ 292 293 var group = Dynamicweb.Ecommerce.Services.ProductGroups.GetGroup(groupId); 294 295 @*if (group.Id == "14.01"){ 296 showFiltersForThisGroup = true; 297 }*@ 298 299 300 foreach (var customfield in group.ProductGroupFieldValues) { 301 if (customfield.ProductGroupField.SystemName == "ShowProductFilters"){ 302 if (customfield.Value.ToString() == "True"){ 303 showFiltersForThisGroup = true; 304 } 305 } 306 307 } 308 309 310 @* if (group.ParentGroups.Count() > 0){ 311 foreach (var parentGroups in group.ParentGroups){ 312 if (parentGroups.Id == "14.01"){ 313 showFiltersForThisGroup = true; 314 } 315 if (parentGroups.Id == "14.02"){ 316 showFiltersForThisGroup = true; 317 } 318 if (parentGroups.Id == "14.03"){ 319 showFiltersForThisGroup = true; 320 } 321 322 if (parentGroups.ParentGroups.Count() > 0){ 323 foreach (var parentParentGroups in parentGroups.ParentGroups){ 324 325 if (parentParentGroups.Id == "14.01"){ 326 showFiltersForThisGroup = true; 327 } 328 329 } 330 } 331 332 } 333 } *@ 334 } 335 336 337 338 339 340 341 @*<input type="hidden" name="PageSize" value="@pageSize">*@ 342 343 344 if (!string.IsNullOrEmpty(searchQuery)) { 345 <input type="hidden" name="q" value="@searchQuery"> 346 <input type="hidden" name="SearchLayout" value="@searchLayout"> 347 } 348 349 350 if (Model.Item.GetBoolean("EnableGroupNavigation")) 351 { 352 int startLevel = Convert.ToInt32(Model.Item.GetRawValueString("GroupNavigationStartLevel", "2")); 353 int stopLevel = Convert.ToInt32(Model.Item.GetRawValueString("GroupNavigationStopLevel", "9")); 354 355 var navigationSettings = new NavigationSettings(); 356 navigationSettings.StartLevel = startLevel; 357 navigationSettings.StopLevel = stopLevel; 358 navigationSettings.Parameters.Add("ID", deviceType); 359 navigationSettings.Parameters.Add("HideTexts", false); 360 navigationSettings.Parameters.Add("HideIcons", true); 361 navigationSettings.Parameters.Add("ContentPadding", contentPadding); 362 navigationSettings.ExpandMode = ExpandMode.All; 363 364 if (layout == "vertical") { 365 <div class="border-bottom py-2@(@groupsTheme)"> 366 <div class="d-flex@(contentPadding)" data-bs-toggle="collapse" data-bs-target="#ProductGroupNavigation_@(deviceType)_@Model.ID" role="button" aria-expanded="true" aria-controls="ProductGroupNavigation_@(deviceType)_@Model.ID"> 367 <h2 class="opacity-85 m-0 flex-fill h6">@Translate("Navigation")</h2> 368 <div class="my-auto collapse-chevron-icon"></div> 369 </div> 370 <div class="collapse show" id="ProductGroupNavigation_@(deviceType)_@Model.ID"> 371 @Navigation.RenderNavigation("Navigation/Vertical.cshtml", navigationSettings) 372 </div> 373 </div> 374 } 375 376 } 377 378 379 int groupCount = 0; 380 int maxGroups = 999; 381 int totalGroups = productList?.FacetGroups != null ? productList.FacetGroups.Count() : 0; 382 383 var lastOpenedFacetCookie = HttpContext.Current.Request.Cookies["LastOpenedFacet"]; 384 385 386 if (productList.FacetGroups != null && showFiltersForThisGroup) { 387 <div class="facets-options"> 388 @if (showFiltersForThisGroup){ 389 foreach (FacetGroupViewModel facetGroup in productList.FacetGroups) 390 { 391 string border = groupCount != totalGroups ? "border-bottom" : ""; 392 393 foreach (FacetViewModel facet in facetGroup.Facets) 394 { 395 string collapseClass = string.Empty; 396 string showClass = " show"; 397 string ariaExpanded = "true"; 398 var expandedFacetGroups = Model.Item.GetRawValueString("ExpandFacetGroups", "all"); 399 400 401 if (expandedFacetGroups != "all" && System.Text.RegularExpressions.Regex.IsMatch(expandedFacetGroups, "([0-9])")) 402 { 403 if (groupCount >= Dynamicweb.Core.Converter.ToInt32(expandedFacetGroups)) 404 { 405 collapseClass = " collapsed"; 406 showClass = string.Empty; 407 ariaExpanded = "false"; 408 } 409 410 } 411 412 if(lastOpenedFacetCookie != null){ 413 if (Translate(facet.Name) == lastOpenedFacetCookie.Value.Replace("%20", " ")){ 414 collapseClass = string.Empty; 415 showClass = " show"; 416 ariaExpanded = "true"; 417 } 418 419 } 420 421 if (facet.Options.Count() > 0) 422 { 423 if (layout == "vertical") { 424 <div class="@border@(contentPadding)@(@groupsTheme)"> 425 <div class="d-flex@(collapseClass)" data-bs-toggle="collapse" data-bs-target="#FacetGroup_@facet.Name.Replace(" ", "").Replace(".", "")_@(deviceType)_@Model.ID" role="button" aria-expanded="@ariaExpanded" aria-controls="FacetGroup_@facet.Name.Replace(" ", "").Replace(".", "")_@(deviceType)_@Model.ID" onclick="lastOpened(this)"> 426 <h2 class="opacity-85 m-0 flex-fill h6 my-2">@Translate(facet.Name)</h2> 427 <div class="my-auto collapse-chevron-icon"></div> 428 </div> 429 <div class="collapse@(showClass)" id="FacetGroup_@facet.Name.Replace(" ", "").Replace(".", "")_@(deviceType)_@Model.ID"> 430 @foreach (FacetOptionViewModel facetOption in facet.Options) 431 { 432 string renderType = facet.RenderType; 433 434 if (renderType == "Colors") 435 { 436 @RenderColorOption(facet, facetOption) 437 } 438 else 439 { 440 @RenderCheckboxOption(facet, facetOption) 441 } 442 } 443 </div> 444 </div> 445 } 446 if (layout == "horizontal") { 447 string hideSelector = groupCount < maxGroups ? "" : "d-none"; 448 int selectedFacetsInGroup = 0; 449 450 foreach (FacetOptionViewModel option in facet.Options) 451 { 452 if (option.Selected) 453 { 454 selectedFacetsInGroup++; 455 } 456 } 457 458 string label = selectedFacetsInGroup > 0 ? @Translate(facet.Name) + "<span class=\"badge bg-dark opacity-50 text-white ms-2\">" + selectedFacetsInGroup + "</span>" : @Translate(facet.Name); 459 460 <div class="dropdown @hideSelector js-facets-selector"> 461 <button class="btn @(groupsTheme) dropdown-toggle" type="button" id="FacetGroup_@facet.Name.Replace(" ", "")_@(deviceType)_@Model.ID" data-bs-toggle="dropdown" aria-expanded="false"> 462 @label 463 </button> 464 <div class="dropdown-menu p-3 @(groupsTheme)" aria-labelledby="FacetGroup_@facet.Name.Replace(" ", "")_@(deviceType)_@Model.ID" style="min-width: 280px"> 465 @foreach (FacetOptionViewModel facetOption in facet.Options) 466 { 467 string translation = Translate(facetOption?.Value.ToString()); // 468 string renderType = facet.RenderType; 469 470 if (renderType == "Colors") 471 { 472 @RenderColorOption(facet, facetOption) 473 } 474 else 475 { 476 @RenderCheckboxOption(facet, facetOption) 477 } 478 } 479 </div> 480 </div> 481 } 482 483 groupCount++; 484 } 485 } 486 } 487 } 488 489 </div> 490 } 491 492 if (enableSorting) 493 { 494 <div class="right"> 495 @if (layout == "vertical") { 496 <div class="border-bottom@(contentPadding)@(groupsTheme)"> 497 <h2 class="opacity-85 m-0 my-2 flex-fill h6">@Translate("Sort by")</h2> 498 <div class="d-flex flex-column gap-2" id="SortBy_@(deviceType)_@Model.ID"> 499 @RenderSorting(deviceType) 500 </div> 501 </div> 502 } 503 @if (layout == "horizontal") { 504 505 <button class="btn @(groupsTheme) dropdown-toggle sort-button" type="button" id="SortBy_@(deviceType)_@Model.ID" data-bs-toggle="dropdown" aria-expanded="false"> 506 @Translate("Sort by") 507 <svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 32 32"><g data-name="81-Arrow Exchange"><path d="m16.71 7.29-7-7a1 1 0 0 0-1.41 0l-7 7 1.41 1.42L8 3.41V32h2V3.41l5.29 5.29zM29.29 23.29 24 28.59V0h-2v28.59l-5.29-5.29-1.41 1.41 7 7a1 1 0 0 0 1.41 0l7-7z"/></g></svg> 508 </button> 509 <div class="dropdown-menu p-3 @(groupsTheme)" aria-labelledby="SortBy_@(deviceType)_@Model.ID" style="min-width: 280px"> 510 <div class="d-flex flex-column gap-2"> 511 @RenderSorting(deviceType) 512 </div> 513 </div> 514 } 515 <button class="btn @(groupsTheme) dropdown-toggle" type="button" id="PageSize_@Model.ID" data-bs-toggle="dropdown" aria-expanded="false"> 516 @Translate("Show product per page") 517 </button> 518 <div class="dropdown-menu p-3 @(groupsTheme)" aria-labelledby="PageSize_@Model.ID" style="min-width: 280px"> 519 <div class="d-flex flex-column gap-2"> 520 @RenderChoosePageSize(pageSize) 521 </div> 522 </div> 523 </div> 524 } 525 526 527 if ((groupCount > maxGroups) && layout == "horizontal") { 528 <button type="button" class="btn @(groupsTheme)" onclick="this.closest('form').querySelectorAll('.js-facets-selector').forEach(function (selector) { selector.classList.remove('d-none'); }); this.classList.add('d-none');"><span class="icon-2">@ReadFile(iconPath + "sliders.svg")</span> @Translate("All filters")</button> 529 } 530 } 531 532 @helper RenderChoosePageSize(string pageSize ){ 533 534 //int originalPageSize = Converter.ToInt32(Dynamicweb.Context.Current.Request.QueryString.Get("OriginalPageSize")) > 0 ? Converter.ToInt32(Dynamicweb.Context.Current.Request.QueryString.Get("OriginalPageSize")) : 12; 535 536 537 <div class="form-check"> 538 <input @if (pageSize == "12") { <text> checked="checked" </text> } 539 class="form-check-input" onchange="swift.ProductList.Update(event)" type="radio" name="PageSize" value="12" id="PageSize_12_@Model.ID"> 540 <label class="form-check-label" for="PageSize_12_@Model.ID"> 541 12 542 </label> 543 </div> 544 <div class="form-check"> 545 <input @if (pageSize == "24") { <text> checked="checked" </text> } 546 class="form-check-input" onchange="swift.ProductList.Update(event)" type="radio" name="PageSize" value="24" id="PageSize_24_@Model.ID"> 547 <label class="form-check-label" for="PageSize_24_@Model.ID"> 548 24 549 </label> 550 </div> 551 <div class="form-check"> 552 <input @if (pageSize == "48") { <text> checked="checked" </text> } 553 class="form-check-input" onchange="swift.ProductList.Update(event)" type="radio" name="PageSize" value="48" id="PageSize_48_@Model.ID"> 554 <label class="form-check-label" for="PageSize_48_@Model.ID"> 555 48 556 </label> 557 </div> 558 <div class="form-check"> 559 <input @if (pageSize == "96") { <text> checked="checked" </text> } 560 class="form-check-input" onchange="swift.ProductList.Update(event)" type="radio" name="PageSize" value="96" id="PageSize_96_@Model.ID"> 561 <label class="form-check-label" for="PageSize_96_@Model.ID"> 562 96 563 </label> 564 </div> 565 } 566 567 @helper RenderSorting(string deviceType) { 568 string sortBySelection = Dynamicweb.Context.Current.Request?.Form["SortBy"] ?? ""; 569 sortBySelection = !string.IsNullOrEmpty(Dynamicweb.Context.Current.Request.QueryString.Get("SortBy")) ? Dynamicweb.Context.Current.Request.QueryString.Get("SortBy") : sortBySelection; 570 string sortNameSelectedRelevance = sortBySelection.ToLower() == "" || sortBySelection.ToLower() == "relevance" ? "checked" : ""; 571 string sortNameSelectedAZ = sortBySelection.ToLower() == "nameforsort" ? "checked" : ""; 572 string sortNameSelectedZA = sortBySelection.ToLower() == "-nameforsort" ? "checked" : ""; 573 string sortPriceLowSelected = sortBySelection.ToLower() == "price" ? "checked" : ""; 574 string sortPriceHighSelected = sortBySelection.ToLower() == "-price" ? "checked" : ""; 575 string sortNewSelected = sortBySelection.ToLower() == "-created" ? "checked" : ""; 576 string sortMostSoldSelected = sortBySelection.ToLower() == "-ordercount" ? "checked" : ""; 577 578 string sortProductNr = sortBySelection.ToLower() == "productnumbersort" ? "checked" : ""; 579 string sortProductNrZA = sortBySelection.ToLower() == "-productnumbersort" ? "checked" : ""; 580 581 string anonymousUsersLimitations = Pageview.AreaSettings.GetRawValueString("AnonymousUsers", ""); 582 bool anonymousUser = Pageview.User == null; 583 bool hidePrice = anonymousUsersLimitations.Contains("price") && anonymousUser; 584 585 if (Model.Item.GetBoolean("SortByRelevance")) 586 { 587 <div class="form-check"> 588 <input class="form-check-input" onchange="swift.ProductList.Update(event)" type="radio" name="SortBy" value="" id="SortByRelevance_@(deviceType)_@Model.ID" @sortNameSelectedRelevance> 589 <label class="form-check-label" for="SortByRelevance_@(deviceType)_@Model.ID"> 590 @Translate("Relevance") 591 </label> 592 </div> 593 } 594 if (Model.Item.GetBoolean("SortByNameAZ")) 595 { 596 <div class="form-check"> 597 <input class="form-check-input" onchange="swift.ProductList.Update(event)" type="radio" name="SortBy" value="NameForSort" id="SortByNameAZ_@(deviceType)_@Model.ID" @sortNameSelectedAZ> 598 <label class="form-check-label" for="SortByNameAZ_@(deviceType)_@Model.ID"> 599 @Translate("Name (A-Z)") 600 </label> 601 </div> 602 } 603 if (Model.Item.GetBoolean("SortByNameZA")) 604 { 605 <div class="form-check"> 606 <input class="form-check-input" onchange="swift.ProductList.Update(event)" type="radio" name="SortBy" value="-NameForSort" id="SortByNameZA_@(deviceType)_@Model.ID" @sortNameSelectedZA> 607 <label class="form-check-label" for="SortByNameZA_@(deviceType)_@Model.ID"> 608 @Translate("Name (Z-A)") 609 </label> 610 </div> 611 } 612 if (Model.Item.GetBoolean("SortByNewest")) 613 { 614 <div class="form-check"> 615 <input class="form-check-input" onchange="swift.ProductList.Update(event)" type="radio" name="SortBy" value="-created" id="SortByNew_@(deviceType)_@Model.ID" @sortNewSelected> 616 <label class="form-check-label" for="SortByNew_@(deviceType)_@Model.ID"> 617 @Translate("Newest") 618 </label> 619 </div> 620 } 621 if (!hidePrice) 622 { 623 if (Model.Item.GetBoolean("SortByLowestPrice")) 624 { 625 <div class="form-check"> 626 <input class="form-check-input" onchange="swift.ProductList.Update(event)" type="radio" name="SortBy" value="Price" id="SortByPriceLow_@(deviceType)_@Model.ID" @sortPriceLowSelected> 627 <label class="form-check-label" for="SortByPriceLow_@(deviceType)_@Model.ID"> 628 @Translate("Lowest price") 629 </label> 630 </div> 631 } 632 if (Model.Item.GetBoolean("SortByHighestPrice")) 633 { 634 <div class="form-check"> 635 <input class="form-check-input" onchange="swift.ProductList.Update(event)" type="radio" name="SortBy" value="-Price" id="SortByPriceHigh_@(deviceType)_@Model.ID" @sortPriceHighSelected> 636 <label class="form-check-label" for="SortByPriceHigh_@(deviceType)_@Model.ID"> 637 @Translate("Highest price") 638 </label> 639 </div> 640 } 641 } 642 if (Model.Item.GetBoolean("SortByMostSold")) 643 { 644 <div class="form-check"> 645 <input class="form-check-input" onchange="swift.ProductList.Update(event)" type="radio" name="SortBy" value="-OrderCount" id="SortByMostSold_@(deviceType)_@Model.ID" @sortMostSoldSelected> 646 <label class="form-check-label" for="SortByMostSold_@(deviceType)_@Model.ID"> 647 @Translate("Most sold") 648 </label> 649 </div> 650 } 651 <div class="form-check"> 652 <input class="form-check-input" onchange="swift.ProductList.Update(event)" type="radio" name="SortBy" value="ProductNumberSort" id="ProductNumberSort_@(deviceType)_@Model.ID" @sortProductNr> 653 <label class="form-check-label" for="ProductNumberSort_@(deviceType)_@Model.ID"> 654 @Translate("Product No. (Low)") 655 </label> 656 </div> 657 658 <div class="form-check"> 659 <input class="form-check-input" onchange="swift.ProductList.Update(event)" type="radio" name="SortBy" value="-ProductNumberSort" id="ProductNumberSortZA_@(deviceType)_@Model.ID" @sortProductNrZA> 660 <label class="form-check-label" for="ProductNumberSortZA_@(deviceType)_@Model.ID"> 661 @Translate("Product No. (High)") 662 </label> 663 </div> 664 } 665 666 @helper RenderCheckboxOption(FacetViewModel facet, FacetOptionViewModel facetOption) 667 { 668 string facetLabel = HtmlEncoder.HtmlEncode(facetOption.Label); 669 string disabled = facetOption.Count <= 0 ? "disabled" : ""; 670 string selected = facetOption.Selected ? "checked" : ""; 671 672 if (facetLabel.ToLower() == "true") 673 { 674 facetLabel = Translate("Yes"); 675 } 676 677 if (facetLabel.ToLower() == "false") 678 { 679 facetLabel = Translate("No"); 680 } 681 682 <label class="form-check mt-1" @disabled> 683 <input type="checkbox" onclick="swift.ProductList.Update(event)" class="form-check-input" name="@facet.QueryParameter" value="[@facetOption.Value]" data-filter-value="@facetLabel" @selected> 684 <span class="form-check-label d-flex align-items-center"> 685 <span class="flex-fill">@Translate(facetLabel) </span> 686 @if (facet.FacetType.ToLower() == "field") { 687 <small class="opacity-85">@facetOption.Count</small> 688 } 689 </span> 690 </label> 691 } 692 693 @helper RenderColorOption(FacetViewModel facet, FacetOptionViewModel facetOption) 694 { 695 string facetLabel = HtmlEncoder.HtmlEncode(facetOption.Label); 696 string disabled = facetOption.Count <= 0 ? "disabled" : ""; 697 string selected = facetOption.Selected ? "checked" : ""; 698 699 string image = facetOption.Value; 700 string colorCode = facetOption.Value; 701 702 var variantOption = Dynamicweb.Ecommerce.Services.VariantOptions.GetVariantOption(facetOption.Value.ToString(), Dynamicweb.Ecommerce.Common.Context.LanguageID); 703 if (variantOption != null) 704 { 705 image = variantOption.LargeImage; 706 colorCode = variantOption.Color; 707 } 708 709 <div class="colorbox"> 710 <label> 711 <input type="checkbox" onclick="swift.ProductList.Update(event)" class="@disabled @selected" name="@facet.QueryParameter" value="[@facetOption.Value]" data-filter-value="@facetLabel" @selected title="@facetOption.Label"> 712 @if (colorCode.Contains("#")) 713 { 714 <span class="colorbox-background" style="background-color: @colorCode"></span> 715 <span class="visually-hidden">@Translate(facetOption.Label)</span> 716 } 717 else 718 { 719 <img class="colorbox-background" src="/Admin/Public/GetImage.ashx?width=25&height=25&image=@image"> 720 <span class="visually-hidden">@Translate(facetOption.Label)</span> 721 } 722 </label> 723 </div> 724 } 725 726
12 out of 350 products
< 1 2 ... 29 30 >