Home
Wiki
Home
Wiki
  1. 2. Components
  • Back to home
  • 1. Themes
  • Vs Code
    • Getting Started
  • Kitchenware
    • Layout
      • New Layout
      • Legacy Layout
    • Components
      • Announcement
      • Banner Carousel
      • Banner With Products Carousel
      • Blog Category List
      • Blog List
      • Brand List
      • Brands Carousel
      • Breadcrumb
      • Call To Action
      • Cart
      • Categories List
      • Change Password
      • Checkout
      • Cookie Manager
      • Filter list
      • Footer
      • Forgot Password
      • Form
      • Hero Carousel
      • Icon Block
      • Invitation
      • Last Visited Products
      • Layout
      • Login
      • Map
      • Nav Bar
      • Offer
      • Product Attachments
      • Product Attributes
      • Product Documentation
      • Product Expected
      • Product Modal
      • Products Block
      • Products Carousel
      • Product Single
      • Profile
      • Quote
      • Register
      • Related Products
      • Search
      • Stores
      • Subscribe Newsletter
      • Text with Image
      • Top Bar
      • Video
    • Reusables
      • Getting Started
    • Assets
      • Getting Started
    • SDK
      • Products
        • _findProductsByCategory
        • _findProductsByIds
        • _findProductsByTitle
        • _findProductsByFilter
        • _findProductsByCriteria
        • _findProductsAndCalculate
        • _findProductsThenCalculate
        • _getProductAttributeSet
        • _setLastVisited
      • Categories
        • _findCategoryTreeById
        • _findCategoriesByIds
        • _findCategoryByAlias
        • _findCategoryTreeByAlias
        • _getCategoryContent
      • Collections
        • _getCollectionContent
        • _findCollectionsByIds
        • _findCollectionsByIdsThenCalculate
      • Brands
        • _getBrandContent
        • _findBrandsByIds
      • Cart
        • _addToCartMulti
        • _addToCart
        • _setCart
        • _clearCart
        • _setCartListener
        • _removeFromCart
        • _calculateCart
      • Checkout
        • _startCheckout
        • _updateCheckout
        • _completeCheckout
      • Shopping Lists
        • _getShoppingLists
        • _updateShoppingList
        • _createShoppingList
        • _deleteShoppingList
        • _getShoppingListByAlias
      • Navigation
        • _getFooterMenu
        • _getHeaderMenu
      • Users
        • _getUserById
      • Utils
        • _calculateCurrency
        • _getCurrencySymbol
        • _getCulture
        • _subscribeToNewsletter
        • _findUnitsByIds
  • Noir
    • 0. Introduction
    • 1. Structure
      • Overview
      • LayoutA.liquid
      • ComponentsList.liquid
      • Metas.liquid
      • CssVariables.liquid
      • Json.liquid
      • GoogleTagManager.liquid
      • StagingButton.liquid
    • 2. Components
      • Overview
      • Announcement
      • BannerCarousel
      • BlogCategoryList
      • BlogList
      • BrandList
      • Breadcrumb
      • Cart
      • CategoriesList
      • ChangePassword
      • Checkout
      • CookieManager
      • FilterList
      • Footer
      • ForgotPassword
      • Form
      • IconBlock
      • Invitation
      • LastVisitedProducts
      • Login
      • Map
      • NavBar
      • ProductAttachments
      • ProductAttributes
      • ProductComparison
      • ProductDocumentation
      • ProductMixList
      • ProductsBlock
      • ProductsCarousel
      • ProductSingle
      • Profile
      • Register
      • RelatedProducts
      • SingleBlog
      • Stores
      • TextWithImage
      • ThankYouPage
      • TopBar
      • Wishlist
    • 3. Reusables
      • Overview
      • Addresses
      • BillingRetail
      • AddressForm
      • AnnouncementModal
      • BackToTop
      • Company
      • General
      • Login
      • LoginModal
      • Orders
      • Payment
      • ProductAttachments
      • ProductAttributes
      • ProductComparisonButton
      • ProductComparisonFloatingButton
      • ProductGridItem
      • ProductListItem
      • ShoppingListsButton
      • ProductModal
      • ProfileInfo
      • PromptModal
      • Register
      • Shipping
      • ShoppingLists
      • ShoppingListsNavbar
      • Toast
      • Users
      • VariantContent
      • WishlistButton
      • Services
    • 4. Assets
      • Fonts
      • Images
      • Templates
      • Javascript
        • Overview
        • theme.js
      • Css / Scss
        • Overview
        • ThemeClasses
    • 5. SDK
      • Overview
      • LiquidGlobals
      • ServicesSDK
  1. 2. Components

Stores

Purpose#

The Stores component renders a store locator page.
It:
shows a sidebar list of stores (grouped) with a search filter
shows a Leaflet map with clustered markers
allows zooming to a selected store and opening its marker popup
can find nearest stores using browser geolocation
falls back to rendering the company “main store” address (or a no-stores message) when there are no configured store groups

