使用Angular(和Angular Material)时遇到的困难

总结

因为在开发Angular7的Web应用程序时遇到了许多困难和问题,所以为了以后的警戒,我决定将它们整理成一篇文章。由于在本次开发中我还使用了Angular Material,所以我也想一并记录下在那里遇到的问题。

沉迷的问题和解决方法列表。

无法离开网络的外部

1. 具體明細

在这次开发中,我认为最困难的部分就是这个了。
如果使用了angular-in-memory-web-api,而不知道默认情况下无法访问外部网络,我花了几天的时间与错误战斗。
当我试图在Angular中进行HTTP访问时,出现了「状态:未找到」的错误。

以下是一种与URL访问共存的方法,但基本上在开发中,我认为最好还是创建一个JSON文件,并使用HttpClient访问该文件,以便更容易切换内部测试环境和外部环境。

在Angular2 angular-in-memory-web-api中,可以实现“模拟”和“URL访问”的共存。

在内部环境中,我们曾经按照以下方式进行操作。原本应该只需切换环境以切换与内部和外部的连接,但由于没有调查时间,所以尚未实现。一旦调查完成将在此添加。

  constructor(
    private http: HttpClient,
  ) { }

// ... 省略

const httpOptions = {
  headers: new HttpHeaders({
    'Content-Type': 'json',
  })
};
return this.http.get<ResponseClass>('jsonfile.json', httpOptions);

在页面跳转的情况下,确保在加载页面后不会出现白屏。

如果您使用AppRoutingModule,建议使用navigateByUrl(‘/xxx_link’)而不是href=xxx。我认为在使用AppRoutingModule并在同一网站内导航时,使用navigateByUrl会更好。

我想要将日期进行格式化并显示出来。

我参考了这篇文章,因为它很易懂。关于Angular日期格式化。

关于 DatePipe 的说明和格式选项列表
Angular:DatePipe

1. 使用HTML来指定格式

如果要在html中格式化,不需要在app.module.ts等文件中添加,只需在html中引用Date类型的变量,并指定格式如下。

<div>{{testDate|date:"yyyy年MM月dd日 HH時mm分"}}</div>

2. 使用TypeScript指定格式

在 TypeScript 中指定的方式有两种方法。

在app.module.ts的providers中添加DatePipe,然后在组件中进行导入并使用。

在这种情况下,需要修改app.module.ts文件以及使用到的两个组件。

import { DatePipe } from '@angular/common';

@NgModule({
  // ... 省略
  providers: [DatePipe],
  // ... 省略
})
import { DatePipe } from '@angular/common';

@Component({
  selector: 'module-component',
  templateUrl: './module-component.html',
  styleUrls: ['./module-component.scss']
})
export class ModuleComponent implements OnInit {
  date1 = new Date();
  date2: string;

  constructor(
    private datepipe: DatePipe,
  ) { }

  ngOnInit(): void {
    this.date2 = this.datepipe.transform(this.date1, 'yyyy年M月d日 HH時mm分ss秒');
  }
}

2.2. 在每个组件的@Component中添加providers并包含DatePipe。

需要修改的只是此处使用的组件。

import { DatePipe } from '@angular/common';

@Component({
  selector: 'module-component',
  templateUrl: './module-component.html',
  styleUrls: ['./module-component.scss'],
  providers: [DatePipe]
})
export class ModuleComponent implements OnInit {
  date1 = new Date();
  date2: string;

  constructor(
    private datepipe: DatePipe,
  ) { }

  ngOnInit(): void {
    this.date2 = this.datepipe.transform(this.date1, 'yyyy年M月d日 HH時mm分ss秒');
  }
}

在中国当地,应将DatePipe的提供者设置为哪个方面结局才最好?

如果组件被频繁加载,最好将其添加到app.module.ts(根模块)中,但是当组件较多时,加载时间会变长。要确定是否适用延迟加载,并选择是将其添加到根模块还是各个组件中。

Angular: 提供者

我想要将使用Angular创建的网站部署到GAE。

我参考了这个。
将Angular制作的应用程序部署到Google App Engine上。

我们在这次开发的Web应用中,在构建时指定了ng build –output-path=./server/static,并且使用了Node.js,因此app.yaml的配置如下所示。

runtime: nodejs8

handlers:
- url: /(.*\.(css|gif|png|jpg|ico|js|html|json))
  static_files: static/\1
  upload: static/(.*\.(css|gif|png|jpg|ico|js|html|json))
- url: /(.*)
  static_files: static/index.html
  upload: static/index.html

