SEROKUを支える技術 Angular Tips編 その3

  • このエントリーをはてなブックマークに追加

SEROKUフリーランスを技術。Angular Tips編 その3について

さて、今回は前回予告したとおり ng-content を使った、テンプレートに対して外部から子要素を突っ込むような処理を書いてみようかと思います。

Angularに置いてあまりサンプル記事がない印象ですが、使い方さえ覚えておけばきっと役に立つはずです!

Tips4 :ng-contentを使った子要素への注入

ng-contentとは、作成したコンポーネントに対して外部から要素を注入するときに使うタグです。

ng-contentを使ったシンプルな例

まずは一番簡単な例を、コードベースで書いていきたいと思います。

    • selector: ‘foo’ とするFooコンポーネントを定義
      
      <div>
        <h1>header要素</h1>
        <!-- 以下ng-contentを配置し、外部から注入するための要素を宣言 -->
        <ng-content></ng-content>
      </div>
      
    • 外部のコンポーネントでfooを呼び出し、さらに要素を注入
      
          <foo>
            <div>test</div>
            <span>test2</span>
          </foo>
      
      
      

 

    • 上記のfooコンポーネントを呼び出した結果のhtml
      
          <div>
            <h1>header要素</h1>
            <!-- angularによって展開され、fooタグに書いたタグが全てng-contentに展開される -->
            <div>test</div>
            <span>test2</span>
          </div>
      

fooタグ内部に書いた要素が、まるまるng-contentと置き換わりますね。
上記の簡単な例を実装する上ではうまくいきましたが、では複数の要素を別々の場所に注入したい場合はどうすればよいでしょう?

ng-contentを使い複数の要素を注入する例

ng-contentではselectアトリビュートを使い、注入するコンテンツを指定することができます。
以下のコードで複数の要素を注入したいと思います。

    • selector: ‘foo’ とするFooコンポーネントを定義
      
      <div>
        <!-- ng-contentを宣言(selectでh1を指定) -->
        <ng-content select="h1"></ng-content>
        <!-- ng-contentを宣言(selectで.headerを指定) -->
        <ng-content select=".header"></ng-content>
        <!-- 以下ng-contentを宣言(select無し) -->
        <ng-content></ng-content>
      </div>
      
    • 外部のコンポーネントでfooを呼び出し、さらに要素を注入
      
          <foo>
            <h1>test</h1>
            <div class="header">test2</div>
            <div>test3</div>
            <span>test4</span>
          </foo>
      
    • 上記のfooコンポーネントを呼び出した結果のhtml
      
          <div>
            <!-- selectでh1を指定しているのでh1タグの要素が展開される -->
            <h1>test</h1>
            <!-- selectで.headerを指定しているのでheaderクラスを指定した要素が展開される -->
            <div class="header">test2</div>
            <!-- 上記指定に当てはまらないタグが全てng-contentに展開される -->
            <div>test3</div>
            <span>test4</span>
          </div>
      

fooタグ内部に書いた要素の中で、Fooコンポーネントのng-contentのselectで指定した箇所にそれぞれ置き換わりますね。
ちなみに、上記の例で言うとh1タグが複数あった場合、またはheaderクラスが複数あった場合でも、selectにマッチする要素分ng-contentは置き換わります。

ng-contentを使った例 応用編

上記の例はあくまでただの使い方の例だったので、どういう時に役に立つかをユースケースを交えながら書いていきたいと思います。
一つの例として、コンポーネントを作る際に、あるボタンイベントを親コンポーネントにEventEmitterを使って通知し、実際の処理は親コンポーネントでやらせているケースがあるとします。

  • selector: ‘foo’ とするFooコンポーネントを定義
    // テンプレート側
    <div>
      <button (click)="clickHandler()"></button>
    </div>
    
    
    // コンポーネント側
    @Output()
    onClicked = new EventEmitter();
    
    clickHandler() {
        onClicked.emit();
    }
    
  • 外部のコンポーネントでfooを呼び出しonClickedに対してイベントハンドラを仕掛けている
    // テンプレート側
    <foo (onClicked)="clickHandler()" ></foo>
    
    
    // コンポーネント側
    clickHandler() {
        // 実際の処理
    }
    

    Fooコンポーネント側のclickHandlerで、なにか特別なことをしているのなら別ですが、ただemitしているだけならば以下のように書いたほうが、Fooコンポーネントはロジックを気にせずにただのViewテンプレートとしての役割に専念できるので見通しが良いです。

  • selector: ‘foo’ とするFooコンポーネントを定義
    // テンプレート側
    <div>
      <ng-content select="button"></ng-content>
    </div>
    
    
    // コンポーネント側
    処理がなくなる!!
    
  • 外部のコンポーネントでfooを呼び出しclickハンドラを設定しているbuttonタグを要素として注入
    // テンプレート側
    <foo>
        <button (click)="clickHandler()"></button>
    </foo>
    
    
    // コンポーネント側
    clickHandler() {
        // 実際の処理
    }
    

    上記は一例に過ぎませんが、同じような状況は結構ある気がします。
    これ使ったほうがコードがキレイになりそうというのがもしあれば試してみると良いかもしれません。

まとめ

今回は ng-content に関して書きました。
前回の記事でngTemplateOutlet にも少し触れましたが、ある特定の要素を置き換えるという場合にも複数のやり方がありますね。
(もちろんそれぞれで適切な使い所は異なりますが)

吐き出したいネタが一旦尽きてしまったので、なにか思いついたらまたアップしたいと思います。
それでは皆さんごきげんよう。

 

SEROKUを支える技術 ~開発準備編~
SEROKUを支える技術~プロジェクト管理編~
SEROKUを支える技術~社内 Kubernetes 編~
SEROKUを支える技術~CI/CD編~
SEROKUを支える技術~社内 Kubernetes トラブルシュート前編~
SEROKUを支える技術 Angular Tips その1
SEROKUを支える技術 Angular Tips その2
SEROKUを支える技術 Angular Tips その3

 

SEROKU新規フリーランスエンジニア・プログラマ登録促進バナー

SEROKU新規フリーランスエンジニア・プログラマ登録促進バナー

SNSでもご購読できます。