まだコンポーネント化もできていない状態。
ある程度の形ができたら、要素を解説しつつまとめる予定。
app.module.ts
import { BrowserModule } from '@angular/platform-browser';
import { NgModule } from '@angular/core';
import { FlexLayoutModule } from '@angular/flex-layout';
import { MatButtonModule } from '@angular/material/button';
import { MatFormFieldModule } from '@angular/material/form-field';
import { MatInputModule } from '@angular/material/input';
import { MatMenuModule } from '@angular/material/menu';
import { MatSelectModule } from '@angular/material/select';
import { MatSidenavModule } from '@angular/material/sidenav';
import { MatIconModule } from '@angular/material/icon';
import { MatToolbarModule } from '@angular/material/toolbar';
import { MatListModule } from '@angular/material/list';
import { MatTreeModule } from '@angular/material/tree';
import { AppComponent } from './app.component';
import { BrowserAnimationsModule } from '@angular/platform-browser/animations';
@NgModule({
declarations: [
AppComponent,
],
imports: [
BrowserModule,
BrowserAnimationsModule,
FlexLayoutModule,
MatButtonModule,
MatFormFieldModule,
MatInputModule,
MatMenuModule,
MatSelectModule,
MatSidenavModule,
MatIconModule,
MatToolbarModule,
MatListModule,
MatTreeModule,
],
providers: [],
bootstrap: [AppComponent]
})
export class AppModule { }
app.component.html
<mat-toolbar color="primary">
<mat-toolbar-row>
<button mat-icon-button>
<mat-icon (click)="drawer.toggle()">menu</mat-icon>
</button>
<h1>SITE</h1>
<span class="menu-spacer"></span>
<div>
</div>
</mat-toolbar-row>
</mat-toolbar>
<mat-drawer-container class="sidenav-container">
<mat-drawer #drawer class="sidenav" fixedInViewport="true"
[attr.role]="'dialog'"
[mode]="'over'"
[opened]="!(isHandset$ | async)"
>
<mat-toolbar>Menu</mat-toolbar>
<mat-nav-list>
<mat-tree [dataSource]="dataSource" [treeControl]="treeControl" class="example-tree">
<!-- This is the tree node template for leaf nodes -->
<mat-tree-node *matTreeNodeDef="let node" matTreeNodeToggle>
<li class="mat-tree-node">
<!-- use a disabled button to provide padding for tree leaf -->
<button mat-icon-button disabled></button>
{{node.name}}
</li>
</mat-tree-node>
<!-- This is the tree node template for expandable nodes -->
<mat-nested-tree-node *matTreeNodeDef="let node; when: hasChild">
<li>
<div class="mat-tree-node">
<button mat-icon-button matTreeNodeToggle
[attr.aria-label]="'Toggle ' + node.name">
<mat-icon class="mat-icon-rtl-mirror">
{{treeControl.isExpanded(node) ? 'expand_more' : 'chevron_right'}}
</mat-icon>
</button>
{{node.name}}
</div>
<ul [class.example-tree-invisible]="!treeControl.isExpanded(node)">
<ng-container matTreeNodeOutlet></ng-container>
</ul>
</li>
</mat-nested-tree-node>
</mat-tree>
</mat-nav-list>
</mat-drawer>
<mat-drawer-content>
<div fxLayout="column" style="height:calc(100vh - 128px)">
<div fxFlex="48px" class="v-center" style="background-color: royalblue">
<ng-container *ngFor="let link of links">
<a href="#"><span>{{link}}</span></a>
</ng-container>
</div>
<div fxFlex class="v base">
<ng-container *ngTemplateOutlet="pack; context:args"></ng-container>
</div>
</div>
</mat-drawer-content>
</mat-drawer-container>
<ng-template #pack let-class="class" let-params="list">
<div [class]="class">
<ng-container *ngFor="let param of params">
<ng-container [ngSwitch]="param">
<ng-container *ngSwitchCase="'i'"><ng-container *ngTemplateOutlet="input"></ng-container></ng-container>
<ng-container *ngSwitchCase="'b'"><ng-container *ngTemplateOutlet="button"></ng-container></ng-container>
<ng-container *ngSwitchDefault><ng-container *ngTemplateOutlet="pack; context:param"></ng-container></ng-container>
</ng-container>
</ng-container>
</div>
</ng-template>
<ng-template #input>
<div class="b">
<span class="l"><label for="cheese">ラベル</label></span>
<span class="i"><input name="cheese" value="インプットエリア"></span>
</div>
</ng-template>
<ng-template #button>
<div class="b">
<button mat-button color="primary">確定</button>
</div>
</ng-template>
app.component.css
a {
display: flex;
justify-content: left;
align-items: center;
border-radius:0px;
width: 100px;
height:100%;
background: linear-gradient(to right, royalblue, royalblue 10%, skyblue);
}
a::before{
content: "";
width:18px;
}
a::after{
content: "";
width:24px;
height:48px;
position: relative;
left:20px;
background:linear-gradient(to bottom left, royalblue 50%, transparent 50%) top left/ 100% 50% no-repeat,
linear-gradient(to top left, royalblue 50%, transparent 50%) bottom left / 100% 50% no-repeat;
z-index: 1;
}
div.base {
background-color:lightslategray;
padding:5px;
}
div.area {
background-color:lightgray;
padding:5px;
}
div.v {
display: flex;
flex-direction: column;
width:100%;
}
div.h {
display: flex;
flex-direction: row;
width:auto;
}
div.b {
display: flex;
border-color:transparent;
border-width:0.5px;
border-style:solid;
height:40px;
width:100%;
}
div.v div.h div.b+div.b{
margin-left: 5px;
}
div.h div.v div.b+div.b{
margin-left: 0px;
}
div.v+div.v{
margin-left: 5px;
}
.area div.v+div.v{
margin-left: 15px;
}
div.h+div.h{
margin-top: 5px;
}
.v-center {
display: flex;
align-items: center;
padding-left:25px;
}
span.l {
display: flex;
justify-content: center;
align-items: center;
background-color:royalblue;
padding:1px;
height:38px;
width:100px;
min-width:100px;
}
span.i {
display: flex;
justify-content: center;
align-items: center;
background-color:aliceblue;
padding:1px 3px;
height:38px;
width:100%;
}
input {
border-width:1px;
border-color:white;
border-style:inset;
height:35px;
width:100%;
}
label {
color:white;
}
.sep {
height:10px;
width:10px;
}
@media screen and (max-width: 640px) {
div.h {
flex-wrap: wrap;
}
div.v+div.v {
margin-left: 0px;
}
div.v div.h div.b+div.b{
margin-left: 0px;
}
.area div.v+div.v{
margin-left: 0px;
}
}
.example-tree-invisible {
display: none;
}
.example-tree ul,
.example-tree li {
margin-top: 0;
margin-bottom: 0;
list-style-type: none;
}
app.component.ts
import { Component } from '@angular/core';
import { BreakpointObserver, Breakpoints } from '@angular/cdk/layout';
import { NestedTreeControl } from '@angular/cdk/tree';
import { MatTreeNestedDataSource } from '@angular/material/tree';
import { Observable } from 'rxjs';
import { map } from 'rxjs/operators';
interface FoodNode {
name: string;
children?: FoodNode[];
}
const TREE_DATA: FoodNode[] = [
{
name: 'Fruit',
children: [
{name: 'Apple'},
{name: 'Banana'},
{name: 'Fruit loops'},
]
}, {
name: 'Vegetables',
children: [
{
name: 'Green',
children: [
{name: 'Broccoli'},
{name: 'Brussels sprouts'},
]
}, {
name: 'Orange',
children: [
{name: 'Pumpkins'},
{name: 'Carrots'},
]
},
]
},
];
interface Container {
layout: string;
children?: Container[];
}
@Component({
selector: 'app-root',
templateUrl: './app.component.html',
styleUrls: ['./app.component.css']
})
export class AppComponent {
title = 'ng-test';
links = ["LINK1", "LINK2", "LINK3"]
v(...params:any[]):any {
return {class:"v", list:params}
}
h(...params:any[]):any {
return {class:"h", list:params}
}
va(...params:any[]):any {
return {class:"v area", list:params}
}
ha(...params:any[]):any {
return {class:"h area", list:params}
}
args =
this.v(
this.h(
this.va("i","i","i","i"),
this.va("i","i","i"),
),
this.ha(
this.v(
"i","i","i"
),
this.v(
"i","i","i","i"
),
),
this.ha(
"i","i","i"
),
this.h(
this.va(
this.h("i","b"),
"i","i"
)
)
)
isHandset$: Observable<boolean> = this.breakpointObserver.observe(Breakpoints.Handset)
.pipe(
map(result => result.matches)
);
constructor(private breakpointObserver: BreakpointObserver) {
this.dataSource.data = TREE_DATA;
}
treeControl = new NestedTreeControl<FoodNode>(node => node.children);
dataSource = new MatTreeNestedDataSource<FoodNode>();
hasChild = (_: number, node: FoodNode) => !!node.children && node.children.length > 0;
}
サーバにあるテキストをマスタとした連想配列を提供するサービス
import { Injectable } from '@angular/core';
import { HttpClient } from '@angular/common/http';
import { Observable } from 'rxjs';
import { map } from 'rxjs/operators';
@Injectable({
providedIn: 'root'
})
export class MapService {
nameMap:Observable<{[name: string]: string}>
constructor(private http: HttpClient) {
let url = "../assets/sample.txt"
this.nameMap = this.http.get(url, {responseType:'text'}).pipe(map(data => {
return data.split('\n')
.map(x => x.split("="))
.reduce((map, arr) => ({
...map,
[arr[0]]: arr[1]
}), {});
}));
}
getValue(name) {
return this.nameMap.pipe(map(x => x[name]))
}
}