孤独プログラマー譚

孤独死が近い。

JavaScript Promise.thenメソッドの返却値

asyncメソッドと似たような考え方でいいと思う。

const promise = new Promise(resolve => resolve())

const foo = promise.then(async () => {
  await new Promise(resolve => {
    setTimeout(resolve, 1000)
  })
  return 'foo_value'
})

const bar = promise.then(() => {
  return new Promise(resolve => {
    setTimeout(() => {
      resolve('bar_value')
    }, 2000)
  })
})

foo.then((res) => console.log(res)) // 1秒後にfoo_value
bar.then((res) => console.log(res)) // 2秒後にbar_value

Promiseオブジェクトをreturnすると、そのままそのPromiseオブジェクトがthen()の返却値となる。
Promiseオブジェクト以外をreturnすると、Promiseでラッピングされて返却される。

JavaScript Promiseとasyncの書き換え

以下の2つ、Promiseとasyncメソッドは書き換えられる。

foo() {
  return new Promise((resolve) => {
    setTimeout(() => {
      resolve('foo_value')
    }, 1000)
  })
}
async bar() {
  await new Promise((resolve) => {
      setTimeout(resolve, 1000)
  })
  return 'bar_value'
}


メソッドから返却されたPromiseオブジェクトはawaitできる。
asyncメソッドの返却値もPromiseオブジェクトとなる。

const val1 = await this.foo()
console.log(val1) // foo_value
const val2 = await this.bar()
console.log(val2) // bar_value


awaitでなく、then()メソッドでも対応できる。
asyncメソッドの返却値(Promiseオブジェクト)からthen()メソッドを使用することもできる。

const promise1 = this.foo()
promise1.then(val => console.log(val)) // foo_value
const promise2 = this.bar()
promise2.then(val => console.log(val)) // bar_value

Angular ルーティング

ルーティングの最低限の構成。

/* app-routing.module.ts */

import { NgModule } from '@angular/core';
import { Routes, RouterModule } from '@angular/router';
import { FooComponent } from './foo/foo.component';

const routes: Routes = [
  { path: 'foo', component: FooComponent }
];

@NgModule({
  imports: [RouterModule.forRoot(routes)],
  exports: [RouterModule]
})
export class AppRoutingModule { }

router-outlet の部分に出力される。

<!-- app.component.html -->

<router-outlet></router-outlet>

Angular FormControl

FormGroup を使わないパターン。

export class AppComponent {
  foo = new FormControl('foo-desu', [
    Validators.required,
  ])
}
<input [formControl]="foo">
<div>value: {{foo.value}}</div>
<div>error: {{foo.errors | json}}</div>


FormGroup を使うパターン。

export class AppComponent {
  constructor(private builder: FormBuilder) {}
  foo = new FormControl('foo-desu', [
    Validators.required,
  ])
  metaForm = this.builder.group({
    foo: this.foo
  })
}
<form [formGroup]="metaForm">
<input [formControl]="foo">
<div>input_value: {{foo.value}}</div>
<div>input_error: {{foo.errors | json}}</div>
<div>form_value: {{metaForm.controls.foo.value}}</div>
<div>form_error: {{metaForm.controls.foo.errors | json}}</div>
</form>

Angular バリデーションエラー表示

ngModel経由なら、input要素のvalue, error とも取得できる。

<input #foo="ngModel" [(ngModel)]="metas.foo" required>
<div>value: {{foo.value}}</div>
<div>error: {{foo.errors?.required}}</div>
export class AppComponent {
  metas = {
    foo: '',
    bar: '',
    baz: '',
  }
}

ngForm経由では、input要素のvalueは取得できても、errorは取得できないっぽい。
(Form全体のエラーは取得できる。)

<form #metaForm="ngForm">
<input name="foo" [(ngModel)]="metas.foo" required>
</form>
<div>value: {{metaForm.value.foo}}</div>
<div>error: {{metaForm.invalid}}</div>

Angular 全て入力後に送信可能になるボタン 2

f:id:halation-summer:20191222145353g:plain
formを使わないバージョン。応用は効かせやすいかも。

<input [(ngModel)]="metas.foo"><br>
<input [(ngModel)]="metas.bar"><br>
<input [(ngModel)]="metas.baz"><br>
<br>
<div>disabled: {{disabled}}</div>
<button [disabled]="disabled">Submit</button>
export class AppComponent {
  metas = {
    foo: '',
    bar: '',
    baz: '',
  }
  get disabled() {
    if (this.metas.foo !== ''
    && this.metas.bar !== ''
    && this.metas.baz !== ''
    ) { return false }
    return true
  }
}

Angular 全て入力後に送信可能になるボタン 1

f:id:halation-summer:20191222141419g:plain
Vue.jsに続いて、Angularでも。
テキストフィールドに全て入力完了後、disabledが解除されて送信可能になるボタン。

<form #metaForm="ngForm">
<input name="foo" [(ngModel)]="metas.foo" required><br>
<input name="bar" [(ngModel)]="metas.bar" required><br>
<input name="baz" [(ngModel)]="metas.baz" required><br>
<br>
<div>disabled: {{metaForm.invalid}}</div>
<button [disabled]="metaForm.invalid">Submit</button>
</form>
export class AppComponent {
  metas = {
    foo: '',
    bar: '',
    baz: '',
  }
}

name属性をつけないと、うまく動かないっぽい。