Marco chinos
Error executing template "Designs/Swift/Components/VariantSelector_Custom.cshtml" System.NullReferenceException: Object reference not set to an instance of an object. at CompiledRazorTemplates.Dynamic.RazorEngine_30dbef4483014918b75421eb16d43a03.ExecuteAsync() at RazorEngine.Templating.TemplateBase.Run(ExecuteContext context, TextWriter reader) at RazorEngine.Templating.RazorEngineCore.RunTemplate(ICompiledTemplate template, TextWriter writer, Object model, DynamicViewBag viewBag) at RazorEngine.Templating.RazorEngineService.Run(ITemplateKey key, TextWriter writer, Type modelType, Object model, DynamicViewBag viewBag) at RazorEngine.Templating.DynamicWrapperService.Run(ITemplateKey key, TextWriter writer, Type modelType, Object model, DynamicViewBag viewBag) at RazorEngine.Templating.RazorEngineServiceExtensions.Run(IRazorEngineService service, String name, TextWriter writer, Type modelType, Object model, DynamicViewBag viewBag) at RazorEngine.Templating.RazorEngineServiceExtensions.<>c__DisplayClass23_0.<Run>b__0(TextWriter writer) at RazorEngine.Templating.RazorEngineServiceExtensions.WithWriter(Action`1 withWriter) at RazorEngine.Templating.RazorEngineServiceExtensions.Run(IRazorEngineService service, String name, Type modelType, Object model, DynamicViewBag viewBag) 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 System.Collections.Generic 3 @using System.Linq 4 @using Dynamicweb.Ecommerce.ProductCatalog 5 @using Dynamicweb.Ecommerce.Variants 6 @using Dynamicweb.Frontend 7 @using Dynamicweb.Ecommerce.Products 8 9 @functions { 10 //Find contrast color (white, black) 11 public static string GetContrastColor(string hexString) 12 { 13 System.Drawing.Color bg = System.Drawing.ColorTranslator.FromHtml(hexString); 14 15 int nThreshold = 105; 16 int bgDelta = Convert.ToInt32((bg.R * 0.299) + (bg.G * 0.587) + 17 (bg.B * 0.114)); 18 19 string foreColor = (255 - bgDelta < nThreshold) ? "#333" : "#fff"; 20 return foreColor; 21 } 22 23 public string GetLayoutForVariantGroup(string variantGroupId) 24 { 25 string showVariantGroups = Model.Item?.GetRawValueString("ShowVariantGroupOptions"); 26 var selectedVariantGroupsList = Model.Item?.GetItems("VariantGroups") ?? new List<ItemViewModel>(); 27 bool showAllVariantGroupsDefault = string.IsNullOrEmpty(showVariantGroups) || selectedVariantGroupsList == null || !selectedVariantGroupsList.Any(); 28 string defaultVariantGroupLayout = Model.Item?.GetRawValueString("DefaultVariantGroupLayout"); 29 defaultVariantGroupLayout = !string.IsNullOrEmpty(defaultVariantGroupLayout) ? defaultVariantGroupLayout : "button"; 30 31 if (showAllVariantGroupsDefault) return defaultVariantGroupLayout; 32 33 foreach (var selectedVariantGroupListItem in selectedVariantGroupsList) 34 { 35 var variantGroups = selectedVariantGroupListItem.GetList("VariantGroups").GetRawValue().OfType<string>().ToList(); 36 if (variantGroups.Any(s => s.Equals(variantGroupId))) return selectedVariantGroupListItem.GetRawValueString("VariantGroupLayout"); 37 } 38 39 return defaultVariantGroupLayout; 40 } 41 42 //Collect all variant images 43 public static Dictionary<string, string> GetVariantImages(List<VariantInfoViewModel> variantInfo, Dictionary<string, string> list) 44 { 45 foreach (var variantGroup in variantInfo) 46 { 47 if (variantGroup.Image?.Value != null && !list.ContainsKey(variantGroup.OptionID)) 48 { 49 list.Add(variantGroup.OptionID, variantGroup.Image.Value); 50 } 51 52 if (variantGroup.VariantInfo != null) 53 { 54 GetVariantImages(variantGroup.VariantInfo, list); 55 } 56 } 57 58 return list; 59 } 60 61 private string GetDefaultOrVariantGroupValue(string variantGroupId, string itemField, string itemFieldDefaultValue, Dictionary<string, string> fieldValueMapping) 62 { 63 if (!string.IsNullOrEmpty(variantGroupId)) 64 { 65 string itemFieldValue = Model.Item?.GetRawValueString(itemField, itemFieldDefaultValue); 66 string itemFieldParameter = GetViewParameterString(itemField); 67 itemFieldValue = string.IsNullOrEmpty(itemFieldValue) && !string.IsNullOrEmpty(itemFieldParameter) ? itemFieldParameter : itemFieldValue; 68 69 if (fieldValueMapping != null && !string.IsNullOrEmpty(itemFieldValue) && fieldValueMapping.Any()) 70 { 71 itemFieldValue = fieldValueMapping.ContainsKey(itemFieldValue) ? fieldValueMapping[itemFieldValue] : itemFieldValue; 72 } 73 74 // If no variantGroup (i.e. Visual Editor), return default value 75 if (string.IsNullOrEmpty(variantGroupId)) return itemFieldValue; 76 77 string showVariantGroups = Model.Item?.GetString("ShowVariantGroupOptions", "all"); 78 var selectedVariantGroupsList = Model.Item?.GetItems("VariantGroups") ?? new List<ItemViewModel>(); 79 // If no exceptions or settings are all the same, return default value 80 if (showVariantGroups == "all" || selectedVariantGroupsList == null || !selectedVariantGroupsList.Any()) return itemFieldValue; 81 82 // Get specific value for variant group 83 foreach (var selectedVariantGroupListItem in selectedVariantGroupsList) 84 { 85 var variantGroups = selectedVariantGroupListItem.GetList("VariantGroups").GetRawValue().OfType<string>().ToList(); 86 if (!variantGroups.Any(s => s.Equals(variantGroupId))) continue; 87 88 itemFieldValue = selectedVariantGroupListItem.GetRawValueString(itemField, itemFieldDefaultValue); 89 itemFieldValue = fieldValueMapping.ContainsKey(itemFieldValue) ? fieldValueMapping[itemFieldValue] : itemFieldValue; 90 } 91 92 return itemFieldValue; 93 } 94 else 95 { 96 return string.Empty; 97 } 98 } 99 100 private bool GetDefaultOrVariantGroupValue(string variantGroupId, string itemField) 101 { 102 if (!string.IsNullOrEmpty(variantGroupId)) 103 { 104 bool itemFieldValue = Model.Item?.GetBoolean(itemField) ?? false; 105 106 // If no variantGroup (i.e. Visual Editor), return default value 107 if (string.IsNullOrEmpty(variantGroupId)) return itemFieldValue; 108 109 string showVariantGroups = Model.Item?.GetString("ShowVariantGroupOptions", "all"); 110 var selectedVariantGroupsList = Model.Item?.GetItems("VariantGroups") ?? new List<ItemViewModel>(); 111 // If no exceptions or settings are all the same, return default value 112 if (showVariantGroups == "all" || selectedVariantGroupsList == null || !selectedVariantGroupsList.Any()) return itemFieldValue; 113 114 // Get specific value for variant group 115 foreach (var selectedVariantGroupListItem in selectedVariantGroupsList) 116 { 117 var variantGroups = selectedVariantGroupListItem.GetList("VariantGroups").GetRawValue().OfType<string>().ToList(); 118 if (!variantGroups.Any(s => s.Equals(variantGroupId))) continue; 119 120 itemFieldValue = selectedVariantGroupListItem.GetBoolean(itemField); 121 } 122 123 return itemFieldValue; 124 } 125 else 126 { 127 return false; 128 } 129 } 130 } 131 132 @{ 133 ProductViewModel product = null; 134 if (Dynamicweb.Context.Current.Items.Contains("ProductDetails")) 135 { 136 product = (ProductViewModel)Dynamicweb.Context.Current.Items["ProductDetails"]; 137 } 138 else if (Pageview.Page.Item["DummyProduct"] != null && Pageview.IsVisualEditorMode) 139 { 140 var pageViewModel = Dynamicweb.Frontend.ContentViewModelFactory.CreatePageInfoViewModel(Pageview.Page); 141 ProductListViewModel productList = pageViewModel.Item.GetValue("DummyProduct") != null ? pageViewModel.Item.GetValue("DummyProduct") as ProductListViewModel : new ProductListViewModel(); 142 143 if (productList?.Products is object) 144 { 145 product = productList.Products[0]; 146 } 147 } 148 //CUSTOM CODE 149 string baseURL = string.Empty; 150 } 151 152 @if ((product is object)) 153 { 154 155 bool hideGroupHeaders = !string.IsNullOrEmpty(Model?.Item?.GetString("HideGroupHeaders")) ? Model.Item.GetBoolean("HideGroupHeaders") : false; 156 var productVariantGroups = product.VariantGroups(); 157 158 string itemId = Model?.Item?.SystemName != null ? $"item_{Model.Item.SystemName.ToLower()}" : string.Empty; 159 160 bool isModalSelector = Model?.Item == null; 161 string target = isModalSelector ? "data-response-target-element=\"DynamicModalContent\"" : string.Empty; 162 163 string variantSelectorServicePageId = !string.IsNullOrEmpty(Dynamicweb.Context.Current.Request.Form.Get("VariantSelectorServicePage")) ? Dynamicweb.Context.Current.Request.Form.Get("VariantSelectorServicePage") : string.Empty; 164 string formAction = isModalSelector ? $"action=\"/Default.aspx?ID={variantSelectorServicePageId}\"" : string.Empty; 165 166 string getProductInfo = !string.IsNullOrEmpty(Dynamicweb.Context.Current.Request.Form["getproductinfo"]) ? Dynamicweb.Context.Current.Request.Form["getproductinfo"] : string.Empty; 167 168 if (productVariantGroups.Any() && product?.VariantInfo?.VariantInfo != null) 169 { 170 string[] variantId = product.VariantId.Split('.'); 171 int groupNumber = 1; 172 173 string baseUrl = $"Default.aspx?ID={GetPageIdByNavigationTag("Shop")}&GroupID={product.PrimaryOrDefaultGroup.Id}&ProductID={product.Id}"; 174 string variantUrl = string.Empty; 175 if (!string.IsNullOrEmpty(product.VariantId) && !isModalSelector) 176 { 177 variantUrl = Dynamicweb.Frontend.SearchEngineFriendlyURLs.GetFriendlyUrl($"Default.aspx?ID={GetPageIdByNavigationTag("Shop")}&GroupID={product.PrimaryOrDefaultGroup.Id}&ProductID={product.Id}&VariantID={product.VariantId}"); 178 } 179 // CUSTOM CODE 180 baseURL = $"/Default.aspx?ID={GetPageIdByNavigationTag("Shop")}&GroupID={product.PrimaryOrDefaultGroup.Id}&ProductID={product.Id}&VariantID="; 181 Dictionary<string, string> variantImages = new Dictionary<string, string>(); 182 variantImages = GetVariantImages(product.VariantInfo.VariantInfo, variantImages); 183 184 <form @formAction class="d-flex flex-column gap-2 js-variant-selector @itemId" @target data-combinations="@string.Join(",", product.VariantCombinations())" data-base-url="@baseUrl" data-friendly-url="@variantUrl"> 185 @if (isModalSelector) 186 { 187 <input type="hidden" name="productId" value="@product.Id"> 188 <input type="hidden" name="variantid" value="@product.VariantId"> 189 <input type="hidden" name="QuantitySelector" value="true"> 190 <input type="hidden" name="VariantSelectorServicePage" value="@variantSelectorServicePageId"> 191 <input type="hidden" name="ViewType" value="ModalContent"> 192 193 if (GetViewParameter("ButtonLayout") != null) 194 { 195 <input type="hidden" name="ButtonLayout" value="@GetViewParameter("ButtonLayout")"> 196 } 197 198 if (GetViewParameter("ButtonAspectRatio") != null) 199 { 200 <input type="hidden" name="ButtonAspectRatio" value="@GetViewParameter("ButtonAspectRatio")"> 201 } 202 203 if (!string.IsNullOrEmpty(getProductInfo)) 204 { 205 <input type="hidden" name="getproductinfo" value="@getProductInfo"> 206 } 207 } 208 209 @foreach (var variantGroup in productVariantGroups) 210 { 211 VariantGroupViewModel group = variantGroup; 212 string variantGroupLayout = GetLayoutForVariantGroup(variantGroup.Id) ?? "button"; 213 string horizontalAlign = GetDefaultOrVariantGroupValue(variantGroup.Id, "HorizontalAlignment", "", new Dictionary<string, string> { { "center", "justify-content-center" }, { "end", "justify-content-end" } }); 214 string horizontalTextAlign = GetDefaultOrVariantGroupValue(variantGroup.Id, "HorizontalAlignment", "", new Dictionary<string, string> { { "center", "text-center" }, { "end", "text-end" } }); 215 bool showSelectedOptionName = GetDefaultOrVariantGroupValue(variantGroup.Id, "ShowSelectedOptionName"); 216 217 <div> 218 @if (!hideGroupHeaders) 219 { 220 <h3 class="h6 @horizontalTextAlign"> 221 @group.Name 222 223 @if (showSelectedOptionName) 224 { 225 string selectedOptionName = group.Options.FirstOrDefault(opt => variantId.Contains(opt.Id))?.Name ?? string.Empty; 226 <span class="fw-light px-1 swift-selected-option-name">@selectedOptionName</span> 227 } 228 </h3> 229 } 230 <div class="d-flex gap-2 @horizontalAlign flex-wrap js-variant-group" data-group-id="@groupNumber"> 231 @if (variantGroupLayout == "button") 232 { 233 234 foreach (var option in group.Options) 235 { 236 @* CUSTOM CODE *@ 237 string productColor = product.VariantId.Split('.').FirstOrDefault() ?? ""; 238 string productSize = option.Id.Split('.').LastOrDefault() ?? ""; 239 string variantCombination = productColor + "." + productSize; 240 Product currentOptionProduct = Dynamicweb.Ecommerce.Services.Products.GetProductById(product.Id, variantCombination, Pageview.Area.EcomLanguageId); 241 242 bool isVariantMaster = currentOptionProduct?.GetIsVariantMaster() ?? false; 243 244 Dictionary<string, bool> hasValidVariantOptionsByMaster = new Dictionary<string, bool>(); 245 Dictionary<string, List<string>> validSizesByColorId = new Dictionary<string, List<string>>(); 246 if (isVariantMaster) 247 { 248 var allVariantsOfMasterProduct = Dynamicweb.Ecommerce.Services.Products.GetProductsAndVariantsByProduct(currentOptionProduct).ToList(); 249 List<string> validVariantsList = new List<string>(); 250 251 foreach (var variant in allVariantsOfMasterProduct) 252 { 253 var colorId = variant.VariantId.Split('.').First() ?? ""; 254 if (!string.IsNullOrEmpty(colorId) && !hasValidVariantOptionsByMaster.ContainsKey(colorId)) 255 { 256 hasValidVariantOptionsByMaster[colorId] = false; 257 foreach (var variantProduct in allVariantsOfMasterProduct) 258 { 259 if (variantProduct.VariantId.Contains(colorId)) 260 { 261 if (variantProduct.Stock > 0) 262 { 263 if (!validSizesByColorId.ContainsKey(colorId)) 264 { 265 validSizesByColorId.Add(colorId, new List<string>()); 266 } 267 hasValidVariantOptionsByMaster[colorId] = true; 268 validSizesByColorId[colorId].Add(variantProduct.VariantId); 269 } 270 } 271 } 272 } 273 274 } 275 276 277 } 278 279 bool isOptionProductOutOfStock = currentOptionProduct == null || currentOptionProduct.Stock <= 0; 280 var skipMaster = true; 281 282 foreach (var item in hasValidVariantOptionsByMaster) 283 { 284 if (item.Value) 285 { 286 if (option.Id.Contains(item.Key)) 287 { 288 skipMaster = false; 289 } 290 291 } 292 } 293 294 if (isVariantMaster && skipMaster) 295 { 296 continue; 297 } 298 299 if (!isVariantMaster && currentOptionProduct.Stock <= 0) 300 { 301 continue; 302 } 303 304 if (isVariantMaster && !validSizesByColorId.ContainsKey(option.Id)) 305 { 306 continue; 307 } 308 309 @* END OF CUSTOM CODE *@ 310 311 string active = variantId != null && variantId.Contains(option.Id) ? "active" : string.Empty; 312 string buttonId = $"{product.Id}_{option.Id}_{Pageview.CurrentParagraph.ID}"; 313 string contrastColor = string.Empty; 314 string buttonAspectRatio = GetDefaultOrVariantGroupValue(variantGroup.Id, "ButtonAspectRatio", "100%", new Dictionary<string, string> { { "100%", "--bs-aspect-ratio:100%" }, { "56%", "--bs-aspect-ratio:56%" }, { "177%", "--bs-aspect-ratio:177%" }, { "75%", "--bs-aspect-ratio:75%" }, { "133%", "--bs-aspect-ratio:133%" } }); 315 buttonAspectRatio = buttonAspectRatio == string.Empty ? "--bs-aspect-ratio:100%" : buttonAspectRatio; 316 317 string buttonLayout = GetDefaultOrVariantGroupValue(variantGroup.Id, "ButtonLayout", "rounded-circle", new Dictionary<string, string> { { "round", "rounded-circle" }, { "square", "rounded-0" }, { "square-rounded", "rounded-3" } }); 318 string buttonTextLayout = GetDefaultOrVariantGroupValue(variantGroup.Id, "ButtonTextLayout", "", new Dictionary<string, string> { { "default", "" }, { "square", "rounded-0" }, { "square-rounded", "rounded-3" } }); 319 var displayType = group.DisplayType; 320 displayType = displayType == VariantGroupDisplayType.NothingSelected && !string.IsNullOrEmpty(option.Color) ? VariantGroupDisplayType.VariantColor : displayType; 321 displayType = displayType == VariantGroupDisplayType.NothingSelected && string.IsNullOrEmpty(option.OptionImage.Value) && string.IsNullOrEmpty(option.Color) ? VariantGroupDisplayType.VariantName : displayType; 322 displayType = displayType == VariantGroupDisplayType.NothingSelected && !string.IsNullOrEmpty(option.OptionImage.Value) ? VariantGroupDisplayType.VariantOptionImage : displayType; 323 324 var btnWidth = displayType == VariantGroupDisplayType.VariantColor || displayType == VariantGroupDisplayType.VariantImage || displayType == VariantGroupDisplayType.VariantOptionImage ? $"style=\"width:64px\"" : string.Empty; 325 var btnClasses = string.Empty; 326 327 btnClasses = displayType == VariantGroupDisplayType.VariantColor ? $"overflow-hidden colorbox colorbox-auto p-0 border {buttonLayout}" : btnClasses; 328 btnClasses = displayType == VariantGroupDisplayType.VariantImage ? $"overflow-hidden p-0 {buttonLayout}" : btnClasses; 329 btnClasses = displayType == VariantGroupDisplayType.VariantOptionImage ? $"overflow-hidden colorbox colorbox-auto {buttonLayout} p-0" : btnClasses; 330 btnClasses = displayType == VariantGroupDisplayType.VariantName ? $"btn-secondary {buttonTextLayout}" : btnClasses; 331 332 var variantOptions = !string.IsNullOrEmpty(product.VariantId)? product.VariantId.Split(".") : new string[0]; 333 334 string? selectedVariant = variantOptions.LastOrDefault(); 335 string? selectedMasterVariant = variantOptions.FirstOrDefault(); 336 337 <button type="button" 338 class="btn @btnClasses d-inline-block variant-option js-variant-option @active @(isVariantMaster ? "is-master" : string.Empty) @(isOptionProductOutOfStock ? "product-out-of-stock" : string.Empty)" @btnWidth 339 onclick="swift.VariantSelector.OptionClick(event)" 340 data-selected-master-variant="@selectedMasterVariant" 341 data-selectedvariant="@selectedVariant" 342 data-variant-id="@option.Id" id="@(product.Id)_@(option.Id)_@Pageview.CurrentParagraph.ID" 343 @( 344 isVariantMaster && 345 validSizesByColorId != null && 346 validSizesByColorId.TryGetValue(option.Id, out var list) && 347 list != null && list.Any() 348 ? $"data-validvariants=\"{string.Join(",", list)}\"" 349 : string.Empty 350 )> 351 <div class="@(displayType == VariantGroupDisplayType.VariantName ? string.Empty : "ratio")" style="@(buttonAspectRatio)"> 352 353 @switch (displayType) 354 { 355 case VariantGroupDisplayType.VariantOptionImage: 356 if (!string.IsNullOrEmpty(option.OptionImage.Value)) 357 { 358 <img style="object-fit:cover;--variantoption-check-color:@(contrastColor)" src="/Admin/Public/GetImage.ashx?image=@(option.OptionImage.Value)&width=64&format=webp"> 359 } 360 else if (!string.IsNullOrEmpty(option.Color)) 361 { 362 <span class="" style="background-color:@(option.Color);--variantoption-check-color:@(contrastColor)"><span class="visually-hidden">@option.Color</span></span> 363 } 364 else 365 { 366 <span class="d-flex align-items-center justify-content-center">@(option.Name)</span> 367 } 368 break; 369 370 case VariantGroupDisplayType.VariantImage: 371 string variantImage = string.Empty; 372 variantImages.TryGetValue(option.Id, out variantImage); 373 <img class="theme" style="object-fit:contain" src="/Admin/Public/GetImage.ashx?image=@(variantImage)&width=64&format=webp"> 374 break; 375 376 case VariantGroupDisplayType.VariantColor: 377 contrastColor = GetContrastColor(option.Color); 378 <span class="" style="background-color:@(option.Color);--variantoption-check-color:@(contrastColor)"><span class="visually-hidden">@option.Color</span></span> 379 break; 380 381 case VariantGroupDisplayType.VariantName: 382 <span class="d-flex align-items-center justify-content-center">@(option.Name)</span> 383 break; 384 385 } 386 </div> 387 </button> 388 } 389 } 390 else 391 { 392 <select class="form-select" id="VariantDropdown_@variantGroup.Id" aria-label="@variantGroup.Name" onchange="swift.VariantSelector.OptionClick(event)"> 393 @if (string.IsNullOrEmpty(product.VariantId)) 394 { 395 <option value="" class="variant-option js-variant-option" data-variant-id="">@Translate("Nothing selected")</option> 396 } 397 398 @foreach (var option in variantGroup.Options) 399 { 400 string active = variantId != null && variantId.Contains(option.Id) ? "active" : ""; 401 var selected = variantId != null && variantId.Contains(option.Id) ? "selected" : ""; 402 var value = $"{product.Id}_{option.Id}"; 403 404 <option value="@(value)" class="variant-option js-variant-option @active" data-variant-id="@option.Id" id="@(value)_@(Pageview.CurrentParagraph.ID)" @selected>@option.Name</option> 405 } 406 </select> 407 } 408 </div> 409 </div> 410 411 groupNumber++; 412 } 413 </form> 414 415 <script type="module"> 416 swift.VariantSelector.init(); 417 </script> 418 } 419 else if (Pageview.IsVisualEditorMode) 420 { 421 string horizontalAlign = GetDefaultOrVariantGroupValue("", "HorizontalAlignment", "", new Dictionary<string, string> { { "center", "justify-content-center" }, { "end", "justify-content-end" } }); 422 string horizontalTextAlign = GetDefaultOrVariantGroupValue("", "HorizontalAlignment", "", new Dictionary<string, string> { { "center", "text-center" }, { "end", "text-end" } }); 423 424 <form class="d-flex flex-column js-variant-selector @itemId" data-combinations="VO1,VO2,VO3,VO4"> 425 <div> 426 @if (!hideGroupHeaders) 427 { 428 <h3 class="h6 @horizontalTextAlign">@Translate("Sizes")</h3> 429 } 430 <div class="mb-3 @horizontalAlign js-variant-group" data-group-id="0"> 431 <button type="button" class="btn btn-secondary d-inline-block mb-2 variant-option js-variant-option" onclick="swift.VariantSelector.OptionClick(event)" data-variant-id="VO1" id="@(product.Id)_VO1_@Pageview.CurrentParagraph.ID">S</button> 432 <button type="button" class="btn btn-secondary d-inline-block mb-2 variant-option js-variant-option" onclick="swift.VariantSelector.OptionClick(event)" data-variant-id="VO2" id="@(product.Id)_VO2_@Pageview.CurrentParagraph.ID">M</button> 433 <button type="button" class="btn btn-secondary d-inline-block mb-2 variant-option js-variant-option" onclick="swift.VariantSelector.OptionClick(event)" data-variant-id="VO3" id="@(product.Id)_VO3_@Pageview.CurrentParagraph.ID">L</button> 434 <button type="button" class="btn btn-secondary d-inline-block mb-2 variant-option js-variant-option" onclick="swift.VariantSelector.OptionClick(event)" data-variant-id="VO4" id="@(product.Id)_VO4_@Pageview.CurrentParagraph.ID">XL</button> 435 </div> 436 </div> 437 </form> 438 439 <script type="module"> 440 swift.VariantSelector.init(); 441 </script> 442 } 443 } 444 else if (Pageview.IsVisualEditorMode) 445 { 446 <div class="alert alert-dark m-0" role="alert"> 447 <span>@Translate("No products available")</span> 448 </div> 449 } 450 @*CUSTOM CODE*@ 451 <style> 452 .disabled-option { 453 pointer-events: none; 454 opacity: 0.5; 455 cursor: not-allowed; 456 } 457 </style> 458 459 <script> 460 document.addEventListener('DOMContentLoaded', () => { 461 462 function selectFirstSizeIfNone(target) { 463 const context = target || document; 464 const sizeGroup = context.querySelector('.js-variant-group[data-group-id="2"]'); 465 if (!sizeGroup) return; 466 467 const activeSize = sizeGroup.querySelector('.js-variant-option.active'); 468 if (!activeSize) { 469 const firstSizeButton = sizeGroup.querySelector('.js-variant-option[data-variant-id]'); 470 if (firstSizeButton) { 471 472 setTimeout(() => firstSizeButton.click(), 1); 473 } 474 } 475 } 476 const hideInactiveVariants = () => { 477 const elements = document.querySelectorAll('.variant-option.in-active:not(option)'); 478 elements.forEach(element => { 479 const validVariants = element.dataset.validvariants ? element.dataset.validvariants.split(',') : ''; 480 if (validVariants.length > 0) { 481 element.classList.remove('in-active'); 482 return; 483 } else { 484 element.classList.add('disabled-option'); 485 } 486 487 }); 488 } 489 hideInactiveVariants(); 490 491 selectFirstSizeIfNone(); 492 493 494 document.addEventListener("updated.swift.pageupdater", (e) => { 495 selectFirstSizeIfNone(e.target); 496 hideInactiveVariants(); 497 }); 498 499 }); 500 </script> 501 @*END OF CUSTOM CODE*@
• Hvis varen er på lager, så findes den også i vores fysiske butik - Vester Voldgade 5, 1552 København
Hvorfor skal du handle på troelstrup.com?
Få fri fragt
30 dages returret
Bliv en del af Troelstrup Exclusive
Beskrivelse
Yderligere information
Marco chinos fra danske No Nationality, også kendt som NN07. Marco chinos er en af brandets helt klassiske chinos, som går igen sæson efter sæson grundet buksernes popularitet. Marco er syet i bomuldsstof med stretch, som gør bukserne behagelige at have på. Designet er herudover ganske klassisk med paspolerede baglommer, skrålommer, billetlomme foran og lukning med lynlås og knapper. Pasformen er regular med relativt smalle ben og mellem livhøjde. Marco er et par super hverdagsbukser, som passer ind i enhver maskulin garderobe.
Detaljer
Specifikationer
| Materiale | Bomuld |
| Vaskeanvisning |
|
| Artikel | 1400 |
| Farve-kode leverandør | 170 GREEN |
| Materiale sammensætning | 96% bomuld, 4% elastan |
| Model | buks |
Om brandet
-
NN.07 blev grundlagt i 2007 af de to venner Victor Lindh og Ulrik Pedersen. Under en inspirationstur til Japan skulle de to venner finde på et navn til deres nye virksomhed. De ville definere hvad de ønskede at skabe med brandet, og kom frem til ‘No Nationality’. Et brand uden grænser – både bogstaveligt talt og symbolsk.