ntaoo blog

主にDart, Flutter, AngularDartについて書いていきます。ときどき長文。日本語のみ。Twitter: @ntaoo

AngularDartの、Angular Componentsの使い方

フルスクラッチでUIを構築していくのは現実的ではない。現代のUIに対する要求水準の高さに応えるために決定的に重要な要素として、UIライブラリの質がある。

Angular TypeScript版にAngular Materialライブラリが提供されているように、AngularDartにはpackage:angular_componentsが提供されている。このパッケージは、マテリアルデザインのUIを構築するためのさまざまなUI部品がAngularのComponentとしてまとめられ、またUIテーマやスタイリングのためのSCSSが同梱されている。AngularDartでUIを構築するならば、素直にマテリアルデザインを採用するべきだ。

Angular TypeScript版のAngular Materialのサイトと比較して、AngularDartのpackage:angular_componentsのサイトは地味なので、誤解されることもあるかもしれない。そこで、ここではpackage:angular_componentsの使い方を解説していく。

特徴

使用方法

セットアップ

セットアップ方法については、他のdart packageと同じくREADMEを参照する。 https://pub.dartlang.org/packages/angular_components

SCSSのビルド用にpackage:sass_builderが必要。

表示

たとえば、MaterialButtonの場合は、 import 'package:angular_components/material_button/material_button.dart';とインポートして、 @Componentアノテーションdirectives名前付き引数にリストとしてMaterialButtonComponentを指定する。

import 'package:angular/angular.dart';
import 'package:angular_components/material_button/material_button.dart';

@Component(
  selector: 'buttons',
  templateUrl: 'buttons.html',
  directives: [MaterialButtonComponent],
)
class ButtonsExampleComponent {}

そして、Templateにカスタムタグを書けば表示される。

<material-button>Default</material-button>

ほとんどのタグにはmaterial- prefixがつけられている。 いくつかのComponentでは、directivesへの登録に加えてprovidersへの登録が必要。

使い方が分からなければ、各componentの使用例を参照する。 例えば、MaterialButtonの場合は、 https://dart-lang.github.io/angular_components/#/material_buttonと、そこからリンクされているソースコード https://github.com/dart-lang/angular_components/blob/master/examples/material_button_example/lib/material_button_example.dartを読んで理解する。

レイアウト

アプリのレイアウトをスクラッチで書くのは地味に面倒でバグが発生しやすい。そのため、https://dart-lang.github.io/angular_components/#/app_layoutマテリアルデザインのレイアウトを構築する方法について解説されている。Flutterのようなscaffold widgetだったり<app-layout></app-layout>というコンポーネントがあるわけではない。複数のComponentやscss stylingを組み合わせる形。

ささいなUI部品はComponentでなくSCSSだけで表現

FlutterではすべてがWidgetであったりやTS版AngularのAngularMaterialがささいなUI部品でもComponentで表現しているのとは異なり、package:angular_componentsでは、ComponentにせずSCSSで表現するものもある。たとえば、MaterialCardやDividerといったもの。


MaterialCardについては、以下のようにmdc-cardのscssを指定して表現している。

https://dart-lang.github.io/angular_components/#/material_card https://github.com/dart-lang/angular_components/blob/master/examples/material_card_example/lib/material_card_example.html


Dividerについては、ギャラリーにセクションは設けられていないが、そのようなささいなものはpackage:angular_componentsが提供するColor関係の変数を用いて、

@import 'package:angular_components/css/material/material';

.divider {
  display: flex;
  width: 100%;
  border-bottom: 1px solid $mat-border-light;
}

このように定義するだけでよい。

<div class="divider">

残念ながらFlutterやAngularMaterialほどのコードの統一感はないが、おそらく実行性能を重視した結果だと思う。

スタイリング

マテリアルデザインのためのスタイリング用のSCSS変数やMixinが用意されている。基本的に、以下をimportして変数を使用する。

@import 'package:angular_components/css/material/material';

*注) sass-builderdart-sassに依存している。dart-sassは、Dartのpackage urlをサポートしているため、上記のpackage:angular_components/の指定は有効。

これにより、

// How to use me:
//
// This set of scss files should never output any css unless sass classes are
// extended in the importing file. This allows you to import _material without
// bloating the css files for your components. All variables and components
// within the material stylesheet are prefixed with "mat-" in order to give a
// clear distinction between them and the styles in components that are using
// these material styles.
//
// Example:
//
// small-example.scss
//     @import "package:angular_components/css/material/material";
//
//     .my-app {
//       background-color: $mat-blue-700;
//     }

@import 'color_palette_material';
@import 'color_material';
@import 'core_material';
@import 'elevation_material';
@import 'scrollbar_material';
@import 'transition_material';
@import 'typography_material';

が有効となる。これらでマテリアルデザインガイドラインで定義されたスタイリングは一通り定義されているはずなので、ここから必要となる変数を利用していく。以下、例で説明する。

テーマカラー

例えば、アプリのテーマカラーを指定するには、

$primary-color: map-get($mat-teal-map, $teal-number);
$secondary-color: $mat-light-green-400;

といった具合に書き、各コンポーネントのSCSSで提供されているmixinなどで指定していく。

Elevation

すべてSCSSで定義されており、使用方法もelevation_materialソースコードのコメントに書かれている。

/// Applies the Material Shadow styles to the selected element.
///
/// Use the attributes below to control the shadow.
///
/// - `animated` -- Whether to animate the shadow transition.
/// - `elevation` -- Z-elevation of shadow. Valid Values: 1,2,3,4,5
///
/// Example:
///
///     .shadow-box {
///       @include material-shadow();
///     }
///
///     <div class="shadow-box" animated elevation="3">...</div>

その他の要素

フォントサイズ、リンクスタイル、マージンなど、一通りのスタイルが定義されているので、マテリアルデザインガイドラインに従うためには、marginをアドホックに指定したりアプリ独自に変数を定義するのではなく、上記で説明したように@import "package:angular_components/css/material/material";を用いて定義された変数を探して適用していくことが基本となる。

各UIコンポーネントへのテーマの適用などのカスタマイズ

MaterialButtonなどの各UIコンポーネントには、テーマの適用などのカスタマイズ方法として、SCSSのmixinなどを用意されている。たとえば、MaterialButtonならば、material_button/_mixins.scssなど。

例:

$primary-color: map-get($mat-teal-map, $teal-number);
$secondary-color: $mat-light-green-400;

@mixin button-mixin {
  $selector: 'material-button';
  @include button-color($selector, $primary-color);
}

@mixin input-mixin {
  @include material-input-theme($primary-color);
}

UI Componentごとに説明されている。

サードパーティマテリアルデザインPackage

FlutterのWidgetの充実度と比べると、package:angular_componentsでサポートしているUI部品の種類は相対的に少ない。不足している部品はスクラッチで作ってしまうのも良いが、サードパーティのものを利用することも検討する。例えば、package:skawa_material_components

https://pub.dartlang.org/packages/skawa_material_components

以下の部品が提供されている。

  • <skawa-data-table>
  • <skawa-grid>
  • <skawa-snackbar>

まとめ

Dartソースコードの可読性がとても高いしDoc Commentも充実しているので、PackageのソースコードとDoc Commentを読む習慣があれば上記の情報はすぐに把握できる。しかし、AngularDartに興味をもった段階でその関連ソースコードを読む、というのもハードルが高いので、AngularDartへの理解の促進と誤解を解くための一助として、この解説を書いた。

不明点や疑問点は、以下のチャンネルなどで質問を投げてくれたら解答したい。

公式ガイド