通貨セレクター自作してみた!

公開
通貨セレクター自作してみた!



通貨セレクター(国/地域セレクター)の作り方について解説します
※以下通貨セレクターで進めます

Dawnだとこんな通貨セレクターがありますよね!! 

こちらをオリジナルで作って自由にカスタマイズしていきたいと思います

完成系はこちら

右上のものが自作した言語セレクターになります

※わかりやすいようにあえてヘッダーの上に配置しています。
※下のセレクターはDawnデフォルトのもの 

{% if localization.available_countries.size > 1 %}
<localization-form>
{% form 'localization' %}
<div class="c_currency-container">
  <div type="button " class="c_disclosure__button c_currency-title" aria-expanded="false" aria-controls="CountryList">
  {{ localization.country.name }} ({{ localization.country.currency.iso_code }} {{ localization.country.currency.symbol }}){% render 'icon-caret' %}
  </div>

  <ul id="CountryList" role="list" class="c_currency-list">
  {% for country in localization.available_countries %}
    <li class="c_disclosure__item" tabindex="-1">
    <a href="#" {% if country.iso_code == localization.country.iso_code %} aria-current="true" {% endif %}
      data-value="{{ country.iso_code }}" onclick="updateCountry('{{ country.iso_code }}'); return false;">
      {{ country.name }} ({{ country.currency.iso_code }} {{ country.currency.symbol }})
    </a>
    </li>
  {% endfor %}
  </ul>

  <input type="hidden" name="country_code" value="{{ localization.country.iso_code }}" id="country_code_hidden">
</div>
{% endform %}
</localization-form>

<script>
  //クリック時にformを送信
  function updateCountry(isoCode) {
  document.getElementById("country_code_hidden").value = isoCode;
  document.querySelector("localization-form form").submit();
  }

  document.addEventListener("DOMContentLoaded", function() {
    const titleElement = document.querySelector(".c_currency-title");
    const listElement = document.querySelector(".c_currency-list");
    
    titleElement.addEventListener("click", function(event) {
        event.stopPropagation();
        listElement.classList.toggle("show");
    });
    
    document.addEventListener("click", function(event) {
        if (!listElement.contains(event.target)) {
        listElement.classList.remove("show");
        }
    });
  });
</script>

<style>
  .c_currency-container {
  position: relative;
  display: inline-block;
  padding: 0 10px;
  z-index: 1;
  }

  .c_currency-container svg {
  width: 10px;
  }

  .c_currency-title {
  display: inline-block;
  cursor: pointer;
  }

  .c_currency-list {
  position: absolute;
  display: none;
  top: 100%;
  right: 0;
  min-width: 100%;
  width: max-content;
  background: #fff;
  margin: 0;
  padding: 10px;
  list-style: none;
  }

  .c_currency-list.show {
  display: block;
  }

  .c_currency-list a {
  font-size: 14px;
  }
</style>
{% endif %}

上記コードを埋め込みたい箇所に貼り付けていただければ大丈夫です!
あとはて適宜CSSを調整していただければ自由にカスタマイズができます!

コードの解説

各種オブジェクト(localization)

今回のコードではlocalizationオブジェクトを使用しています

こちらのオブジェクトを使用して利用可能な国とその言語に対する情報を使用できます

{{ localization.available_countries.size }} → 利用可能な国数

{{ localization.country.name }} → 選択中の国の名前(日本)

{{ localization.country.iso_code }} → 選択中の国のISOコード(JPY)

{{ localization.country.currency.symbol }} → 選択中のシンボルマーク(¥)

利用可能な国をfor文で回して1つずつ出力させます セレクターの中身の部分(添付の赤枠)


{% for country in localization.available_countries %}
    <li class="c_disclosure__item" tabindex="-1">
        <a href="#" {% if country.iso_code == localization.country.iso_code %} aria-current="true" {% endif %}
            data-value="{{ country.iso_code }}" onclick="updateCountry('{{ country.iso_code }}'); return false;">
        {{ country.name }} ({{ country.currency.iso_code }} {{ country.currency.symbol }})
        </a>
    </li>
{% endfor %}