无法为 Mat-XX 设置 ngModel。

在app.module.ts中import FormsModule

// インポートに追加
import { FormsModule } from '@angular/forms';

@NgModule({
  imports: [
    // ... 省略
    FormsModule,
    // ... 省略
  ],
})
export class AppModule {
  // ... 省略
}

Angular 4错误:无法绑定到ngModel,因为它不是select的已知属性。

在mat-XX上没有动画发生。

在 app.module.ts 中导入 BrowserAnimationsModule 或 NoopAnimationsModule
Angular:Angular动画简介
Angular:Angular Material 入门指南

// インポートに追加
import { BrowserAnimationsModule } from '@angular/platform-browser/animations';
// アニメーションを無効化したい場合はこちらをインポート
import { NoopAnimationsModule } from '@angular/platform-browser/animations';

@NgModule({
  imports: [
    // どちらか一方をimportsに含める
    BrowserAnimationsModule,
    NoopAnimationsModule,
    // ... 省略
  ],
})
export class AppModule {
  // ... 省略
}

角材料中的按钮没有显示出水波效果

我想创建一个没有初始值的mat-select选项

创建一个未确定的[值]的

<mat-form-field floatLabel="never">
  <mat-label>内容を選択</mat-label>
  <mat-select name="selectItem" [(ngModel)]="selectItem">
    <mat-option>未選択</mat-option>
    <mat-option *ngFor="let slt of selectModels" [value]="slt.id">
      {{slt.description}}
    </mat-option>
  </mat-select>
</mat-form-field>

如果按照上述设定,选择mat-select会显示“未选择”选项。

mat-select_default_01.png

如果选择了”未选择”选项,则不会显示项目,而是返回到”选择内容”。

mat-select_default_02.png

我想阻止当选mat-XX项目时placeholder上移。

如果使用 mat-label,请在 mat-form-field 标签内添加 floatLabel=”never”,或者不使用 mat-label,而是使用 placeholder。

<!-- mat-selectの場合はfloatLabel="never" -->
<mat-form-field floatLabel="never">
  <mat-label>内容を選択</mat-label>
  <mat-select name="selectItem" [(ngModel)]="selectItem">
    <mat-option>未選択</mat-option>
    <mat-option *ngFor="let slt of selectModels" [value]="slt.id">
      {{slt.description}}
    </mat-option>
  </mat-select>
</mat-form-field>

<!-- inputタグはこちらも使用可能 -->
<div><input matInput placeholder="内容を入力"></div>

我希望以Date或String的形式获取或设置DatePicker的值。

此处我参考了一下。
JavaScript 的 Date 有太多陷阱。

// インポートに追加
import { MatDatepickerModule } from '@angular/material/datepicker';
import { MatInputModule } from '@angular/material/input';
import { MatNativeDateModule } from '@angular/material/core';

@NgModule({
  imports: [
    // ... 省略
    MatDatepickerModule,
    MatInputModule,
    MatNativeDateModule,
    // ... 省略
  ],
})
export class AppModule {
  // ... 省略
}
<div>{{selectDate2}}</div>
<mat-form-field floatLabel="never">
  <input matInput name="picker1" [matDatepicker]="picker1" placeholder="日付を選択" [(ngModel)]="selectDate"
    (dateChange)="onDatePickerChange($event)">
  <mat-datepicker-toggle matSuffix [for]="picker1"></mat-datepicker-toggle>
  <mat-datepicker #picker1></mat-datepicker>
</mat-form-field>
  ngOnInit(): void {
    // 文字列を日付に変換
    const date = '20181231';
    const dateStr = date.substr(0, 4) + '/' + date.substr(4, 2) + '/' + date.substr(6, 2);
    const time = ' 00:00:00';
    this.selectDate = new Date(dateStr + time);
  }

  // 設定された日付を取得して文字列に変換
  public onDatePickerChange(event: any): void {
    // 取得したプロパティをそのまま使用する場合、未設定時にnullになるため一度インスタンスを生成する
    const dateStr = new Date(this.selectDate);
    const yyyy = ('0000' + dateStr.getFullYear()).slice(-4);
    // 月は0〜11で取得されるので+1 足す
    const mm = ('00' + (dateStr.getMonth() + 1)).slice(-2);
    const dd = ('00' + dateStr.getDate()).slice(-2);

    this.selectDate2 = yyyy + mm + dd;
  }

我想在打开DatePicker后添加验证。

