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_76284208c87d4164b54fe2824338f5ae.<>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 303
   at CompiledRazorTemplates.Dynamic.RazorEngine_76284208c87d4164b54fe2824338f5ae.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 horizontalFacetsParent.style.setProperty('--sticky-top', headerBottomPos + 'px'); 159 horizontalFacets.style.cssText = 'width:' + horizontalFacetsParent.offsetWidth + 'px'; 160 161 162 } else { 163 facetsTop.classList.remove("sticky"); 164 horizontalFacets.classList.remove("sticky"); 165 } 166 } 167 168 </script> 169 170 } 171 if (layout == "horizontal") { 172 contentPadding = Model.Item.GetRawValueString("ContentPadding", "") == "small" ? " p-3" : contentPadding; 173 174 175 <div class="@theme @contentPadding h-100"> 176 <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()"> 177 @RenderForm(productList, "desktop", enableSorting, layout) 178 179 @if (selectedFacetsCount > 0) { 180 <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> 181 } 182 </form> 183 </div> 184 } 185 186 bool showFiltersForThisGroup = false; 187 188 string groupId = !string.IsNullOrEmpty(Dynamicweb.Context.Current.Request.QueryString.Get("GroupID")) ? Dynamicweb.Context.Current.Request.QueryString.Get("GroupID") : ""; 189 190 191 if (!string.IsNullOrEmpty(groupId)){ 192 193 var group = Dynamicweb.Ecommerce.Services.ProductGroups.GetGroup(groupId); 194 195 196 foreach (var customfield in group.ProductGroupFieldValues) { 197 if (customfield.ProductGroupField.SystemName == "ShowProductFilters"){ 198 if (customfield.Value.ToString() == "True"){ 199 showFiltersForThisGroup = true; 200 } 201 } 202 203 } 204 } 205 206 207 if (showFiltersForThisGroup){ 208 209 210 //Mobile 211 <div class="d-block d-lg-none mt-lg-0 @(contentPadding)@(theme) sticky-facets-horizontal-mobile FacetsForm_Mobile_@Model.Item.SystemName.ToLower()_@Model.ID"> 212 213 214 215 <button type="button" class="btn btn-primary w-100" data-bs-toggle="modal" data-bs-target="#FacetsModal"> 216 <span class="d-flex align-items-center"> 217 <span class="flex-grow-1 text-start"> 218 @Translate("Filter") @selectedFacetsLabel 219 </span> 220 <span class="icon-2"> 221 @ReadFile(iconPath + "sliders.svg") 222 </span> 223 </span> 224 </button> 225 226 <form method="post" action="@url" data-response-target-element="content" class="modal" id="FacetsModal" tabindex="-1" aria-hidden="false"> 227 <div class="modal-dialog modal-fullscreen"> 228 <div class="modal-content"> 229 230 <div class="modal-header@(modalTheme)"> 231 <h5 class="modal-title">@Translate("Filters and sorting")</h5> 232 <button type="button" class="btn-close" data-bs-dismiss="modal" aria-label="Close" onclick="document.querySelector('body').style = ''"></button> 233 </div> 234 <div class="modal-body@(modalTheme)"> 235 @RenderForm(productList, "mobile", enableSorting) 236 </div> 237 <div class="modal-footer d-flex@(modalTheme)"> 238 @if (selectedFacetsCount != 0) 239 { 240 <button type="button" class="btn btn-secondary flex-fill" onclick="swift.ProductList.ResetFacets(event)">@Translate("Clear") (@selectedFacetsCount)</button> 241 } 242 <button type="button" class="btn btn-primary flex-fill" onclick="location.reload();">@Translate("Update")</button> 243 </div> 244 </div> 245 </div> 246 </form> 247 </div> 248 249 } 250 } 251 else 252 { 253 if (Pageview.IsVisualEditorMode) 254 { 255 <div class="alert alert-dark m-0" role="alert"> 256 <span>@Translate("Facets: The facets selectors will be shown here, if any")</span> 257 </div> 258 } 259 else if (productList.TotalProductsCount > 0) 260 { 261 @*<div class="alert alert-dark m-0" id="NoFiltersAlert_@Model.ID"> 262 @Translate("No filters are available") 263 </div>*@ 264 265 } 266 } 267 268 269 @helper RenderForm(ProductListViewModel productList, string deviceType, bool enableSorting, string layout = "vertical") 270 { 271 string groupId = !string.IsNullOrEmpty(Dynamicweb.Context.Current.Request.QueryString.Get("GroupID")) ? Dynamicweb.Context.Current.Request.QueryString.Get("GroupID") : ""; 272 273 string iconPath = "/Files/Templates/Designs/Swift/Assets/icons/"; 274 string pageSize = !string.IsNullOrEmpty(Dynamicweb.Context.Current.Request.QueryString.Get("PageSize")) ? Dynamicweb.Context.Current.Request.QueryString.Get("PageSize") : productList.PageSize.ToString(); 275 276 string searchQuery = !string.IsNullOrEmpty(Dynamicweb.Context.Current.Request.QueryString.Get("q")) ? Dynamicweb.Context.Current.Request.QueryString.Get("q") : ""; 277 string searchLayout = !string.IsNullOrEmpty(Dynamicweb.Context.Current.Request.QueryString.Get("SearchLayout")) ? Dynamicweb.Context.Current.Request.QueryString.Get("SearchLayout") : ""; 278 279 string groupsTheme = ""; 280 string extraBottomMargin = ""; 281 if (deviceType != "mobile") 282 { 283 groupsTheme = !string.IsNullOrWhiteSpace(Model.Item.GetRawValueString("FacetGroupsTheme")) ? " theme " + Model.Item.GetRawValueString("FacetGroupsTheme").Replace(" ", "").Trim().ToLower() : ""; 284 extraBottomMargin = !string.IsNullOrEmpty(groupsTheme) ? "mb-3" : ""; 285 } 286 287 string contentPadding = Model.Item.GetRawValueString("ContentPadding", ""); 288 contentPadding = contentPadding == "none" ? " px-0 py-2" : contentPadding; 289 contentPadding = contentPadding == "small" ? " px-3 py-2" : contentPadding; 290 291 bool showFiltersForThisGroup = false; 292 293 294 if (!string.IsNullOrEmpty(groupId)){ 295 296 var group = Dynamicweb.Ecommerce.Services.ProductGroups.GetGroup(groupId); 297 298 @*if (group.Id == "14.01"){ 299 showFiltersForThisGroup = true; 300 }*@ 301 302 303 foreach (var customfield in group.ProductGroupFieldValues) { 304 if (customfield.ProductGroupField.SystemName == "ShowProductFilters"){ 305 if (customfield.Value.ToString() == "True"){ 306 showFiltersForThisGroup = true; 307 } 308 } 309 310 } 311 312 313 @* if (group.ParentGroups.Count() > 0){ 314 foreach (var parentGroups in group.ParentGroups){ 315 if (parentGroups.Id == "14.01"){ 316 showFiltersForThisGroup = true; 317 } 318 if (parentGroups.Id == "14.02"){ 319 showFiltersForThisGroup = true; 320 } 321 if (parentGroups.Id == "14.03"){ 322 showFiltersForThisGroup = true; 323 } 324 325 if (parentGroups.ParentGroups.Count() > 0){ 326 foreach (var parentParentGroups in parentGroups.ParentGroups){ 327 328 if (parentParentGroups.Id == "14.01"){ 329 showFiltersForThisGroup = true; 330 } 331 332 } 333 } 334 335 } 336 } *@ 337 } 338 339 340 341 342 343 344 @*<input type="hidden" name="PageSize" value="@pageSize">*@ 345 346 347 if (!string.IsNullOrEmpty(searchQuery)) { 348 <input type="hidden" name="q" value="@searchQuery"> 349 <input type="hidden" name="SearchLayout" value="@searchLayout"> 350 } 351 352 353 if (Model.Item.GetBoolean("EnableGroupNavigation")) 354 { 355 int startLevel = Convert.ToInt32(Model.Item.GetRawValueString("GroupNavigationStartLevel", "2")); 356 int stopLevel = Convert.ToInt32(Model.Item.GetRawValueString("GroupNavigationStopLevel", "9")); 357 358 var navigationSettings = new NavigationSettings(); 359 navigationSettings.StartLevel = startLevel; 360 navigationSettings.StopLevel = stopLevel; 361 navigationSettings.Parameters.Add("ID", deviceType); 362 navigationSettings.Parameters.Add("HideTexts", false); 363 navigationSettings.Parameters.Add("HideIcons", true); 364 navigationSettings.Parameters.Add("ContentPadding", contentPadding); 365 navigationSettings.ExpandMode = ExpandMode.All; 366 367 if (layout == "vertical") { 368 <div class="border-bottom py-2@(@groupsTheme)"> 369 <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"> 370 <h2 class="opacity-85 m-0 flex-fill h6">@Translate("Navigation")</h2> 371 <div class="my-auto collapse-chevron-icon"></div> 372 </div> 373 <div class="collapse show" id="ProductGroupNavigation_@(deviceType)_@Model.ID"> 374 @Navigation.RenderNavigation("Navigation/Vertical.cshtml", navigationSettings) 375 </div> 376 </div> 377 } 378 379 } 380 381 382 int groupCount = 0; 383 int maxGroups = 999; 384 int totalGroups = productList?.FacetGroups != null ? productList.FacetGroups.Count() : 0; 385 386 var lastOpenedFacetCookie = HttpContext.Current.Request.Cookies["LastOpenedFacet"]; 387 388 389 if (productList.FacetGroups != null && showFiltersForThisGroup) { 390 <div class="facets-options"> 391 @if (showFiltersForThisGroup){ 392 foreach (FacetGroupViewModel facetGroup in productList.FacetGroups) 393 { 394 string border = groupCount != totalGroups ? "border-bottom" : ""; 395 396 foreach (FacetViewModel facet in facetGroup.Facets) 397 { 398 string collapseClass = string.Empty; 399 string showClass = " show"; 400 string ariaExpanded = "true"; 401 var expandedFacetGroups = Model.Item.GetRawValueString("ExpandFacetGroups", "all"); 402 403 404 if (expandedFacetGroups != "all" && System.Text.RegularExpressions.Regex.IsMatch(expandedFacetGroups, "([0-9])")) 405 { 406 if (groupCount >= Dynamicweb.Core.Converter.ToInt32(expandedFacetGroups)) 407 { 408 collapseClass = " collapsed"; 409 showClass = string.Empty; 410 ariaExpanded = "false"; 411 } 412 413 } 414 415 if(lastOpenedFacetCookie != null){ 416 if (Translate(facet.Name) == lastOpenedFacetCookie.Value.Replace("%20", " ")){ 417 collapseClass = string.Empty; 418 showClass = " show"; 419 ariaExpanded = "true"; 420 } 421 422 } 423 424 if (facet.Options.Count() > 0) 425 { 426 if (layout == "vertical") { 427 <div class="@border@(contentPadding)@(@groupsTheme)"> 428 <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)"> 429 <h2 class="opacity-85 m-0 flex-fill h6 my-2">@Translate(facet.Name)</h2> 430 <div class="my-auto collapse-chevron-icon"></div> 431 </div> 432 <div class="collapse@(showClass)" id="FacetGroup_@facet.Name.Replace(" ", "").Replace(".", "")_@(deviceType)_@Model.ID"> 433 @foreach (FacetOptionViewModel facetOption in facet.Options) 434 { 435 string renderType = facet.RenderType; 436 437 if (renderType == "Colors") 438 { 439 @RenderColorOption(facet, facetOption) 440 } 441 else 442 { 443 @RenderCheckboxOption(facet, facetOption) 444 } 445 } 446 </div> 447 </div> 448 } 449 if (layout == "horizontal") { 450 string hideSelector = groupCount < maxGroups ? "" : "d-none"; 451 int selectedFacetsInGroup = 0; 452 453 foreach (FacetOptionViewModel option in facet.Options) 454 { 455 if (option.Selected) 456 { 457 selectedFacetsInGroup++; 458 } 459 } 460 461 string label = selectedFacetsInGroup > 0 ? @Translate(facet.Name) + "<span class=\"badge bg-dark opacity-50 text-white ms-2\">" + selectedFacetsInGroup + "</span>" : @Translate(facet.Name); 462 463 <div class="dropdown @hideSelector js-facets-selector"> 464 <button class="btn @(groupsTheme) dropdown-toggle" type="button" id="FacetGroup_@facet.Name.Replace(" ", "")_@(deviceType)_@Model.ID" data-bs-toggle="dropdown" aria-expanded="false"> 465 @label 466 </button> 467 <div class="dropdown-menu p-3 @(groupsTheme)" aria-labelledby="FacetGroup_@facet.Name.Replace(" ", "")_@(deviceType)_@Model.ID" style="min-width: 280px"> 468 @foreach (FacetOptionViewModel facetOption in facet.Options) 469 { 470 string translation = Translate(facetOption?.Value.ToString()); // 471 string renderType = facet.RenderType; 472 473 if (renderType == "Colors") 474 { 475 @RenderColorOption(facet, facetOption) 476 } 477 else 478 { 479 @RenderCheckboxOption(facet, facetOption) 480 } 481 } 482 </div> 483 </div> 484 } 485 486 groupCount++; 487 } 488 } 489 } 490 } 491 492 </div> 493 } 494 495 if (enableSorting) 496 { 497 <div class="right"> 498 @if (layout == "vertical") { 499 <div class="border-bottom@(contentPadding)@(groupsTheme)"> 500 <h2 class="opacity-85 m-0 my-2 flex-fill h6">@Translate("Sort by")</h2> 501 <div class="d-flex flex-column gap-2" id="SortBy_@(deviceType)_@Model.ID"> 502 @RenderSorting(deviceType) 503 </div> 504 </div> 505 } 506 @if (layout == "horizontal") { 507 508 <button class="btn @(groupsTheme) dropdown-toggle sort-button" type="button" id="SortBy_@(deviceType)_@Model.ID" data-bs-toggle="dropdown" aria-expanded="false"> 509 @Translate("Sort by") 510 <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> 511 </button> 512 <div class="dropdown-menu p-3 @(groupsTheme)" aria-labelledby="SortBy_@(deviceType)_@Model.ID" style="min-width: 280px"> 513 <div class="d-flex flex-column gap-2"> 514 @RenderSorting(deviceType) 515 </div> 516 </div> 517 } 518 <button class="btn @(groupsTheme) dropdown-toggle" type="button" id="PageSize_@Model.ID" data-bs-toggle="dropdown" aria-expanded="false"> 519 @Translate("Show product per page") 520 </button> 521 <div class="dropdown-menu p-3 @(groupsTheme)" aria-labelledby="PageSize_@Model.ID" style="min-width: 280px"> 522 <div class="d-flex flex-column gap-2"> 523 @RenderChoosePageSize(pageSize) 524 </div> 525 </div> 526 </div> 527 } 528 529 530 if ((groupCount > maxGroups) && layout == "horizontal") { 531 <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> 532 } 533 } 534 535 @helper RenderChoosePageSize(string pageSize ){ 536 537 //int originalPageSize = Converter.ToInt32(Dynamicweb.Context.Current.Request.QueryString.Get("OriginalPageSize")) > 0 ? Converter.ToInt32(Dynamicweb.Context.Current.Request.QueryString.Get("OriginalPageSize")) : 12; 538 539 540 <div class="form-check"> 541 <input @if (pageSize == "12") { <text> checked="checked" </text> } 542 class="form-check-input" onchange="swift.ProductList.Update(event)" type="radio" name="PageSize" value="12" id="PageSize_12_@Model.ID"> 543 <label class="form-check-label" for="PageSize_12_@Model.ID"> 544 12 545 </label> 546 </div> 547 <div class="form-check"> 548 <input @if (pageSize == "24") { <text> checked="checked" </text> } 549 class="form-check-input" onchange="swift.ProductList.Update(event)" type="radio" name="PageSize" value="24" id="PageSize_24_@Model.ID"> 550 <label class="form-check-label" for="PageSize_24_@Model.ID"> 551 24 552 </label> 553 </div> 554 <div class="form-check"> 555 <input @if (pageSize == "48") { <text> checked="checked" </text> } 556 class="form-check-input" onchange="swift.ProductList.Update(event)" type="radio" name="PageSize" value="48" id="PageSize_48_@Model.ID"> 557 <label class="form-check-label" for="PageSize_48_@Model.ID"> 558 48 559 </label> 560 </div> 561 <div class="form-check"> 562 <input @if (pageSize == "96") { <text> checked="checked" </text> } 563 class="form-check-input" onchange="swift.ProductList.Update(event)" type="radio" name="PageSize" value="96" id="PageSize_96_@Model.ID"> 564 <label class="form-check-label" for="PageSize_96_@Model.ID"> 565 96 566 </label> 567 </div> 568 } 569 570 @helper RenderSorting(string deviceType) { 571 string sortBySelection = Dynamicweb.Context.Current.Request?.Form["SortBy"] ?? ""; 572 sortBySelection = !string.IsNullOrEmpty(Dynamicweb.Context.Current.Request.QueryString.Get("SortBy")) ? Dynamicweb.Context.Current.Request.QueryString.Get("SortBy") : sortBySelection; 573 string sortNameSelectedRelevance = sortBySelection.ToLower() == "" || sortBySelection.ToLower() == "relevance" ? "checked" : ""; 574 string sortNameSelectedAZ = sortBySelection.ToLower() == "nameforsort" ? "checked" : ""; 575 string sortNameSelectedZA = sortBySelection.ToLower() == "-nameforsort" ? "checked" : ""; 576 string sortPriceLowSelected = sortBySelection.ToLower() == "price" ? "checked" : ""; 577 string sortPriceHighSelected = sortBySelection.ToLower() == "-price" ? "checked" : ""; 578 string sortNewSelected = sortBySelection.ToLower() == "-created" ? "checked" : ""; 579 string sortMostSoldSelected = sortBySelection.ToLower() == "-ordercount" ? "checked" : ""; 580 581 string sortProductNr = sortBySelection.ToLower() == "productnumbersort" ? "checked" : ""; 582 string sortProductNrZA = sortBySelection.ToLower() == "-productnumbersort" ? "checked" : ""; 583 584 string anonymousUsersLimitations = Pageview.AreaSettings.GetRawValueString("AnonymousUsers", ""); 585 bool anonymousUser = Pageview.User == null; 586 bool hidePrice = anonymousUsersLimitations.Contains("price") && anonymousUser; 587 588 if (Model.Item.GetBoolean("SortByRelevance")) 589 { 590 <div class="form-check"> 591 <input class="form-check-input" onchange="swift.ProductList.Update(event)" type="radio" name="SortBy" value="" id="SortByRelevance_@(deviceType)_@Model.ID" @sortNameSelectedRelevance> 592 <label class="form-check-label" for="SortByRelevance_@(deviceType)_@Model.ID"> 593 @Translate("Relevance") 594 </label> 595 </div> 596 } 597 if (Model.Item.GetBoolean("SortByNameAZ")) 598 { 599 <div class="form-check"> 600 <input class="form-check-input" onchange="swift.ProductList.Update(event)" type="radio" name="SortBy" value="NameForSort" id="SortByNameAZ_@(deviceType)_@Model.ID" @sortNameSelectedAZ> 601 <label class="form-check-label" for="SortByNameAZ_@(deviceType)_@Model.ID"> 602 @Translate("Name (A-Z)") 603 </label> 604 </div> 605 } 606 if (Model.Item.GetBoolean("SortByNameZA")) 607 { 608 <div class="form-check"> 609 <input class="form-check-input" onchange="swift.ProductList.Update(event)" type="radio" name="SortBy" value="-NameForSort" id="SortByNameZA_@(deviceType)_@Model.ID" @sortNameSelectedZA> 610 <label class="form-check-label" for="SortByNameZA_@(deviceType)_@Model.ID"> 611 @Translate("Name (Z-A)") 612 </label> 613 </div> 614 } 615 if (Model.Item.GetBoolean("SortByNewest")) 616 { 617 <div class="form-check"> 618 <input class="form-check-input" onchange="swift.ProductList.Update(event)" type="radio" name="SortBy" value="-created" id="SortByNew_@(deviceType)_@Model.ID" @sortNewSelected> 619 <label class="form-check-label" for="SortByNew_@(deviceType)_@Model.ID"> 620 @Translate("Newest") 621 </label> 622 </div> 623 } 624 if (!hidePrice) 625 { 626 if (Model.Item.GetBoolean("SortByLowestPrice")) 627 { 628 <div class="form-check"> 629 <input class="form-check-input" onchange="swift.ProductList.Update(event)" type="radio" name="SortBy" value="Price" id="SortByPriceLow_@(deviceType)_@Model.ID" @sortPriceLowSelected> 630 <label class="form-check-label" for="SortByPriceLow_@(deviceType)_@Model.ID"> 631 @Translate("Lowest price") 632 </label> 633 </div> 634 } 635 if (Model.Item.GetBoolean("SortByHighestPrice")) 636 { 637 <div class="form-check"> 638 <input class="form-check-input" onchange="swift.ProductList.Update(event)" type="radio" name="SortBy" value="-Price" id="SortByPriceHigh_@(deviceType)_@Model.ID" @sortPriceHighSelected> 639 <label class="form-check-label" for="SortByPriceHigh_@(deviceType)_@Model.ID"> 640 @Translate("Highest price") 641 </label> 642 </div> 643 } 644 } 645 if (Model.Item.GetBoolean("SortByMostSold")) 646 { 647 <div class="form-check"> 648 <input class="form-check-input" onchange="swift.ProductList.Update(event)" type="radio" name="SortBy" value="-OrderCount" id="SortByMostSold_@(deviceType)_@Model.ID" @sortMostSoldSelected> 649 <label class="form-check-label" for="SortByMostSold_@(deviceType)_@Model.ID"> 650 @Translate("Most sold") 651 </label> 652 </div> 653 } 654 <div class="form-check"> 655 <input class="form-check-input" onchange="swift.ProductList.Update(event)" type="radio" name="SortBy" value="ProductNumberSort" id="ProductNumberSort_@(deviceType)_@Model.ID" @sortProductNr> 656 <label class="form-check-label" for="ProductNumberSort_@(deviceType)_@Model.ID"> 657 @Translate("Product No. (Low)") 658 </label> 659 </div> 660 661 <div class="form-check"> 662 <input class="form-check-input" onchange="swift.ProductList.Update(event)" type="radio" name="SortBy" value="-ProductNumberSort" id="ProductNumberSortZA_@(deviceType)_@Model.ID" @sortProductNrZA> 663 <label class="form-check-label" for="ProductNumberSortZA_@(deviceType)_@Model.ID"> 664 @Translate("Product No. (High)") 665 </label> 666 </div> 667 } 668 669 @helper RenderCheckboxOption(FacetViewModel facet, FacetOptionViewModel facetOption) 670 { 671 string facetLabel = HtmlEncoder.HtmlEncode(facetOption.Label); 672 string disabled = facetOption.Count <= 0 ? "disabled" : ""; 673 string selected = facetOption.Selected ? "checked" : ""; 674 675 if (facetLabel.ToLower() == "true") 676 { 677 facetLabel = Translate("Yes"); 678 } 679 680 if (facetLabel.ToLower() == "false") 681 { 682 facetLabel = Translate("No"); 683 } 684 685 <label class="form-check mt-1" @disabled> 686 <input type="checkbox" onclick="swift.ProductList.Update(event)" class="form-check-input" name="@facet.QueryParameter" value="[@facetOption.Value]" data-filter-value="@facetLabel" @selected> 687 <span class="form-check-label d-flex align-items-center"> 688 <span class="flex-fill">@Translate(facetLabel) </span> 689 @if (facet.FacetType.ToLower() == "field") { 690 <small class="opacity-85">@facetOption.Count</small> 691 } 692 </span> 693 </label> 694 } 695 696 @helper RenderColorOption(FacetViewModel facet, FacetOptionViewModel facetOption) 697 { 698 string facetLabel = HtmlEncoder.HtmlEncode(facetOption.Label); 699 string disabled = facetOption.Count <= 0 ? "disabled" : ""; 700 string selected = facetOption.Selected ? "checked" : ""; 701 702 string image = facetOption.Value; 703 string colorCode = facetOption.Value; 704 705 var variantOption = Dynamicweb.Ecommerce.Services.VariantOptions.GetVariantOption(facetOption.Value.ToString(), Dynamicweb.Ecommerce.Common.Context.LanguageID); 706 if (variantOption != null) 707 { 708 image = variantOption.LargeImage; 709 colorCode = variantOption.Color; 710 } 711 712 <div class="colorbox"> 713 <label> 714 <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"> 715 @if (colorCode.Contains("#")) 716 { 717 <span class="colorbox-background" style="background-color: @colorCode"></span> 718 <span class="visually-hidden">@Translate(facetOption.Label)</span> 719 } 720 else 721 { 722 <img class="colorbox-background" src="/Admin/Public/GetImage.ashx?width=25&height=25&image=@image"> 723 <span class="visually-hidden">@Translate(facetOption.Label)</span> 724 } 725 </label> 726 </div> 727 } 728 729
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_76284208c87d4164b54fe2824338f5ae.<>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 303
   at CompiledRazorTemplates.Dynamic.RazorEngine_76284208c87d4164b54fe2824338f5ae.Execute() in D:\dynamicweb.net\Solutions\FlexMedia\siso2021.cloud.dynamicweb-cms.com\files\Templates\Designs\Swift\Paragraph\Swift_ProductListFacets.cshtml:line 177
   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 horizontalFacetsParent.style.setProperty('--sticky-top', headerBottomPos + 'px'); 159 horizontalFacets.style.cssText = 'width:' + horizontalFacetsParent.offsetWidth + 'px'; 160 161 162 } else { 163 facetsTop.classList.remove("sticky"); 164 horizontalFacets.classList.remove("sticky"); 165 } 166 } 167 168 </script> 169 170 } 171 if (layout == "horizontal") { 172 contentPadding = Model.Item.GetRawValueString("ContentPadding", "") == "small" ? " p-3" : contentPadding; 173 174 175 <div class="@theme @contentPadding h-100"> 176 <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()"> 177 @RenderForm(productList, "desktop", enableSorting, layout) 178 179 @if (selectedFacetsCount > 0) { 180 <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> 181 } 182 </form> 183 </div> 184 } 185 186 bool showFiltersForThisGroup = false; 187 188 string groupId = !string.IsNullOrEmpty(Dynamicweb.Context.Current.Request.QueryString.Get("GroupID")) ? Dynamicweb.Context.Current.Request.QueryString.Get("GroupID") : ""; 189 190 191 if (!string.IsNullOrEmpty(groupId)){ 192 193 var group = Dynamicweb.Ecommerce.Services.ProductGroups.GetGroup(groupId); 194 195 196 foreach (var customfield in group.ProductGroupFieldValues) { 197 if (customfield.ProductGroupField.SystemName == "ShowProductFilters"){ 198 if (customfield.Value.ToString() == "True"){ 199 showFiltersForThisGroup = true; 200 } 201 } 202 203 } 204 } 205 206 207 if (showFiltersForThisGroup){ 208 209 210 //Mobile 211 <div class="d-block d-lg-none mt-lg-0 @(contentPadding)@(theme) sticky-facets-horizontal-mobile FacetsForm_Mobile_@Model.Item.SystemName.ToLower()_@Model.ID"> 212 213 214 215 <button type="button" class="btn btn-primary w-100" data-bs-toggle="modal" data-bs-target="#FacetsModal"> 216 <span class="d-flex align-items-center"> 217 <span class="flex-grow-1 text-start"> 218 @Translate("Filter") @selectedFacetsLabel 219 </span> 220 <span class="icon-2"> 221 @ReadFile(iconPath + "sliders.svg") 222 </span> 223 </span> 224 </button> 225 226 <form method="post" action="@url" data-response-target-element="content" class="modal" id="FacetsModal" tabindex="-1" aria-hidden="false"> 227 <div class="modal-dialog modal-fullscreen"> 228 <div class="modal-content"> 229 230 <div class="modal-header@(modalTheme)"> 231 <h5 class="modal-title">@Translate("Filters and sorting")</h5> 232 <button type="button" class="btn-close" data-bs-dismiss="modal" aria-label="Close" onclick="document.querySelector('body').style = ''"></button> 233 </div> 234 <div class="modal-body@(modalTheme)"> 235 @RenderForm(productList, "mobile", enableSorting) 236 </div> 237 <div class="modal-footer d-flex@(modalTheme)"> 238 @if (selectedFacetsCount != 0) 239 { 240 <button type="button" class="btn btn-secondary flex-fill" onclick="swift.ProductList.ResetFacets(event)">@Translate("Clear") (@selectedFacetsCount)</button> 241 } 242 <button type="button" class="btn btn-primary flex-fill" onclick="location.reload();">@Translate("Update")</button> 243 </div> 244 </div> 245 </div> 246 </form> 247 </div> 248 249 } 250 } 251 else 252 { 253 if (Pageview.IsVisualEditorMode) 254 { 255 <div class="alert alert-dark m-0" role="alert"> 256 <span>@Translate("Facets: The facets selectors will be shown here, if any")</span> 257 </div> 258 } 259 else if (productList.TotalProductsCount > 0) 260 { 261 @*<div class="alert alert-dark m-0" id="NoFiltersAlert_@Model.ID"> 262 @Translate("No filters are available") 263 </div>*@ 264 265 } 266 } 267 268 269 @helper RenderForm(ProductListViewModel productList, string deviceType, bool enableSorting, string layout = "vertical") 270 { 271 string groupId = !string.IsNullOrEmpty(Dynamicweb.Context.Current.Request.QueryString.Get("GroupID")) ? Dynamicweb.Context.Current.Request.QueryString.Get("GroupID") : ""; 272 273 string iconPath = "/Files/Templates/Designs/Swift/Assets/icons/"; 274 string pageSize = !string.IsNullOrEmpty(Dynamicweb.Context.Current.Request.QueryString.Get("PageSize")) ? Dynamicweb.Context.Current.Request.QueryString.Get("PageSize") : productList.PageSize.ToString(); 275 276 string searchQuery = !string.IsNullOrEmpty(Dynamicweb.Context.Current.Request.QueryString.Get("q")) ? Dynamicweb.Context.Current.Request.QueryString.Get("q") : ""; 277 string searchLayout = !string.IsNullOrEmpty(Dynamicweb.Context.Current.Request.QueryString.Get("SearchLayout")) ? Dynamicweb.Context.Current.Request.QueryString.Get("SearchLayout") : ""; 278 279 string groupsTheme = ""; 280 string extraBottomMargin = ""; 281 if (deviceType != "mobile") 282 { 283 groupsTheme = !string.IsNullOrWhiteSpace(Model.Item.GetRawValueString("FacetGroupsTheme")) ? " theme " + Model.Item.GetRawValueString("FacetGroupsTheme").Replace(" ", "").Trim().ToLower() : ""; 284 extraBottomMargin = !string.IsNullOrEmpty(groupsTheme) ? "mb-3" : ""; 285 } 286 287 string contentPadding = Model.Item.GetRawValueString("ContentPadding", ""); 288 contentPadding = contentPadding == "none" ? " px-0 py-2" : contentPadding; 289 contentPadding = contentPadding == "small" ? " px-3 py-2" : contentPadding; 290 291 bool showFiltersForThisGroup = false; 292 293 294 if (!string.IsNullOrEmpty(groupId)){ 295 296 var group = Dynamicweb.Ecommerce.Services.ProductGroups.GetGroup(groupId); 297 298 @*if (group.Id == "14.01"){ 299 showFiltersForThisGroup = true; 300 }*@ 301 302 303 foreach (var customfield in group.ProductGroupFieldValues) { 304 if (customfield.ProductGroupField.SystemName == "ShowProductFilters"){ 305 if (customfield.Value.ToString() == "True"){ 306 showFiltersForThisGroup = true; 307 } 308 } 309 310 } 311 312 313 @* if (group.ParentGroups.Count() > 0){ 314 foreach (var parentGroups in group.ParentGroups){ 315 if (parentGroups.Id == "14.01"){ 316 showFiltersForThisGroup = true; 317 } 318 if (parentGroups.Id == "14.02"){ 319 showFiltersForThisGroup = true; 320 } 321 if (parentGroups.Id == "14.03"){ 322 showFiltersForThisGroup = true; 323 } 324 325 if (parentGroups.ParentGroups.Count() > 0){ 326 foreach (var parentParentGroups in parentGroups.ParentGroups){ 327 328 if (parentParentGroups.Id == "14.01"){ 329 showFiltersForThisGroup = true; 330 } 331 332 } 333 } 334 335 } 336 } *@ 337 } 338 339 340 341 342 343 344 @*<input type="hidden" name="PageSize" value="@pageSize">*@ 345 346 347 if (!string.IsNullOrEmpty(searchQuery)) { 348 <input type="hidden" name="q" value="@searchQuery"> 349 <input type="hidden" name="SearchLayout" value="@searchLayout"> 350 } 351 352 353 if (Model.Item.GetBoolean("EnableGroupNavigation")) 354 { 355 int startLevel = Convert.ToInt32(Model.Item.GetRawValueString("GroupNavigationStartLevel", "2")); 356 int stopLevel = Convert.ToInt32(Model.Item.GetRawValueString("GroupNavigationStopLevel", "9")); 357 358 var navigationSettings = new NavigationSettings(); 359 navigationSettings.StartLevel = startLevel; 360 navigationSettings.StopLevel = stopLevel; 361 navigationSettings.Parameters.Add("ID", deviceType); 362 navigationSettings.Parameters.Add("HideTexts", false); 363 navigationSettings.Parameters.Add("HideIcons", true); 364 navigationSettings.Parameters.Add("ContentPadding", contentPadding); 365 navigationSettings.ExpandMode = ExpandMode.All; 366 367 if (layout == "vertical") { 368 <div class="border-bottom py-2@(@groupsTheme)"> 369 <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"> 370 <h2 class="opacity-85 m-0 flex-fill h6">@Translate("Navigation")</h2> 371 <div class="my-auto collapse-chevron-icon"></div> 372 </div> 373 <div class="collapse show" id="ProductGroupNavigation_@(deviceType)_@Model.ID"> 374 @Navigation.RenderNavigation("Navigation/Vertical.cshtml", navigationSettings) 375 </div> 376 </div> 377 } 378 379 } 380 381 382 int groupCount = 0; 383 int maxGroups = 999; 384 int totalGroups = productList?.FacetGroups != null ? productList.FacetGroups.Count() : 0; 385 386 var lastOpenedFacetCookie = HttpContext.Current.Request.Cookies["LastOpenedFacet"]; 387 388 389 if (productList.FacetGroups != null && showFiltersForThisGroup) { 390 <div class="facets-options"> 391 @if (showFiltersForThisGroup){ 392 foreach (FacetGroupViewModel facetGroup in productList.FacetGroups) 393 { 394 string border = groupCount != totalGroups ? "border-bottom" : ""; 395 396 foreach (FacetViewModel facet in facetGroup.Facets) 397 { 398 string collapseClass = string.Empty; 399 string showClass = " show"; 400 string ariaExpanded = "true"; 401 var expandedFacetGroups = Model.Item.GetRawValueString("ExpandFacetGroups", "all"); 402 403 404 if (expandedFacetGroups != "all" && System.Text.RegularExpressions.Regex.IsMatch(expandedFacetGroups, "([0-9])")) 405 { 406 if (groupCount >= Dynamicweb.Core.Converter.ToInt32(expandedFacetGroups)) 407 { 408 collapseClass = " collapsed"; 409 showClass = string.Empty; 410 ariaExpanded = "false"; 411 } 412 413 } 414 415 if(lastOpenedFacetCookie != null){ 416 if (Translate(facet.Name) == lastOpenedFacetCookie.Value.Replace("%20", " ")){ 417 collapseClass = string.Empty; 418 showClass = " show"; 419 ariaExpanded = "true"; 420 } 421 422 } 423 424 if (facet.Options.Count() > 0) 425 { 426 if (layout == "vertical") { 427 <div class="@border@(contentPadding)@(@groupsTheme)"> 428 <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)"> 429 <h2 class="opacity-85 m-0 flex-fill h6 my-2">@Translate(facet.Name)</h2> 430 <div class="my-auto collapse-chevron-icon"></div> 431 </div> 432 <div class="collapse@(showClass)" id="FacetGroup_@facet.Name.Replace(" ", "").Replace(".", "")_@(deviceType)_@Model.ID"> 433 @foreach (FacetOptionViewModel facetOption in facet.Options) 434 { 435 string renderType = facet.RenderType; 436 437 if (renderType == "Colors") 438 { 439 @RenderColorOption(facet, facetOption) 440 } 441 else 442 { 443 @RenderCheckboxOption(facet, facetOption) 444 } 445 } 446 </div> 447 </div> 448 } 449 if (layout == "horizontal") { 450 string hideSelector = groupCount < maxGroups ? "" : "d-none"; 451 int selectedFacetsInGroup = 0; 452 453 foreach (FacetOptionViewModel option in facet.Options) 454 { 455 if (option.Selected) 456 { 457 selectedFacetsInGroup++; 458 } 459 } 460 461 string label = selectedFacetsInGroup > 0 ? @Translate(facet.Name) + "<span class=\"badge bg-dark opacity-50 text-white ms-2\">" + selectedFacetsInGroup + "</span>" : @Translate(facet.Name); 462 463 <div class="dropdown @hideSelector js-facets-selector"> 464 <button class="btn @(groupsTheme) dropdown-toggle" type="button" id="FacetGroup_@facet.Name.Replace(" ", "")_@(deviceType)_@Model.ID" data-bs-toggle="dropdown" aria-expanded="false"> 465 @label 466 </button> 467 <div class="dropdown-menu p-3 @(groupsTheme)" aria-labelledby="FacetGroup_@facet.Name.Replace(" ", "")_@(deviceType)_@Model.ID" style="min-width: 280px"> 468 @foreach (FacetOptionViewModel facetOption in facet.Options) 469 { 470 string translation = Translate(facetOption?.Value.ToString()); // 471 string renderType = facet.RenderType; 472 473 if (renderType == "Colors") 474 { 475 @RenderColorOption(facet, facetOption) 476 } 477 else 478 { 479 @RenderCheckboxOption(facet, facetOption) 480 } 481 } 482 </div> 483 </div> 484 } 485 486 groupCount++; 487 } 488 } 489 } 490 } 491 492 </div> 493 } 494 495 if (enableSorting) 496 { 497 <div class="right"> 498 @if (layout == "vertical") { 499 <div class="border-bottom@(contentPadding)@(groupsTheme)"> 500 <h2 class="opacity-85 m-0 my-2 flex-fill h6">@Translate("Sort by")</h2> 501 <div class="d-flex flex-column gap-2" id="SortBy_@(deviceType)_@Model.ID"> 502 @RenderSorting(deviceType) 503 </div> 504 </div> 505 } 506 @if (layout == "horizontal") { 507 508 <button class="btn @(groupsTheme) dropdown-toggle sort-button" type="button" id="SortBy_@(deviceType)_@Model.ID" data-bs-toggle="dropdown" aria-expanded="false"> 509 @Translate("Sort by") 510 <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> 511 </button> 512 <div class="dropdown-menu p-3 @(groupsTheme)" aria-labelledby="SortBy_@(deviceType)_@Model.ID" style="min-width: 280px"> 513 <div class="d-flex flex-column gap-2"> 514 @RenderSorting(deviceType) 515 </div> 516 </div> 517 } 518 <button class="btn @(groupsTheme) dropdown-toggle" type="button" id="PageSize_@Model.ID" data-bs-toggle="dropdown" aria-expanded="false"> 519 @Translate("Show product per page") 520 </button> 521 <div class="dropdown-menu p-3 @(groupsTheme)" aria-labelledby="PageSize_@Model.ID" style="min-width: 280px"> 522 <div class="d-flex flex-column gap-2"> 523 @RenderChoosePageSize(pageSize) 524 </div> 525 </div> 526 </div> 527 } 528 529 530 if ((groupCount > maxGroups) && layout == "horizontal") { 531 <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> 532 } 533 } 534 535 @helper RenderChoosePageSize(string pageSize ){ 536 537 //int originalPageSize = Converter.ToInt32(Dynamicweb.Context.Current.Request.QueryString.Get("OriginalPageSize")) > 0 ? Converter.ToInt32(Dynamicweb.Context.Current.Request.QueryString.Get("OriginalPageSize")) : 12; 538 539 540 <div class="form-check"> 541 <input @if (pageSize == "12") { <text> checked="checked" </text> } 542 class="form-check-input" onchange="swift.ProductList.Update(event)" type="radio" name="PageSize" value="12" id="PageSize_12_@Model.ID"> 543 <label class="form-check-label" for="PageSize_12_@Model.ID"> 544 12 545 </label> 546 </div> 547 <div class="form-check"> 548 <input @if (pageSize == "24") { <text> checked="checked" </text> } 549 class="form-check-input" onchange="swift.ProductList.Update(event)" type="radio" name="PageSize" value="24" id="PageSize_24_@Model.ID"> 550 <label class="form-check-label" for="PageSize_24_@Model.ID"> 551 24 552 </label> 553 </div> 554 <div class="form-check"> 555 <input @if (pageSize == "48") { <text> checked="checked" </text> } 556 class="form-check-input" onchange="swift.ProductList.Update(event)" type="radio" name="PageSize" value="48" id="PageSize_48_@Model.ID"> 557 <label class="form-check-label" for="PageSize_48_@Model.ID"> 558 48 559 </label> 560 </div> 561 <div class="form-check"> 562 <input @if (pageSize == "96") { <text> checked="checked" </text> } 563 class="form-check-input" onchange="swift.ProductList.Update(event)" type="radio" name="PageSize" value="96" id="PageSize_96_@Model.ID"> 564 <label class="form-check-label" for="PageSize_96_@Model.ID"> 565 96 566 </label> 567 </div> 568 } 569 570 @helper RenderSorting(string deviceType) { 571 string sortBySelection = Dynamicweb.Context.Current.Request?.Form["SortBy"] ?? ""; 572 sortBySelection = !string.IsNullOrEmpty(Dynamicweb.Context.Current.Request.QueryString.Get("SortBy")) ? Dynamicweb.Context.Current.Request.QueryString.Get("SortBy") : sortBySelection; 573 string sortNameSelectedRelevance = sortBySelection.ToLower() == "" || sortBySelection.ToLower() == "relevance" ? "checked" : ""; 574 string sortNameSelectedAZ = sortBySelection.ToLower() == "nameforsort" ? "checked" : ""; 575 string sortNameSelectedZA = sortBySelection.ToLower() == "-nameforsort" ? "checked" : ""; 576 string sortPriceLowSelected = sortBySelection.ToLower() == "price" ? "checked" : ""; 577 string sortPriceHighSelected = sortBySelection.ToLower() == "-price" ? "checked" : ""; 578 string sortNewSelected = sortBySelection.ToLower() == "-created" ? "checked" : ""; 579 string sortMostSoldSelected = sortBySelection.ToLower() == "-ordercount" ? "checked" : ""; 580 581 string sortProductNr = sortBySelection.ToLower() == "productnumbersort" ? "checked" : ""; 582 string sortProductNrZA = sortBySelection.ToLower() == "-productnumbersort" ? "checked" : ""; 583 584 string anonymousUsersLimitations = Pageview.AreaSettings.GetRawValueString("AnonymousUsers", ""); 585 bool anonymousUser = Pageview.User == null; 586 bool hidePrice = anonymousUsersLimitations.Contains("price") && anonymousUser; 587 588 if (Model.Item.GetBoolean("SortByRelevance")) 589 { 590 <div class="form-check"> 591 <input class="form-check-input" onchange="swift.ProductList.Update(event)" type="radio" name="SortBy" value="" id="SortByRelevance_@(deviceType)_@Model.ID" @sortNameSelectedRelevance> 592 <label class="form-check-label" for="SortByRelevance_@(deviceType)_@Model.ID"> 593 @Translate("Relevance") 594 </label> 595 </div> 596 } 597 if (Model.Item.GetBoolean("SortByNameAZ")) 598 { 599 <div class="form-check"> 600 <input class="form-check-input" onchange="swift.ProductList.Update(event)" type="radio" name="SortBy" value="NameForSort" id="SortByNameAZ_@(deviceType)_@Model.ID" @sortNameSelectedAZ> 601 <label class="form-check-label" for="SortByNameAZ_@(deviceType)_@Model.ID"> 602 @Translate("Name (A-Z)") 603 </label> 604 </div> 605 } 606 if (Model.Item.GetBoolean("SortByNameZA")) 607 { 608 <div class="form-check"> 609 <input class="form-check-input" onchange="swift.ProductList.Update(event)" type="radio" name="SortBy" value="-NameForSort" id="SortByNameZA_@(deviceType)_@Model.ID" @sortNameSelectedZA> 610 <label class="form-check-label" for="SortByNameZA_@(deviceType)_@Model.ID"> 611 @Translate("Name (Z-A)") 612 </label> 613 </div> 614 } 615 if (Model.Item.GetBoolean("SortByNewest")) 616 { 617 <div class="form-check"> 618 <input class="form-check-input" onchange="swift.ProductList.Update(event)" type="radio" name="SortBy" value="-created" id="SortByNew_@(deviceType)_@Model.ID" @sortNewSelected> 619 <label class="form-check-label" for="SortByNew_@(deviceType)_@Model.ID"> 620 @Translate("Newest") 621 </label> 622 </div> 623 } 624 if (!hidePrice) 625 { 626 if (Model.Item.GetBoolean("SortByLowestPrice")) 627 { 628 <div class="form-check"> 629 <input class="form-check-input" onchange="swift.ProductList.Update(event)" type="radio" name="SortBy" value="Price" id="SortByPriceLow_@(deviceType)_@Model.ID" @sortPriceLowSelected> 630 <label class="form-check-label" for="SortByPriceLow_@(deviceType)_@Model.ID"> 631 @Translate("Lowest price") 632 </label> 633 </div> 634 } 635 if (Model.Item.GetBoolean("SortByHighestPrice")) 636 { 637 <div class="form-check"> 638 <input class="form-check-input" onchange="swift.ProductList.Update(event)" type="radio" name="SortBy" value="-Price" id="SortByPriceHigh_@(deviceType)_@Model.ID" @sortPriceHighSelected> 639 <label class="form-check-label" for="SortByPriceHigh_@(deviceType)_@Model.ID"> 640 @Translate("Highest price") 641 </label> 642 </div> 643 } 644 } 645 if (Model.Item.GetBoolean("SortByMostSold")) 646 { 647 <div class="form-check"> 648 <input class="form-check-input" onchange="swift.ProductList.Update(event)" type="radio" name="SortBy" value="-OrderCount" id="SortByMostSold_@(deviceType)_@Model.ID" @sortMostSoldSelected> 649 <label class="form-check-label" for="SortByMostSold_@(deviceType)_@Model.ID"> 650 @Translate("Most sold") 651 </label> 652 </div> 653 } 654 <div class="form-check"> 655 <input class="form-check-input" onchange="swift.ProductList.Update(event)" type="radio" name="SortBy" value="ProductNumberSort" id="ProductNumberSort_@(deviceType)_@Model.ID" @sortProductNr> 656 <label class="form-check-label" for="ProductNumberSort_@(deviceType)_@Model.ID"> 657 @Translate("Product No. (Low)") 658 </label> 659 </div> 660 661 <div class="form-check"> 662 <input class="form-check-input" onchange="swift.ProductList.Update(event)" type="radio" name="SortBy" value="-ProductNumberSort" id="ProductNumberSortZA_@(deviceType)_@Model.ID" @sortProductNrZA> 663 <label class="form-check-label" for="ProductNumberSortZA_@(deviceType)_@Model.ID"> 664 @Translate("Product No. (High)") 665 </label> 666 </div> 667 } 668 669 @helper RenderCheckboxOption(FacetViewModel facet, FacetOptionViewModel facetOption) 670 { 671 string facetLabel = HtmlEncoder.HtmlEncode(facetOption.Label); 672 string disabled = facetOption.Count <= 0 ? "disabled" : ""; 673 string selected = facetOption.Selected ? "checked" : ""; 674 675 if (facetLabel.ToLower() == "true") 676 { 677 facetLabel = Translate("Yes"); 678 } 679 680 if (facetLabel.ToLower() == "false") 681 { 682 facetLabel = Translate("No"); 683 } 684 685 <label class="form-check mt-1" @disabled> 686 <input type="checkbox" onclick="swift.ProductList.Update(event)" class="form-check-input" name="@facet.QueryParameter" value="[@facetOption.Value]" data-filter-value="@facetLabel" @selected> 687 <span class="form-check-label d-flex align-items-center"> 688 <span class="flex-fill">@Translate(facetLabel) </span> 689 @if (facet.FacetType.ToLower() == "field") { 690 <small class="opacity-85">@facetOption.Count</small> 691 } 692 </span> 693 </label> 694 } 695 696 @helper RenderColorOption(FacetViewModel facet, FacetOptionViewModel facetOption) 697 { 698 string facetLabel = HtmlEncoder.HtmlEncode(facetOption.Label); 699 string disabled = facetOption.Count <= 0 ? "disabled" : ""; 700 string selected = facetOption.Selected ? "checked" : ""; 701 702 string image = facetOption.Value; 703 string colorCode = facetOption.Value; 704 705 var variantOption = Dynamicweb.Ecommerce.Services.VariantOptions.GetVariantOption(facetOption.Value.ToString(), Dynamicweb.Ecommerce.Common.Context.LanguageID); 706 if (variantOption != null) 707 { 708 image = variantOption.LargeImage; 709 colorCode = variantOption.Color; 710 } 711 712 <div class="colorbox"> 713 <label> 714 <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"> 715 @if (colorCode.Contains("#")) 716 { 717 <span class="colorbox-background" style="background-color: @colorCode"></span> 718 <span class="visually-hidden">@Translate(facetOption.Label)</span> 719 } 720 else 721 { 722 <img class="colorbox-background" src="/Admin/Public/GetImage.ashx?width=25&height=25&image=@image"> 723 <span class="visually-hidden">@Translate(facetOption.Label)</span> 724 } 725 </label> 726 </div> 727 } 728 729
12 aus 494 Produkte
< 1 2 ... 41 42 >