カスタムエレメンツ

ここまで、(1)JavaScript から Elm のプログラムを起動する方法を、(2)初期化の際にデータを フラグ として渡す方法を、(3)ポート を使用して Elm と JavaScript の間でメッセージを送り合う方法を見てきました。けれど、知っていますか?他にも連携を行う方法があります!

ブラウザは カスタムエレメンツ のサポートを進めており、これは JavaScript と Elm の連携にとても役立ちます。

Webページのローカライズと国際化を題材に、カスタムエレメンツを使う最小限の例を見てみましょう。

カスタムエレメンツの作成

日付データを地域ごとの固有の表記にローカライズしたいとき、残念ながらまだElmの主要なパッケージにはそのAPIがありません。そこで、こんな関数を作ったとしましょう。

//
//   localizeDate('sr-RS', 12, 5) === "петак, 1. јун 2012."
//   localizeDate('en-GB', 12, 5) === "Friday, 1 June 2012"
//   localizeDate('en-US', 12, 5) === "Friday, June 1, 2012"
//
function localizeDate(lang, year, month)
{
    const dateTimeFormat = new Intl.DateTimeFormat(lang, {
        weekday: 'long',
        year: 'numeric',
        month: 'long',
        day: 'numeric'
    });

    return dateTimeFormat.format(new Date(year, month));
}

Elmからこれを使うにはどうすればいいのでしょうか? 最近のブラウザを使うと、こんなふうにして新しい種類のDOMノードを作ることができます。

//
//   <intl-date lang="sr-RS" year="2012" month="5">
//   <intl-date lang="en-GB" year="2012" month="5">
//   <intl-date lang="en-US" year="2012" month="5">
//
customElements.define('intl-date',
    class extends HTMLElement {
        // カスタムエレメンツを使うために必要な定義です
        constructor() { super(); }
        connectedCallback() { this.setTextContent(); }
        attributeChangedCallback() { this.setTextContent(); }
        static get observedAttributes() { return ['lang','year','month']; }

        // 属性の値を使って`textContent`を更新します
        setTextContent()
        {
            const lang = this.getAttribute('lang');
            const year = this.getAttribute('year');
            const month = this.getAttribute('month');
            this.textContent = localizeDate(lang, year, month);
        }
    }
);

何より重要なところはattributeChangedCallbackobservedAttributesです。これは、特定の属性に注目し、その値が変更されたときに検知するための仕組みです。

Elmを初期化するよりも前にこのコードを読み込んでおくと、Elmからこんなふうに利用できます。

import Html exposing (Html, node)
import Html.Attributes (attribute)

viewDate : String -> Int -> Int -> Html msg
viewDate lang year month =
  node "intl-date"
    [ attribute "lang" lang
    , attribute "year" (String.fromInt year)
    , attribute "month" (String.fromInt month)
    ]
    []

viewの中でローカライズした日付を表示したいときは、viewDateを呼ぶだけでよくなりました。

この例の完全版はここから確認できます。

追加情報

Luke Westbyはカスタムエレメンツの経験が豊富です。彼のElm Europeでの発表は、カスタムエレメンツを紹介する最高の資料です!

カスタムエレメンツのドキュメントにはわかりづらいところもありますが、Intlのような小さな機能をElmに組み込むのに必要な知識はこれだけです。そして、もしあなたの作りたいものに必要だと思うなら、同じ方法で大きなReactのウィジェットを組み込むこともできるのです。

results matching ""

    No results matching ""