在制造过程中,当使用DatePicker时,我希望可以实现下面所描述的功能。

    • 日付の直接入力は不可

 

    アイコンクリックして日付入力(または未入力でキャンセル)時にValidationを実行
DatePicker_Validation_01.png

躲避的方式

DatePicker_Validation_02.png
<form #testForm="ngForm" appIdentityRevealed>
// ... 省略
  <mat-form-field floatLabel="never" hideRequiredMarker>
    <input matInput name="picker1" [matDatepicker]="picker1" placeholder="日付を選択" [(ngModel)]="selectDate"
      (dateChange)="onDatePickerChange($event)" readonly required #selectDate1="ngModel">
    <mat-datepicker-toggle matSuffix [for]="picker1"></mat-datepicker-toggle>
    <mat-datepicker #picker1 name="date1" (opened)="streamOpened()" (closed)="streamClosed(testForm)"></mat-datepicker>
    <mat-hint class="alert alert-danger" *ngIf="pickerClosed && selectDate1?.errors?.required" class="icon-warn">
      日付は必須入力です。
    </mat-hint>
  </mat-form-field>
// ... 省略
</form>
import { NgForm } from '@angular/forms';
// ... 省略
export class ModuleComponent implements OnInit {
  pickerClosed = false;
// ... 省略
  public streamOpened() {
    this.pickerClosed = false;
  }

  public streamClosed(form: NgForm) {
    this.pickerClosed = true;
    form.controls.picker1.markAsTouched({ onlySelf: true });
  }
}

按下Enter键时阻止表单提交。

我想在文本区域内启用Enter键(允许换行),但在其他表单中禁用通过Enter键提交表单。使用Angular 2。

<form #testForm="ngForm" appIdentityRevealed (keydown.enter)="handleEnterKeyPress($event)">
// ... 省略
</form>
  handleEnterKeyPress(event) {
    const tagName = event.target.tagName.toLowerCase();
    if (tagName !== 'textarea') {
      return false;
    }
  }

我想要更改DatePicker的位置。

想要创建一个普通的日期选择器,但是默认的地区设置是en-US,我想要将其改为ja-JP。

安装软件包。

请安装以下两个软件包。

npm install moment
npm install @angular/material-moment-adapter

如果不将其添加到app.module.ts中(如果不创建CustomDateAdapter),

import { DateAdapter, MAT_DATE_FORMATS, MAT_DATE_LOCALE } from '@angular/material/core';
import { MAT_MOMENT_DATE_FORMATS, MomentDateAdapter } from '@angular/material-moment-adapter';

@Component({
  // ... 省略
  providers: [
    { provide: MAT_DATE_LOCALE, useValue: 'ja-JP' },
    { provide: DateAdapter, useClass: MomentDateAdapter, deps: [MAT_DATE_LOCALE] },
    { provide: MAT_DATE_FORMATS, useValue: MAT_MOMENT_DATE_FORMATS },
  ],
})
DatePicker_change_location_01.png

如果要添加到app.module.ts中(如果要创建CustomDateAdapter),则需要进行以下操作。

如果有时间的话,最好创建一个CustomDateAdapter,因为使用上述方法打开DatePicker时,年月的显示可能会相反。是日期输入的救世主吗?尝试使用Angular Material的日期选择器。

我希望在文件选择按钮中使用Angular Material按钮,而不是默认按钮。

我已参考了下述文章。

在 Angular Material 中选择文件按钮

我想要让Mat-Chip的垂直高度可以调整。

似乎mat-chip内自动生成的mat-standard-chip具有指定的高度。
通过为mat-chip指定以下的css,可以使高度可变。

mat-chip {
  // mat-standard-chipの高さ固定を上書き
  height: auto;
}

最后

如果在实施过程中出现困惑的地方,我将随时添加补充说明。

仅需一种选项,将以下内容用中文进行翻译:

“Reference”

Angular的HTTP访问时显示”statusText: Not Found”
在Angular2 angular-in-memory-web-api中如何同时使用模拟和url访问的方法
Angular日期格式化
Angular:DatePipe
Angular:提供者
将基于Angular的应用程序部署到Google App Engine
Angular 4错误:无法绑定ngModel,因为它不是select的已知属性
Angular:Angular动画介绍
Angular:Angular Material入门
在Angular应用程序中按钮上不显示涟漪效果-Angular-Material
JavaScript的Date存在太多的陷阱
在Angular 2中阻止回车提交模板驱动的表单
试用使用Angular Material的日期输入”救世主”
使用Angular Material选择文件按钮

广告
将在 10 秒后关闭
bannerAds