とりあえずCustom elementsを作りたい

# はじめに
　私は研究や仕事でWeb Componentsに関する技術を使っているわけではなく、プロではないのですが「とりあえず使ってみたい！」と思って使ってみました。
　本記事は「技術的なことは追々わかるとして、とりあえず動くものを作りたい！」という人向けです。
　日本語で結構、技術的なことを分かりやすくまとめてくださっている記事は [初心者向けWebComponentsまとめ](https://qiita.com/s-yoshida/items/056c23b1dc25e0ac7555) にあります。「初心者向けWebComponentsまとめ」ではライフサイクルなどにも触れていますが、 **本記事はHTML5のタグをペタペタ貼って、一つのElementを作ってみよう！** というものです。
　Qiitaに、この先書き続けるか分からないので、[自分のウェブサイト](https://sites.google.com/alumni.tsukuba.ac.jp/akira/study/webcomponents) にも同じ内容を書いています。こちらは、これからWebcomponentsについての知識が増えれば、随時更新しまとめていきますので、よければ参照してください。逆に言えば、この記事は誤植や誤りの訂正以外は書きっぱなしになります。

# 用意するファイル
用意するファイルは以下の2つです。適当なディレクトリに適当なディレクトリ（今回はwebcomponentsにしています）を作成してください。
Custom Elementは全てjavascriptで記述します。その記述されたCustom ElementをHTMLファイルで利用するという流れです。

```
webcomponents/
    |- index.html
    |- example-template.js
```

# コードと解説
それぞれのファイルとコードについて解説をします。

HTMLファイルで重要なのは、Custom Elementを引っ張ってくるときに'defer'を入れないと、正しく動かないことです。javascriptを参照するときに、必ず入れましょう。

```html:index.html
<!DOCTYPE html>
<html lang='en'>

<head>
  <meta http-equiv='Content-Type' content='text/html; charset=UTF-8'>
  <script type="text/javascript" src="./example-template.js" defer></script> <!--　Custom Elementを引っ張ってくる "defer"　を書かないと動かない  -->
  <title>custom elements example</title>
</head>

<body>
  <!-- Custom Elementの利用。nameTitleとplaceHolderは作成した新しい属性（Attribute） -->
  <example-template nameTitle="Text form" placeHolder="Please type your name"></example-template>
  <example-template nameTitle="Text form2" placeHolder="複数elementを使っても、きちんと別々に文字が入る。"></example-template>
</body>

</html>
```

```javascript:example-template.js
class ExampleTemplate extends HTMLElement {
    constructor() {
        // superは必ず一番最初に呼び出される。
        super();
        // これより下にCustom Elementに関する記述を行う

        //shadow rootの作成。これが今回の一番上のノード（ルート）
        const shadow = this.attachShadow({ mode: 'open' });

        // 今回はひとまとまりをsectionで包む
        const wrapper = document.createElement('section');

        //* Sectionの下に並べるElementsの情報を入れていく *//
        // h2タグ（タイトル）
        const subtitle = document.createElement('h2');
        const titleSub = this.getAttribute('nameTitle');    // nameTitleというAttributeの値を取得
        subtitle.textContent = titleSub;                    // nameTitleの値をh2タグで表示

        // form & input (テキストフィールド)
        const formF = document.createElement('form');
        const textField = document.createElement('input');

        textField.setAttribute('type', 'text');             // inputのtype指定
        textField.setAttribute('class', 'textField');       // classをtextFieldに
        const contents = this.getAttribute('placeHolder');  // placeHolderというAttributeの値を取得
        textField.setAttribute('placeholder', contents);    // input(type=text)のplaceholderにplaceHolderの値を代入
        formF.appendChild(textField);                       // formの下にtextFieldをネストする

        // Shadow domにCSSを適用する
        const style = document.createElement('style');
        console.log(style.isConnected);
        style.textContent = `
        .textField {
            width: 500px;
            height: 300px;
        }
        `;                                                  //今回はtextFieldの幅と高さを指定した。

        // shadow domを一番上にして、上で作ったものをネストしていく
        // shadow |- style
        //        |- wrapper |- subtitle
        //                   |- formF
        shadow.appendChild(style);
        shadow.appendChild(wrapper);
        wrapper.appendChild(subtitle);
        wrapper.appendChild(formF);
    }
}
// 新しいElementの定義
customElements.define('example-template', ExampleTemplate);


```

# 実際に表示される画面
<img width="629" alt="スクリーンショット 2020-06-28 23.19.23.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/81253/1edb0a48-7027-799f-ef03-251c93c1a414.png">

# まとめ
* HTMLとjavascriptでCustom Elementを作った
* 同じelementの同じ属性に異なる入力を入れたところ、表示はきちんと異なるそれぞれの入力値が表示された

# 問合せ
　間違えや「ここ、こうした方がいいよ！」という意見や「詳しく聞きたい！」ということがありましたら、以下のメールアドレスまたは本記事にコメントをお願いします。
akira.kashihara@hotmail.com