@Component({
...
template: '<p #bio></p>'
})
export class UserDetailsComponent {
@ViewChild('bio') bio;
}
<p>
tag that has the bio template reference variable in the component’s template view.<p>
tag is rendered as a child of the parent view that uses this component.<p>
tag in the template support content projection.<p>
tag visible in the final render. If the #bio was used in the template and the @ViewChild was not used in the class, then Angular would automatically hide the <p>
tag that has #bio on it.DigitalOcean - viewchild-access-component
<form>
element to indicate what fields it should include.Angular.io - Reactive Form Groups
paramMap
and the queryParamMap
on the ActivatedRoute
class?<h2>Names</h2>
<div *ngFor="let user of users | async"></div>
<h2>Ages</h2>
<div *ngFor="let user of users | async"></div>
<h2>Genders</h2>
<div *ngFor="let user of users | async"></div>
export class OrderService {
constructor(private httpClient: HttpClient) {}
addOrder(order: Order) {
// Missing line
}
}
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>
tag to routing?@Component({
selector: 'app-shopping-cart',
. . .
})
export class ShoppingCartComponent {
@Output() itemTotalChanged = new EventEmitter();
}
itemTotalChanged
class field public.itemTotalChanged
class field, like so: <app-shopping-cart [itemTotalChanged]="newTotal"></app-shopping-cart>
.itemTotalChanged
class field, like so: <app-shopping-cart (itemTotalChanged)="logNewTotal($event)"></app-shopping-cart>
.Angular.io - Sending data to parent component
<div *ngIf="isVisible">Active</div>
<div [hidden]="!isVisible">Active</div>
ngIf
is shorthand for the other example. When Angular processes that directive, it writes a div element to the DOM with the hidden property.ngIf
directive does not render the div in the DOM if the expression is false. The hidden
property usage hides the div content in the browser viewport, but the div is still in the DOM.ngIf
is valid, but the use of the hidden
property is wrong and will throw an error.<form #userForm="ngForm">
<input type="text" ngModel name="firstName" required />
<input type="text" ngModel name="lastName" required />
<button (click)="submit(userForm.value)">Save</button>
</form>
A
<button (click)="submit(userForm.value)" disable="userForm.invalid">Save</button>
B
<button (click)="submit(userForm.value)" [disabled]="userForm.invalid">Save</button>
C
<button (click)="submit(userForm.value)" [ngForm.disabled]="userForm.valid">Save</button>
D
<button (click)="submit(userForm.value)" *ngIf="userForm.valid">Save</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>Boss: </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="">Invalid field data</span>
<h1 #headerText>User List</h1>
<h1>
elementPluralsight - Template reference variable
[{ provide: FormattedLogger, useClass: Logger }][{ provide: FormattedLogger, useExisting: Logger }];
{
path: 'customers',
component: CustomerListComponent,
data: { accountSection: true }
}
ngIf
structural directive change the rendered DOM based on this template syntax?@Component({
selector: 'app-product',
template: '<div *ngIf="product"></div>',
})
export class ProductComponent {
@Input() product;
}
<div>
acts as a placeholder. If the product class field is “truthy,” the <div>
will get replaced by just the product.name
value; if not, then nothing will be rendered.<div>
will always be rendered, and if the product field is “truthy,” the <div>
element will contain the product.name
value; otherwise, it will render the <div>
element with no value in it.<div>
with the value of the product.name
field. If it is not “truthy,’ the rendered DOM will not contain the <div>
element.@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>
element at runtime.<ng-content>
for this component.fixture.detectChanges()
call in this unit test?TestBed.configureTestingModule({
declarations: [UserCardComponent],
});
let fixture = TestBed.createComponent(UserCardComponent);
fixture.detectChanges();
expect(fixture.nativeElement.querySelector('h1').textContent).toContain(
fixture.componentInstance.title,
);
Router.navigate
method when goToUser is passed the value 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>
element to wire it up?FormArray
FormControl
FormGroup
all of these answers
<form [formGroup]="form">
<input type="text" formControlName="username" />
...
</form>
A
<span *ngIf="username.minLength.invalid"> Username length is not valid </span>
B
<input type="text" formControlName="username" [showMinLength]="true" />
C
<span *ngIf="form.get('username').getError('minLength') as minLengthError">
Username must be at least characters.
</span>
D
<input type="text" formControlName="username" #userName="ngModel" />
<span *ngIf="userName.errors.minlength">
Username must be at least characters.
</span>
TestBed.configureTestingModule({
declarations: [UserCardComponent],
});
let fixture = TestBed.createComponent(UserCardComponent);
fixture.componentTemplate
fixture.getComponentHtml()
fixture.nativeElement
fixture.componentInstance.template
@Component({
selector: 'app-card',
template: '<h1>Data Card</h1><ng-content></ng-content>'
})
export class CardComponent { }
@Component({
selector: 'app-bio',
template: '<ng-content></ng-content>.
})
export class BioComponent { }
// markup usage:
<app-card><app-bio>Been around for four years.</app-bio></app-card>
A
<app-card>
<h1>Data Card</hl>
<app-bio>
Been around for four years.
</app-bio>
</app-card>
B
<h1>Data Card</h1>
<app-bio> Been around for four years. </app-bio>
C
<app-card>
<h1>Data Card</hl>
<ng-content></ng-content>
<app-bio>
Been around for four years.
<ng-content></ng-content>
</app-bio>
</app-card>
D
<app-card>
<h1>Data Card</hl>
</app-card>
@Component({
selector: 'app-user-card',
template: '<app-title-card></app-title-card><p>Jenny Smith</p>'
})
@Component({
selector: 'app-title-card',
template: '<h1>User Data</hl>'
})
// usage of user card component in parent component html
<app-user-card></app-user-card>
A
<app-user-card>
<app-title-card>
<h1>User Data</h1>
</app-title-card>
<p>Jenny Smith</p>
</app-user-card>
B
<h1>User Data</h1>
<p>Jenny Smith</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>User Data</h1>
<p>Jenny Smith</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
will execute the get query. The retry operator is used to tell the pipe call to retry the get query three times.Httpclient.get
call.const spy = jasmine.createSpyObj('DataService', ['getUsersFromApi']);
TestBed.configureTestingModule({
providers: [UserService, { provide: DataService, useValue: spy }],
});
const userService = TestBed.get(UserService);
All other tests be ignored, including tests that assert results against one of these providers and a non-defined provider.
Although it will work when multiple providers in this configuration are asserted against in a single test.
@Directive({
selector: '[appTruncate]'
})
export class TruncateDirective {
. . .
}
// example of desired usage:
<p [appTruncate]="10">Some very long text here</p>
@Input() appTruncate: number;
@Output() appTruncate;
constructor(maxLength: number) { }
Nothing. The directive selector cannot be used to pass in values to the directive.
HttpClient.get
request?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
has been registered in the providers for the application, which answer best describes what happens based on this component’s constructor?@Component({
...
})
export class OrderHistoryComponent {
constructor(private dataService: DataService) {}
...
}
OrderHistoryComponent
will have its own version of a DataService
and that it should never use any existing instances. The DataService
would need to be instantiated within the class as a private field for this code to be complete and working.OrderHistoryComponent
, the injector will provide an instance of a DataService
class to the component constructor’s first argument. The constructor’s dataService
parameter will be used to set a private instance field with the same name on the instance.dataService
that can be used to bind an existing DataService
instance to.ngIf
directive to implement an else case that will display the text “User is not active”:<div *ngIf="userIsActive; else inactive">Currently active!</div>
A
<div #inactive>User is not active.</div>
B
<div *ngIf="inactive">User is not active.</div>
C
<ng-template #else="inactive">
<div>User is not active.</div>
</ng-template>
D
<ng-template #inactive>
<div>User is not active.</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
for username
is getting configured to exclude three validators from the validators that it is allowed to use.FormControl
for username
is getting configured to allow three possible validators to be used: required, maxLength
, and a custom one named unique
. To enable these validators
, a validator directive would need to be put on the form fields in the markup.FormControl
for username
is getting configured with three validators: the required
and minLength
validators that come from Angular, and a custom validator function named unique
that checks for the value not equal to the string 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()">Save</button>
</form>
prelodingStrategy
property configuration in this router code?RouterModule.forRoot(
...{
preloadingStrategy: PreloadAllModules,
},
);
References:
userName
to the h1
element title property?<h1 [title]="userName">Current user is </h1>
title="userName"
title=""
title="userName"
async
pipe doing in this example?@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
statement.ngFor
iteration to support multiple lists of users at the same time.HttpClient.get
method and unwrapping the returned value so it can be iterated over in the ngFor
.users
field to be rendered concurrently to the DOM.@Directive({ selector: '[appTruncate]'
})
export class TruncateDirective{ . . .
}
html <p data-directive="appTruncate">Some long text </p>
html <p appTruncate>Some long text</p>
html <p app-truncate>Some long text</p>
html <app-truncate>Some long text</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;
}
}
some lo...
some ltrue
some long text
[How do I call an Angular 2 pipe with multiple arguments?] (https://stackoverflow.com/questions/36816788/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>
export interface AppSettings {
title: string;
version: number;
}
Angular unit tests - recheck answers
CanActivate vs Canload CanActivate prevents access on routes, CanLoad prevents lazy loading.
{ path: 'document', component: DocumentComponent, outlet: 'document-box'
}
<document-box>
in the DOM and insert a DocumentComponent element into them on route navigation.<document-box>
element in addition ot being routed to.<router-outlet>
element with the name attribute matching the string value as the location for the DocumentComponent to be rendered when routed to.Angular-outlet - recheck answer
<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
}
html
<input type='text' id='productName'>
Dom element in the component template.Input()
Input()
useValue
provider configuration and set that equal to an existing object or an object literal.asValue
provider configuration property, setting it to true.Configuring dependency providers
{path: 'user/:id', component: UserDetailComponent }
<form [formGroup]="form">
<input type="text" formControlName="username" />
<button type="submit" [disabled]="form. invalid">Submit</button>
</form>
<button>
element.<form>
element.<div [ngClass]="{ ‘active-item': isActive }">Item One</div>
<div active-item>Item One</div>
<div class="active-item">Item One</div>
<div class="is-active">Item One</div>
<div class="active-item isActive">Item One</div>
<input [(ngModel)]="user.name" />
<form>
element to indicate what fields it should include.<span [ngClass]="{ 'active': isActive, 'can-toggle': canToggle }"> Employed </span>
A
<span class=" ">
Employed
</span>
B
<span [class.active]="isActive" [class.can-toggle]="canToggle"> Employed </span>
C
<span [styles.class.active]="isActive" [styles.class.can-toggle]="canToggle"> Employed </span>
D
<span [css.class.active]="isActive" [css.class.can-toggle]="canToggle"> Employed </span>
@Directive({
selector: '[customValidator]',
providers: [
{
provide: NG_VALIDATORS,
useExisting: CustomValidatorDirective,
multi: true,
},
],
})
export class CustomValidatorDirective implements Validator {}
@Component({
selector: 'app-date-card',
template: '',
})
export class DateCardComponent {
currentYear() {
return new Date().getFullYear();
}
}