カスタムHTML<localization-form>

ん?なんか変なタグで囲ってるぞ?ってなりますよね!

私もなりましたw

こちらはカスタム要素というものでして、 HTMLのカスタム要素を使って独自のHTML(localization-form)を定義しています。

 

↓↓もうちょっと詳しく、カスタム要素とは?

HTMLのカスタム要素は、開発者が独自のHTML要素を定義することができる仕組みです。これらのカスタム要素は、通常のHTML要素と同じように文書内に配置され、ブラウザによって解釈されます。カスタム要素は、Webコンポーネントの一部として使用され、特定の機能や振る舞いを持つ再利用可能なコンポーネントを作成するために使用されます。
※Dawnだとlocalization-form.jsで定義されています。

formタグ{% form 'localization' %}{% endform %}

国セレクター、言語セレクター用のformタグがあらかじめShopifyで準備されていています

参考サイト

こちらのコードで囲ってあげることで自動でformタグとinputタグが出力されます

自動で出力されるHTMLタグ↓↓

<form method="post" action="/localization" id="localization_form" accept-charset="UTF-8" class="shopify-localization-form" enctype="multipart/form-data">
    <input type="hidden" name="form_type" value="localization" />
    <input type="hidden" name="utf8" value="✓" />
    <input type="hidden" name="_method" value="put" />
    <input type="hidden" name="return_to" value="/" />
</form>

あとはJSで下記のinputのvalueに値を入れて送信するコードを書いてあげればうまく動作します。

formタグなので送信する必要がありますのでJavaScriptを使って値を送信しています


<script>
  //クリック時にformを送信
  function updateCountry(isoCode) {
    document.getElementById("country_code_hidden").value = isoCode;
    document.querySelector("localization-form form").submit();
  }

  document.addEventListener("DOMContentLoaded", function() {
    const titleElement = document.querySelector(".c_currency-title");
    const listElement = document.querySelector(".c_currency-list");
    
    titleElement.addEventListener("click", function(event) {
      event.stopPropagation();
      listElement.classList.toggle("show");
    });
    
    document.addEventListener("click", function(event) {
      if (!listElement.contains(event.target)) {
      listElement.classList.remove("show");
      }
    });
  });
</script>

Dawnだとこの記述でも動きます



{{ 'component-localization-form.css' | asset_url | stylesheet_tag: preload: true }}

{%- if  localization.available_countries.size > 1 -%}
  <localization-form class="header__icons--localization" >
    {%- form 'localization', id: 'HeaderCountryForm', class: 'localization-form' -%}
      <div>
        <h2 class="visually-hidden" id="HeaderCountryLabel">{{ 'localization.country_label' | t }}</h2>
        {%- render 'country-localization', localPosition: 'HeaderCountry' -%}
      </div>
    {%- endform -%}
  </localization-form>
{% endif %}

<script src="{{ 'localization-form.js' | asset_url }}" defer="defer"></script>
 

こちらも適宜CSSでデザインを調整していただければと思います。

※Dawnのバージョンによってはうまく動かない可能性があるのでご注意ください

form用のCSSとJavaScriptを読み込んでいるんだなーと思っていただければ少しは理解ができるかと

通貨形式は非推奨

通貨形式は非推奨となり、ローカライズ形式に置き換えられました。

通貨形式がcurrencyを使ったものローカライズ形式はlocalizationを使ったものです!
今回紹介したものはローカライズ形式を使っていますのでご安心ください



{% form 'currency' %}
  form_content
{% endform %}

currencyオブジェクトを使った通貨セレクターは非推奨となっていますのでご注意くださいね!

一応動きはしますがいつ使えなくなるかわからないので使わない事に越したことはないかと。。

参考サイト

まとめ

formを使った実装ができるようになると通貨セレクターだけではなく

カート周り、アカウント周り、お問い合わせのカスタマイズができるようになりますのでぜひ一度触ってみてください!

一旦はコピペで動きを見てみて
その後、記事を深く読んでみたり色々とググってみたりと色々といじいじしてみて下さい

localizationフォームタグ
localizationオブジェクト
Back to blog