Inputs (model contract)#

Model shape (storefront example)#

{
  "name": "Stores",
  "view": "Default",
  "section": "SectionA",
  "settings": {
    "groups": [
      {
        "title": "Sample title",
        "stores": [
          {
            "name": "Sample text",
            "address": {
              "address1": "Sample text",
              "address2": "",
              "city": "Sample text",
              "state": "Sample text",
              "country": "",
              "postalCode": "",
              "translation": {}
            },
            "phone": "Sample text",
            "email": "sample@example.com",
            "workingHours": "<p>Sample text</p>",
            "latitude": "37.000000",
            "longitude": "23.000000",
            "url": "https://example.com/store",
            "imageTranslation": {}
          },
          "..."
        ]
      },
      "..."
    ],
    "markerLink": {
      "id": "Marker Media Id",
      "link": "https://example.com/media/marker.png",
      "mediaType": "Image"
    },
    "id": "Component Id",
    "section": "SectionA",
    "type": "NoirStores",
    "name": "Stores",
    "configuredInContentApi": true,
    "view": "Default",
    "displayName": "",
    "cssClass": ""
  },
  "translations": {
    "mainStore": "Sample text",
    "noStoresFound": "Sample text",
    "findNearestStores": "Sample text",
    "...": "..."
  }
}

Required fields#

settings.id

Optional fields#

settings.cssClass
settings.groups[]
When missing/empty, the template falls back to:
the company address from GlobalData.Company.Address.*, if present
otherwise translations.noStoresAvailable
settings.markerLink.link (custom marker icon)
translations.*

JavaScript#

Global object#

Components/Stores/Default.js exposes:
Liquid binds it via Alpine:
<section
  x-data='storesdefault.initComponent(groups, markerLink, id, viewStoreTranslation, viewDirectionsTranslation)'
>

initComponent(groups, markerLink, id, viewStoreTranslation, viewDirectionsTranslation)#

What it does
Creates and returns the Alpine state object.
Stores the groups/stores data, translations used in marker popups, and map state.

init()#

What it does
Flattens groups[] into flatStores[] and adds groupTitle into each store.
Initializes the Leaflet map.
Key behaviors / edge cases
After flattening, it assigns this.groups = this.flatStores.
From that point on, groups is effectively the flat list.

initMap()#

What it does
Creates a Leaflet map (L.map) in #map-<id>.
Adds Carto Voyager tiles.
Adds markers and fits bounds (or centers on the single marker).

setInteractionsEnabled(enabled)#

What it does
Enables/disables map interactions (scroll zoom, dragging, etc.).

addMarkers()#

What it does
Creates a marker cluster group.
For each store with valid latitude/longitude:
creates a Leaflet marker (custom icon if markerLink exists)
binds a popup with store info + optional “View store” and “View directions” links
Key behaviors / edge cases
Skips stores with invalid coordinates.
Disables map interactions while the popup is open and re-enables them on close.

filterStores()#

What it does
Filters the list based on searchQuery across:
city
store name
group title
postal code
address1
Key behaviors / edge cases
Uses accent-insensitive matching via removeAccents(...).

removeAccents(str)#

What it does
Removes diacritical marks by normalizing to NFD.

filteredStoresCount (getter)#

What it does
Returns the current filtered list count.

toggleStoreDetails(storeIndex)#

What it does
Expands/collapses the store details in the sidebar.

zoomStore(storeIndex)#

What it does
Centers the map on the selected store.
Finds the closest marker to the store coordinates and opens its popup.

findNearestStores()#

What it does
Requests user location via navigator.geolocation.
Calculates distances to stores and zooms to the nearest.
Key behaviors / edge cases
Shows alert(...) messages for geolocation errors.

calculateDistance(lat1, lon1, lat2, lon2)#

What it does
Returns distance in km using the Haversine formula.

degToRad(deg)#

What it does
Converts degrees to radians.

Dependencies#

Alpine.js
Leaflet (L)
Leaflet MarkerCluster (L.markerClusterGroup)
generalreusabledefault.searchComponent() (search input model)

Notes#

The sidebar uses flatStores for rendering; groups is mutated into the flat list during init().
Marker popups are created via bindPopup(...) with HTML strings.
The template’s fallback “main store” view depends on GlobalData.Company.Address.*.

Extras#

Template behavior (Liquid + Alpine)#

Renders a sidebar only when settings.groups.size > 0.
When there are no groups:
renders a “main store” address if it can build one from GlobalData.Company.Address.*
else renders translations.noStoresAvailable.
Calls zoomStore(...) when the user clicks “Find us on the map” under a store.
Modified at 2026-04-14 13:18:56
Previous
SingleBlog
Next
TextWithImage
Built with