Skip to content

Commit

Permalink
fix(material/schematics): switch to new control flow (#28106)
Browse files Browse the repository at this point in the history
Reworks our schematics to use the new control from in Angular v17.

(cherry picked from commit 328e4d2)
  • Loading branch information
crisbeto committed Nov 13, 2023
1 parent 09c7eb4 commit a09ca60
Show file tree
Hide file tree
Showing 5 changed files with 65 additions and 60 deletions.
Expand Up @@ -3,7 +3,9 @@

<div cdkDropList #todoList="cdkDropList" [cdkDropListData]="todo"
[cdkDropListConnectedTo]="doneList" class="list" (cdkDropListDropped)="drop($event)">
<div class="list-item" *ngFor="let item of todo" cdkDrag>{{item}}</div>
@for (item of todo; track item) {
<div class="list-item" cdkDrag>{{item}}</div>
}
</div>
</div>

Expand All @@ -12,6 +14,8 @@

<div cdkDropList #doneList="cdkDropList" [cdkDropListData]="done"
[cdkDropListConnectedTo]="todoList" class="list" (cdkDropListDropped)="drop($event)">
<div class="list-item" *ngFor="let item of done" cdkDrag>{{item}}</div>
@for (item of done; track item) {
<div class="list-item" cdkDrag>{{item}}</div>
}
</div>
</div>
Expand Up @@ -15,63 +15,62 @@
<div class="col">
<mat-form-field class="full-width">
<input matInput placeholder="First name" formControlName="firstName">
<mat-error *ngIf="addressForm.controls['firstName'].hasError('required')">
First name is <strong>required</strong>
</mat-error>
@if (addressForm.controls['firstName'].hasError('required')) {
<mat-error>First name is <strong>required</strong></mat-error>
}
</mat-form-field>
</div>
<div class="col">
<mat-form-field class="full-width">
<input matInput placeholder="Last name" formControlName="lastName">
<mat-error *ngIf="addressForm.controls['lastName'].hasError('required')">
Last name is <strong>required</strong>
</mat-error>
@if (addressForm.controls['lastName'].hasError('required')) {
<mat-error>Last name is <strong>required</strong></mat-error>
}
</mat-form-field>
</div>
</div>
<div class="row">
<div class="col">
<mat-form-field class="full-width">
<textarea matInput placeholder="Address" formControlName="address"></textarea>
<mat-error *ngIf="addressForm.controls['address'].hasError('required')">
Address is <strong>required</strong>
</mat-error>
@if (addressForm.controls['address'].hasError('required')) {
<mat-error>Address is <strong>required</strong></mat-error>
}
</mat-form-field>
</div>
</div>
<div class="row" *ngIf="!hasUnitNumber">
<div class="col">
<button mat-button type="button" (click)="hasUnitNumber = !hasUnitNumber">
+ Add C/O, Apt, Suite, Unit
</button>
</div>
</div>
<div class="row" *ngIf="hasUnitNumber">
<div class="row">
<div class="col">
<mat-form-field class="full-width">
<textarea matInput placeholder="Address 2" formControlName="address2"></textarea>
</mat-form-field>
@if (hasUnitNumber) {
<mat-form-field class="full-width">
<textarea matInput placeholder="Address 2" formControlName="address2"></textarea>
</mat-form-field>
} @else {
<button mat-button type="button" (click)="hasUnitNumber = !hasUnitNumber">
+ Add C/O, Apt, Suite, Unit
</button>
}
</div>
</div>
<div class="row">
<div class="col">
<mat-form-field class="full-width">
<input matInput placeholder="City" formControlName="city">
<mat-error *ngIf="addressForm.controls['city'].hasError('required')">
City is <strong>required</strong>
</mat-error>
@if (addressForm.controls['city'].hasError('required')) {
<mat-error>City is <strong>required</strong></mat-error>
}
</mat-form-field>
</div>
<div class="col">
<mat-form-field class="full-width">
<mat-select placeholder="State" formControlName="state">
<mat-option *ngFor="let state of states" [value]="state.abbreviation">
{{ state.name }}
</mat-option>
@for (state of states; track state) {

This comment has been minimized.

Copy link
@imario42

imario42 Nov 17, 2023

Hi! Shouldn't the track use something like "track state.abbreviation" here?

This comment has been minimized.

Copy link
@crisbeto

crisbeto Nov 17, 2023

Author Member

Yeah I think that would be valid too. I went with the shorter one since this example doesn't use immutable data so the object references will always be the same.

This comment has been minimized.

Copy link
@imario42

imario42 Nov 17, 2023

Sure, I just thought about users stumbling upon such examples and then probably get the wrong impression about how it works. Like fetching/refetching that 'state' list from the server. Then that example would not do what it is aimed for, no? Then Angular would always recreate those elements.

<mat-option [value]="state.abbreviation">{{ state.name }}</mat-option>
}
</mat-select>
<mat-error *ngIf="addressForm.controls['state'].hasError('required')">
State is <strong>required</strong>
</mat-error>
@if (addressForm.controls['state'].hasError('required')) {
<mat-error>State is <strong>required</strong></mat-error>
}
</mat-form-field>
</div>
</div>
Expand Down
@@ -1,24 +1,26 @@
<div class="grid-container">
<h1 class="mat-h1">Dashboard</h1>
<mat-grid-list cols="2" rowHeight="350px">
<mat-grid-tile *ngFor="let card of cards | async" [colspan]="card.cols" [rowspan]="card.rows">
<mat-card class="dashboard-card">
<mat-card-header>
<mat-card-title>
{{card.title}}
<button mat-icon-button class="more-button" [matMenuTriggerFor]="menu" aria-label="Toggle menu">
<mat-icon>more_vert</mat-icon>
</button>
<mat-menu #menu="matMenu" xPosition="before">
<button mat-menu-item>Expand</button>
<button mat-menu-item>Remove</button>
</mat-menu>
</mat-card-title>
</mat-card-header>
<mat-card-content class="dashboard-card-content">
<div>Card Content Here</div>
</mat-card-content>
</mat-card>
</mat-grid-tile>
@for (card of cards | async) {
<mat-grid-tile [colspan]="card.cols" [rowspan]="card.rows">
<mat-card class="dashboard-card">
<mat-card-header>
<mat-card-title>
{{card.title}}
<button mat-icon-button class="more-button" [matMenuTriggerFor]="menu" aria-label="Toggle menu">
<mat-icon>more_vert</mat-icon>
</button>
<mat-menu #menu="matMenu" xPosition="before">
<button mat-menu-item>Expand</button>
<button mat-menu-item>Remove</button>
</mat-menu>
</mat-card-title>
</mat-card-header>
<mat-card-content class="dashboard-card-content">
<div>Card Content Here</div>
</mat-card-content>
</mat-card>
</mat-grid-tile>
}
</mat-grid-list>
</div>
Expand Up @@ -12,14 +12,15 @@
</mat-sidenav>
<mat-sidenav-content>
<mat-toolbar color="primary">
<button
type="button"
aria-label="Toggle sidenav"
mat-icon-button
(click)="drawer.toggle()"
*ngIf="isHandset$ | async">
<mat-icon aria-label="Side nav toggle icon">menu</mat-icon>
</button>
@if (isHandset$ | async) {
<button
type="button"
aria-label="Toggle sidenav"
mat-icon-button
(click)="drawer.toggle()">
<mat-icon aria-label="Side nav toggle icon">menu</mat-icon>
</button>
}
<span><%= project %></span>
</mat-toolbar>
<!-- Add Content Here -->
Expand Down
@@ -1,13 +1,13 @@
import { Component, inject<% if(!!viewEncapsulation) { %>, ViewEncapsulation<% }%><% if(changeDetection !== 'Default') { %>, ChangeDetectionStrategy<% }%> } from '@angular/core';
import { BreakpointObserver, Breakpoints } from '@angular/cdk/layout';<% if(standalone) { %>
import { AsyncPipe } from '@angular/common';
import { MatToolbarModule } from '@angular/material/toolbar';
import { MatButtonModule } from '@angular/material/button';
import { MatSidenavModule } from '@angular/material/sidenav';
import { MatListModule } from '@angular/material/list';
import { MatIconModule } from '@angular/material/icon';<% } %>
import { Observable } from 'rxjs';
import { map, shareReplay } from 'rxjs/operators';
import { AsyncPipe, NgIf } from '@angular/common';

@Component({
selector: '<%= selector %>',<% if(inlineTemplate) { %>
Expand All @@ -29,7 +29,6 @@ import { AsyncPipe, NgIf } from '@angular/common';
MatListModule,
MatIconModule,
AsyncPipe,
NgIf
]<% } %>
})
export class <%= classify(name) %>Component {
Expand Down

0 comments on commit a09ca60

Please sign in to comment.