@Component({
...
template: '<p #bio></p>'
})
export class UserDetailsComponent {
@ViewChild('bio') bio;
}
<p>, який має змінну шаблону bio в поданні шаблону компонента.<p> рендериться як дочірній елемент батьківського подання, яке використовує цей компонент.<p> у шаблоні підтримуючим проекцію вмісту.<p> видимим у фінальному рендері. Якщо #bio був використаний у шаблоні, а @ViewChild не був використаний у класі, тоді Angular автоматично приховає тег <p>, який має #bio.DigitalOcean - viewchild-access-component
<form>, щоб вказати, які поля він повинен включати.Angular.io - Reactive Form Groups
paramMap та queryParamMap у класі ActivatedRoute?<h2>Імена</h2>
<div *ngFor="let user of users | async"></div>
<h2>Вік</h2>
<div *ngFor="let user of users | async"></div>
<h2>Стать</h2>
<div *ngFor="let user of users | async"></div>
export class OrderService {
constructor(private httpClient: HttpClient) {}
addOrder(order: Order) {
// Відсутній рядок
}
}
this.httpClient.url(this.orderUrl).post(order);this.httpClient.send(this.orderUrl, order);this.httpClient.post<Order>(this.orderUrl, order);this.httpClient.post<Order>(this.orderUrl, order).subscribe();Angular.io - Sending data to server
@Component({
selector: 'app-user-card',
. . .
})
<div app-user-card></div>.<app-user-card></app-user-card>.<app-user-card></app-user-card>.<user-card></user-card>.Angular.io - Component Metadata
A
<ul>
<li [ngFor]="let productName of productNames"></li>
</ul>
B
<ul>
<li ngFor="let productName of productNames"></li>
</ul>
C
<ul>
<li *ngFor="let productName of productNames"></li>
</ul>
D
<ul>
<? for productName in productNames { ?>
<li></li>
<? } ?>
</ul>
Angular.io- Structural Directives
@Component({
selector: 'app-title-card',
template: '',
})
class TitleCardComponent {
title = 'User Data';
}
title[title]Angular.io - String Interpolation or Text Interpolation
Angular.io - Displaying a from control value
<a> до маршрутизації?@Component({
selector: 'app-shopping-cart',
. . .
})
export class ShoppingCartComponent {
@Output() itemTotalChanged = new EventEmitter();
}
itemTotalChanged публічним.itemTotalChanged, наприклад: <app-shopping-cart [itemTotalChanged]="newTotal"></app-shopping-cart>.itemTotalChanged, наприклад: <app-shopping-cart (itemTotalChanged)="logNewTotal($event)"></app-shopping-cart>.Angular.io - Sending data to parent component
<div *ngIf="isVisible">Активний</div>
<div [hidden]="!isVisible">Активний</div>
ngIf є скороченням для іншого прикладу. Коли Angular обробляє цю директиву, він записує елемент div у DOM з властивістю hidden.ngIf не рендерить div у DOM, якщо вираз є false. Використання властивості hidden приховує вміст div у вікні браузера, але div все ще залишається в DOM.ngIf є правильним, але використання властивості hidden є неправильним і викличе помилку.<form #userForm="ngForm">
<input type="text" ngModel name="firstName" required />
<input type="text" ngModel name="lastName" required />
<button (click)="submit(userForm.value)">Зберегти</button>
</form>
A
<button (click)="submit(userForm.value)" disable="userForm.invalid">Зберегти</button>
B
<button (click)="submit(userForm.value)" [disabled]="userForm.invalid">Зберегти</button>
C
<button (click)="submit(userForm.value)" [ngForm.disabled]="userForm.valid">Зберегти</button>
D
<button (click)="submit(userForm.value)" *ngIf="userForm.valid">Зберегти</button>
Angular.io - Submit the form with ngSubmit
Angular.io - ng generate options
@Component({
selector: 'app-title-card',
template: '<h1 title="User Data"> </h1>',
})
export class TitleCardComponent {
titleText = 'User Data';
}
<h1 data-title="titleText"></h1><h1 title="titleText"></h1><h1 [title]="titleText"></h1><h1 titleText></h1>Angular.io - String Interpolation
<span>Керівник: </span>
{ path: 'user/:id', component: UserDetailComponent }{ url: 'user/:id', routedComponent: UserDetailComponent }{ routedPath: 'user/:id', component: UserDetailComponent }{ destination: new UserDetailComponent(), route: 'user/:id' }CodeCraft - Parameterised Routes
@Directive({
selector: '[appCallout]',
})
export class CalloutDirective {
@HostBinding('style.font-weight') fontWeight = 'normal';
@HostListener('mouseenter')
onMouseEnter() {
this.fontWeight = 'bold';
}
@HostListener('mouseleave')
onMouseLeave() {
this.fontWeight = 'normal';
}
}
<input type="text" ngModel name="firstName" required minlength="4" />
<span *ngIf="">Невірні дані поля</span>
<h1 #headerText>Список користувачів</h1>
<h1>Pluralsight - Template reference variable
[{ provide: FormattedLogger, useClass: Logger }][{ provide: FormattedLogger, useExisting: Logger }];
{
path: 'customers',
component: CustomerListComponent,
data: { accountSection: true }
}
ngIf змінює відрендерений DOM на основі цього синтаксису шаблону?@Component({
selector: 'app-product',
template: '<div *ngIf="product"></div>',
})
export class ProductComponent {
@Input() product;
}
<div> діє як заповнювач. Якщо поле класу product є “truthy”, <div> буде замінено лише значенням product.name; якщо ні, то нічого не буде відрендерено.<div> завжди буде відрендерено, і якщо поле product є “truthy”, елемент <div> міститиме значення product.name; в іншому випадку він відрендерить елемент <div> без значення в ньому.<div> зі значенням поля product.name. Якщо воно не є “truthy”, відрендерений DOM не міститиме елемент <div>.@NgModule({
declarations: [AppComponent],
imports: [BrowserModule],
bootstrap: [AppComponent],
})
export class AppModule {}
platformBrowserDynamic().bootstrapModule(AppModule);
Angular.io - The basic NgModule
{
path: ':id',
component: UserComponent,
resolve: {
user: UserResolverService
}
}
@Component({
. . .
template: '<ng-content></ng-content>'
})
export class TabsListComponent {
@ContentChildren(TabComponent) tabs;
}
<ng-content> під час виконання.<ng-content> для цього компонента.fixture.detectChanges() у цьому модульному тесті?TestBed.configureTestingModule({
declarations: [UserCardComponent],
});
let fixture = TestBed.createComponent(UserCardComponent);
fixture.detectChanges();
expect(fixture.nativeElement.querySelector('h1').textContent).toContain(
fixture.componentInstance.title,
);
Router.navigate, коли goToUser передається значення 15?export class ToolsComponent {
constructor(private router: Router) {}
goToUser(id: number) {
this.router.navigate(['user', id]);
}
}
@Directive({
selector: ' [appHighlight] ',
})
export class HighlightDirective {
@HostBinding('class.highlighted') highlight = true;
}
<form> для його підключення?FormArrayFormControlFormGroupвсі ці відповіді<form [formGroup]="form">
<input type="text" formControlName="username" />
...
</form>
A
<span *ngIf="username.minLength.invalid"> Довжина імені користувача недійсна </span>
B
<input type="text" formControlName="username" [showMinLength]="true" />
C
<span *ngIf="form.get('username').getError('minLength') as minLengthError">
Ім'я користувача повинно містити принаймні символів.
</span>
D
<input type="text" formControlName="username" #userName="ngModel" />
<span *ngIf="userName.errors.minlength">
Ім'я користувача повинно містити принаймні
символів.
</span>
TestBed.configureTestingModule({
declarations: [UserCardComponent],
});
let fixture = TestBed.createComponent(UserCardComponent);
fixture.componentTemplatefixture.getComponentHtml()fixture.nativeElementfixture.componentInstance.template @Component({
selector: 'app-card',
template: '<h1>Карта даних</h1><ng-content></ng-content>'
})
export class CardComponent { }
@Component({
selector: 'app-bio',
template: '<ng-content></ng-content>.
})
export class BioComponent { }
// використання розмітки:
<app-card><app-bio>Існує вже чотири роки.</app-bio></app-card>
A
<app-card>
<h1>Карта даних</h1>
<app-bio> Існує вже чотири роки. </app-bio>
</app-card>
B
<h1>Карта даних</h1>
<app-bio> Існує вже чотири роки. </app-bio>
C
<app-card>
<h1>Карта даних</h1>
<ng-content></ng-content>
<app-bio>
Існує вже чотири роки.
<ng-content></ng-content>
</app-bio>
</app-card>
D
<app-card>
<h1>Карта даних</h1>
</app-card>
@Component({
selector: 'app-user-card',
template: '<app-title-card></app-title-card><p>Дженні Сміт</p>'
})
@Component({
selector: 'app-title-card',
template: '<h1>Дані користувача</h1>'
})
// використання компонента user card в HTML батьківського компонента
<app-user-card></app-user-card>
A
<app-user-card>
<app-title-card>
<h1>Дані користувача</h1>
</app-title-card>
<p>Дженні Сміт</p>
</app-user-card>
B
<h1>Дані користувача</h1>
<p>Дженні Сміт</p>
<p></p>
C
<app-user-card>
<app-title-card></app-title-card>
</app-user-card>
D
<div app-user-card>
<h1 app-title-card>Дані користувача</h1>
<p>Дженні Сміт</p>
</div>
constructor(@Inject('Logger') private logger) { }
A
providers: [Logger];
B
providers: [{ provide: 'Logger', useClass: Logger }];
C
@Injectable({
providedln: 'root'
})
D
providers: [{ provide: 'Logger' }];
export class SettingsService {
constructor(private httpClient: HttpClient) { }
...
getSettings()
{
return this.httpClient.get<Settings>(this.settingsUrl)
.pipe(
retry(3)
);
}}
getSettings виконає запит get. Оператор retry використовується, щоб вказати виклику pipe повторити запит get тричі.Httpclient.get.const spy = jasmine.createSpyObj('DataService', ['getUsersFromApi']);
TestBed.configureTestingModule({
providers: [UserService, { provide: DataService, useValue: spy }],
});
const userService = TestBed.get(UserService);
@Directive({
selector: '[appTruncate]'
})
export class TruncateDirective {
. . .
}
// приклад бажаного використання:
<p [appTruncate]="10">Якийсь дуже довгий текст тут</p>
@Input() appTruncate: number;@Output() appTruncate;constructor(maxLength: number) { }Нічого. Селектор директиви не може використовуватися для передачі значень у директиву.HttpClient.get?export class OrderService {
constructor(private httpClient: HttpClient) {}
getOrdersByYear(year: number): Observable<Order[]> {
return this.httpClient.get<Order[]>(this.ordersUrl);
}
}
return this.httpClient.get<Order[]>(this.ordersUrl, {'year': year})return this.httpClient.get<Order[]>(this.ordersUrl, year)C
const options = { params: new HttpParams().set('year', year) };
return this.httpClient.get<Order[]>(this.ordersUrl, options);
D
getOrdersByYear(year: number): Observable<Order[]> {
return this.httpClient.addParam('year', year).get<Order[]>(this.ordersUrl, year);
}
DataService був зареєстрований у провайдерах для додатку, яка відповідь найкраще описує, що відбувається на основі конструктора цього компонента?@Component({
...
})
export class OrderHistoryComponent {
constructor(private dataService: DataService) {}
...
}
OrderHistoryComponent матиме свою власну версію DataService і що він ніколи не повинен використовувати будь-які існуючі екземпляри. DataService потрібно було б створити всередині класу як приватне поле, щоб цей код був повним і працюючим.OrderHistoryComponent, інжектор надасть екземпляр класу DataService першому аргументу конструктора компонента. Параметр dataService конструктора буде використано для встановлення приватного поля екземпляра з тією ж назвою на екземплярі.dataService, яку можна використовувати для прив’язки існуючого екземпляра DataService.ngIf для реалізації випадку else, який відобразить текст “Користувач неактивний”:<div *ngIf="userIsActive; else inactive">Наразі активний!</div>
A
<div #inactive>Користувач неактивний.</div>
B
<div *ngIf="inactive">Користувач неактивний.</div>
C
<ng-template #else="inactive">
<div>Користувач неактивний.</div>
</ng-template>
D
<ng-template #inactive>
<div>Користувач неактивний.</div>
</ng-template>
A
{
path: 'users',
lazy: './users/users.module#UsersModule'
}
B
{
path: 'users',
loadChildren: () => import('./users/users.module').then(m => m.UserModule)
}
C
{
path: 'users',
loadChildren: './users/users.module#UsersModule'
}
D
{
path: 'users',
module: UsersModule
}
Angular.io - Lazy Loading Modules
export class UserFormControl implements OnInit {
...
ngOnInit() {
this.form = this.formBuilder.group({
username: this.formBuilder.control('',
[Validators.required, Validators.minLength(5), this.unique]),
)};
}
unique(control: FormControl) {
return control.value !== 'admin' ? null: {notUnique: true};
}
}
FormControl для username налаштовується на виключення трьох валідаторів з валідаторів, які йому дозволено використовувати.FormControl для username налаштовується на дозвіл використання трьох можливих валідаторів: required, maxLength та користувацького з назвою unique. Щоб увімкнути ці валідатори, директиву валідатора потрібно було б помістити на поля форми в розмітці.FormControl для username налаштовується з трьома валідаторами: валідаторами required і minLength, які надходять від Angular, та користувацькою функцією валідатора з назвою unique, яка перевіряє, що значення не дорівнює рядку admin.@Injectable({
providedIn: 'root'
)}
export class DataService { }
export interface AppSettings {
title: string;
version: number;
}
export const APP_SETTINGS = new InjectionToken<AppSettings>('app.settings');
<form #form="ngForm">
<input type="text" ngModel="firstName" /> <input type="text" ngModel="lastName" />
<button (click)="submit()">Зберегти</button>
</form>
prelodingStrategy у цьому коді маршрутизатора?RouterModule.forRoot(
...{
preloadingStrategy: PreloadAllModules,
},
);
Посилання:
userName до властивості title елемента h1?<h1 [title]="userName">Поточний користувач: </h1>
title="userName"title=""title="userName"async pipe у цьому прикладі?@Component({
selector: 'app-users',
template: '<div *ngFor="let user of users | async"></div>',
})
export class UsersComponent implements OnInit {
users;
constructor(private httpClient: HttpClient) {}
ngOnInit(): void {
this.users = this.httpClient.get<{ name: string }>('users');
}
}
ngFor.ngFor для підтримки кількох списків користувачів одночасно.HttpClient.get, і розгортає повернене значення, щоб його можна було ітерувати в ngFor.users бути відрендереними одночасно в DOM.@Directive({ selector: '[appTruncate]'
})
export class TruncateDirective{ . . .
}
html <p data-directive="appTruncate">Якийсь довгий текст </p> html <p appTruncate>Якийсь довгий текст</p> html <p app-truncate>Якийсь довгий текст</p> html <app-truncate>Якийсь довгий текст</app-truncate> How to detect when an @Input() value changes in Angular?
@Pipe({ name: 'truncate' })
export class TruncatePipe implements PipeTransform {
transform(value: string, maxLength: number, showEllipsis: boolean) {
const newValue = maxLength ? value.substr(0, maxLength) : value;
return showEllipsis ? '${newValue}...' : newValue;
}
}
якийсь ...якийсьtrueякийсь довгий текстHow do I call an Angular 2 pipe with multiple arguments?
<div *ngIf="location">
<h1></h1>
<p></p>
</div>
A
<div *ngIf="location">
<h1></h1>
<p></p>
</div>
B
<ng-template *ngIf="location">
<h1></h1>
<p></p>
</ng-template>
C
<div *ngIf="location" [display]=" ' hidden' ">
<h1></h1>
<p></p>
</div>
D
<ng-container *ngIf="location">
<h1></h1>
<p></p>
</ng-container>
<div class="tab"></div>
[width]="tabWidth"[inline.width]="tabWidth"[style.width.px]="tabWidth"{ path: 'document', component: DocumentComponent, outlet: 'document-box'
}
<document-box> у DOM і вставить елемент DocumentComponent в них при навігації маршруту.<document-box> на додаток до маршрутизації.<router-outlet> з атрибутом name, що відповідає строковому значенню, як місце для рендерингу DocumentComponent при маршрутизації.<div *ngFor="let item of items"> - </div>
*ngFor="let item of items; let uniqueItem"*ngFor="let item of items.distinct()"*ngFor="let item of items: let i = index"*ngFor="let item of items; trackBy: trackById"StackOverflow - How to use trackBy with ngFor
ng build --configuration=production --progress=false
Angular documentation - ng build
@Component({ selector:'app-product-name', ...
})
export class ProductNameComponent { @Input() productName: string
}
<input type='text' id='productName'> у шаблоні компонента.Angular documentation - Input()
useValue і встановити її рівною існуючому об’єкту або об’єктному літералу.asValue, встановивши її в true.Configuring dependency providers
{path: 'user/:id', component: UserDetailComponent }
<form [formGroup]="form">
<input type="text" formControlName="username" />
<button type="submit" [disabled]="form.invalid">Надіслати</button>
</form>
<button>.<form>.<div [ngClass]="{ 'active-item': isActive }">Елемент один</div>
<div active-item>Елемент один</div><div class="active-item">Елемент один</div><div class="is-active">Елемент один</div><div class="active-item isActive">Елемент один</div><input [(ngModel)]="user.name" />
A
@NgModule({
exports: [TableModule],
})
export class SharedModule {}
B
@NgModule({
imports: [TableModule],
})
export class SharedModule {}
C
@NgModule({
declarations: [TableModule],
})
export class SharedModule {}
D
@NgModule({
providers: [TableModule],
})
export class SharedModule {}
{ path: 'document', component: DocumentComponent, outlet: 'document-box'
}
<document-box> у DOM і вставить елемент DocumentComponent в них при навігації маршруту.<document-box> на додаток до маршрутизації.<router-outlet> з атрибутом name, що відповідає строковому значенню, як місце для рендерингу DocumentComponent при маршрутизації.useValue і встановити її рівною існуючому об’єкту або об’єктному літералу.asValue, встановивши її в true.Configuring dependency providers
{path: 'user/:id', component: UserDetailComponent }
<form [formGroup]="form">
<input type="text" formControlName="userName" />
</form>
Angular - Routing & Navigation
Angular - Component Interaction
@Component({...})
export class UserProfileComponent implements CanDeactivate<UserProfileComponent> {
canDeactivate(
component: UserProfileComponent,
currentRoute: ActivatedRouteSnapshot,
currentState: RouterStateSnapshot,
nextState?: RouterStateSnapshot
): Observable<boolean> | Promise<boolean> | boolean {
// Ваша логіка перевірки
}
}
@Injectable({
providedIn: 'root',
})
export class AuthGuard implements CanActivate {
constructor(private authService: AuthService) {}
canActivate(route: ActivatedRouteSnapshot, state: RouterStateSnapshot): boolean {
return this.authService.isLoggedIn();
}
}
Angular - Structural and Attribute Directives
@Pipe({ name: 'exponentialStrength' })
export class ExponentialStrengthPipe implements PipeTransform {
transform(value: number, exponent: string): number {
const exp = parseInt(exponent, 10);
return Math.pow(value, isNaN(exp) ? 1 : exp);
}
}
export class UserProfileComponent implements CanDeactivate<UserProfileComponent> {
canDeactivate(component: UserProfileComponent): Observable<boolean> | Promise<boolean> | boolean {
return component.canLeave ? component.canLeave() : true;
}
}
@Injectable({ providedIn: 'root' })
export class CustomPreloadingStrategy implements PreloadingStrategy {
preload(route: Route, load: () => Observable<any>): Observable<any> {
return route.data && route.data.preload ? load() : of(null);
}
}
@Injectable({ providedIn: 'root' })
export class UserResolver implements Resolve<User> {
constructor(private userService: UserService) {}
resolve(route: ActivatedRouteSnapshot, state: RouterStateSnapshot): Observable<User> {
return this.userService.getUser(route.params['id']);
}
}
@Injectable({
providedIn: 'root',
})
export class AuthGuard implements CanLoad {
constructor(private authService: AuthService) {}
canLoad(route: Route, segments: UrlSegment[]): Observable<boolean> | Promise<boolean> | boolean {
return this.authService.isLoggedIn();
}
}
@Injectable({
providedIn: 'root',
})
export class AuthGuard implements CanActivateChild {
constructor(private authService: AuthService) {}
canActivateChild(
childRoute: ActivatedRouteSnapshot,
state: RouterStateSnapshot,
): Observable<boolean> | Promise<boolean> | boolean {
return this.authService.isLoggedIn();
}
}