mirror of
https://github.com/angular/angular.git
synced 2026-09-14 13:54:52 +08:00
refactor(docs-infra): apply prettier formatting to adev (#54625)
Apply prettier formatting to adev code PR Close #54625
This commit is contained in:
@@ -7,6 +7,7 @@ export const format: FormatConfig = {
|
||||
'prettier': {
|
||||
'matchers': [
|
||||
'**/*.{yaml,yml}',
|
||||
'adev/**/*.{js,ts}',
|
||||
'devtools/**/*.{js,ts}',
|
||||
'tools/**/*.{js,ts}',
|
||||
'modules/**/*.{js,ts}',
|
||||
|
||||
+11
-7
@@ -21,7 +21,7 @@ module.exports = function (config) {
|
||||
'/dummy/image': 'src/assets/images/logos/angular/angular.png',
|
||||
},
|
||||
client: {
|
||||
clearContext: false, // leave Jasmine Spec Runner output visible in browser
|
||||
clearContext: false, // leave Jasmine Spec Runner output visible in browser
|
||||
jasmine: {
|
||||
// you can add configuration options for Jasmine here
|
||||
// the possible options are listed at https://jasmine.github.io/api/edge/Configuration.html
|
||||
@@ -32,15 +32,12 @@ module.exports = function (config) {
|
||||
},
|
||||
},
|
||||
jasmineHtmlReporter: {
|
||||
suppressAll: true // removes the duplicated traces
|
||||
suppressAll: true, // removes the duplicated traces
|
||||
},
|
||||
coverageReporter: {
|
||||
dir: require('path').join(__dirname, './coverage/site'),
|
||||
subdir: '.',
|
||||
reporters: [
|
||||
{ type: 'html' },
|
||||
{ type: 'text-summary' }
|
||||
],
|
||||
reporters: [{type: 'html'}, {type: 'text-summary'}],
|
||||
},
|
||||
reporters: ['progress', 'kjhtml', 'jasmine-seed'],
|
||||
port: 9876,
|
||||
@@ -51,7 +48,14 @@ module.exports = function (config) {
|
||||
ChromeHeadlessNoSandbox: {
|
||||
base: 'ChromeHeadless',
|
||||
// See /integration/README.md#browser-tests for more info on these args
|
||||
flags: ['--no-sandbox', '--headless', '--disable-gpu', '--disable-dev-shm-usage', '--hide-scrollbars', '--mute-audio'],
|
||||
flags: [
|
||||
'--no-sandbox',
|
||||
'--headless',
|
||||
'--disable-gpu',
|
||||
'--disable-dev-shm-usage',
|
||||
'--hide-scrollbars',
|
||||
'--mute-audio',
|
||||
],
|
||||
},
|
||||
},
|
||||
browsers: ['ChromeHeadlessNoSandbox'],
|
||||
|
||||
@@ -7,7 +7,15 @@
|
||||
*/
|
||||
|
||||
import {DOCUMENT, isPlatformBrowser} from '@angular/common';
|
||||
import {Component, inject, NgZone, OnInit, PLATFORM_ID, signal, WritableSignal} from '@angular/core';
|
||||
import {
|
||||
Component,
|
||||
inject,
|
||||
NgZone,
|
||||
OnInit,
|
||||
PLATFORM_ID,
|
||||
signal,
|
||||
WritableSignal,
|
||||
} from '@angular/core';
|
||||
import {NavigationEnd, NavigationSkipped, Router, RouterLink, RouterOutlet} from '@angular/router';
|
||||
import {filter, map, skip} from 'rxjs/operators';
|
||||
import {
|
||||
|
||||
@@ -28,12 +28,12 @@ export class ContentLoader implements DocsContentLoader {
|
||||
this.cache.set(
|
||||
path,
|
||||
this.httpClient
|
||||
.get(`assets/content/${path}`, {
|
||||
responseType: 'text',
|
||||
})
|
||||
.pipe(map((contents) => ({contents, id: path})))
|
||||
.toPromise()
|
||||
);
|
||||
.get(`assets/content/${path}`, {
|
||||
responseType: 'text',
|
||||
})
|
||||
.pipe(map((contents) => ({contents, id: path})))
|
||||
.toPromise(),
|
||||
);
|
||||
} catch {
|
||||
this.router.navigateByUrl('/404');
|
||||
}
|
||||
|
||||
@@ -16,10 +16,7 @@ import {NodeRuntimeSandbox} from '../node-runtime-sandbox.service';
|
||||
import {EmbeddedTutorialManager} from '../embedded-tutorial-manager.service';
|
||||
|
||||
import {CodeMirrorEditor, EDITOR_CONTENT_CHANGE_DELAY_MILLIES} from './code-mirror-editor.service';
|
||||
import {
|
||||
TutorialConfig,
|
||||
TutorialMetadata,
|
||||
} from '@angular/docs';
|
||||
import {TutorialConfig, TutorialMetadata} from '@angular/docs';
|
||||
|
||||
class FakeNodeRuntimeSandbox {
|
||||
async writeFile(path: string, content: string) {}
|
||||
|
||||
@@ -13,5 +13,4 @@ export const TUTORIALS_ASSETS_METADATA_DIRECTORY = 'metadata';
|
||||
export const TUTORIALS_SOURCE_CODE_WEB_PATH = `${TUTORIALS_ASSETS_WEB_PATH}/${TUTORIALS_ASSETS_SOURCE_CODE_DIRECTORY}`;
|
||||
export const TUTORIALS_METADATA_WEB_PATH = `${TUTORIALS_ASSETS_WEB_PATH}/${TUTORIALS_ASSETS_METADATA_DIRECTORY}`;
|
||||
|
||||
|
||||
export const TUTORIALS_COMMON_DIRECTORY = 'common';
|
||||
export const TUTORIALS_COMMON_DIRECTORY = 'common';
|
||||
|
||||
@@ -245,7 +245,7 @@ describe('EmbeddedTutorialManager', () => {
|
||||
},
|
||||
},
|
||||
};
|
||||
|
||||
|
||||
const metadata: TutorialMetadata = {
|
||||
tutorialFiles: {'app.js': ''},
|
||||
openFiles: ['app.js'],
|
||||
@@ -295,7 +295,6 @@ describe('EmbeddedTutorialManager', () => {
|
||||
);
|
||||
});
|
||||
|
||||
|
||||
it('should not set shouldReinstallDependencies if project did not change', async () => {
|
||||
const fetchMock = spyOn(window, 'fetch');
|
||||
|
||||
@@ -325,7 +324,6 @@ describe('EmbeddedTutorialManager', () => {
|
||||
it('should trigger shouldReInstallDependencies if new metadata has different dependencies', async () => {
|
||||
const fetchMock = spyOn(window, 'fetch');
|
||||
|
||||
|
||||
fetchMock
|
||||
.withArgs(`${TUTORIALS_ASSETS_WEB_PATH}/${tutorial}/source-code.json`)
|
||||
.and.returnValues(Promise.resolve(new Response('{}', {status: 200})));
|
||||
|
||||
@@ -11,10 +11,7 @@ import {FileSystemTree} from '@webcontainer/api';
|
||||
import {BehaviorSubject} from 'rxjs';
|
||||
|
||||
import {TutorialMetadata} from '@angular/docs';
|
||||
import {
|
||||
TUTORIALS_COMMON_DIRECTORY,
|
||||
TUTORIALS_ASSETS_WEB_PATH
|
||||
} from './constants';
|
||||
import {TUTORIALS_COMMON_DIRECTORY, TUTORIALS_ASSETS_WEB_PATH} from './constants';
|
||||
|
||||
/**
|
||||
* A service responsible for the current tutorial, retrieving and providing
|
||||
@@ -140,7 +137,9 @@ export class EmbeddedTutorialManager {
|
||||
}
|
||||
|
||||
private async fetchTutorialSourceCode(tutorial: string): Promise<FileSystemTree> {
|
||||
const tutorialSourceCode = await fetch(`${TUTORIALS_ASSETS_WEB_PATH}/${tutorial}/source-code.json`);
|
||||
const tutorialSourceCode = await fetch(
|
||||
`${TUTORIALS_ASSETS_WEB_PATH}/${tutorial}/source-code.json`,
|
||||
);
|
||||
|
||||
if (!tutorialSourceCode.ok) throw new Error(`Missing source code for tutorial ${tutorial}`);
|
||||
|
||||
@@ -148,7 +147,9 @@ export class EmbeddedTutorialManager {
|
||||
}
|
||||
|
||||
private async fetchTutorialMetadata(tutorial: string): Promise<TutorialMetadata> {
|
||||
const tutorialSourceCode = await fetch(`${TUTORIALS_ASSETS_WEB_PATH}/${tutorial}/metadata.json`);
|
||||
const tutorialSourceCode = await fetch(
|
||||
`${TUTORIALS_ASSETS_WEB_PATH}/${tutorial}/metadata.json`,
|
||||
);
|
||||
|
||||
if (!tutorialSourceCode.ok) throw new Error(`Missing metadata for ${tutorial}`);
|
||||
|
||||
|
||||
@@ -1,8 +1,7 @@
|
||||
export { EmbeddedTutorialManager } from './embedded-tutorial-manager.service'
|
||||
export { LoadingStep } from './enums/loading-steps'
|
||||
export { NodeRuntimeState } from './node-runtime-state.service'
|
||||
export {EmbeddedTutorialManager} from './embedded-tutorial-manager.service';
|
||||
export {LoadingStep} from './enums/loading-steps';
|
||||
export {NodeRuntimeState} from './node-runtime-state.service';
|
||||
|
||||
export { NodeRuntimeSandbox } from './node-runtime-sandbox.service'
|
||||
|
||||
export {EmbeddedEditor, EMBEDDED_EDITOR_SELECTOR} from './embedded-editor.component'
|
||||
export {NodeRuntimeSandbox} from './node-runtime-sandbox.service';
|
||||
|
||||
export {EmbeddedEditor, EMBEDDED_EDITOR_SELECTOR} from './embedded-editor.component';
|
||||
|
||||
@@ -12,10 +12,7 @@ import {BehaviorSubject, of as observableOf} from 'rxjs';
|
||||
import {signal} from '@angular/core';
|
||||
import {WebContainer} from '@webcontainer/api';
|
||||
import {TutorialType} from '@angular/docs';
|
||||
import {
|
||||
FakeWebContainer,
|
||||
FakeWebContainerProcess,
|
||||
} from '@angular/docs/testing';
|
||||
import {FakeWebContainer, FakeWebContainerProcess} from '@angular/docs/testing';
|
||||
import {AlertManager} from './alert-manager.service';
|
||||
import {EmbeddedTutorialManager} from './embedded-tutorial-manager.service';
|
||||
import {LoadingStep} from './enums/loading-steps';
|
||||
|
||||
@@ -16,7 +16,7 @@ import {
|
||||
} from '@angular/core';
|
||||
|
||||
import {injectAsync} from '../../../core/services/inject-async';
|
||||
import { EmbeddedEditor, EmbeddedTutorialManager } from '../../../editor';
|
||||
import {EmbeddedEditor, EmbeddedTutorialManager} from '../../../editor';
|
||||
|
||||
@Component({
|
||||
selector: 'adev-code-editor',
|
||||
@@ -39,9 +39,7 @@ export class CodeEditorComponent implements OnInit {
|
||||
|
||||
private async loadEmbeddedEditor() {
|
||||
const nodeRuntimeSandbox = await injectAsync(this.environmentInjector, () =>
|
||||
import('../../../editor/index').then(
|
||||
(c) => c.NodeRuntimeSandbox,
|
||||
),
|
||||
import('../../../editor/index').then((c) => c.NodeRuntimeSandbox),
|
||||
);
|
||||
|
||||
await this.embeddedTutorialManager.fetchAndSetTutorialFiles(this.tutorialFiles);
|
||||
|
||||
@@ -31,7 +31,10 @@ export class BuildText extends View {
|
||||
/**
|
||||
* Create the build text.
|
||||
*/
|
||||
constructor(private readonly gl: OGLRenderingContext, private readonly document: Document) {
|
||||
constructor(
|
||||
private readonly gl: OGLRenderingContext,
|
||||
private readonly document: Document,
|
||||
) {
|
||||
super();
|
||||
|
||||
this.userData['x'] = 0;
|
||||
|
||||
@@ -27,7 +27,10 @@ export class BuildView extends View {
|
||||
/**
|
||||
* Create the build view.
|
||||
*/
|
||||
constructor(private readonly gl: OGLRenderingContext, private readonly document: Document) {
|
||||
constructor(
|
||||
private readonly gl: OGLRenderingContext,
|
||||
private readonly document: Document,
|
||||
) {
|
||||
super();
|
||||
|
||||
this.visible = false;
|
||||
|
||||
@@ -34,7 +34,10 @@ export class Lines extends View {
|
||||
/**
|
||||
* Create the container view.
|
||||
*/
|
||||
constructor(private readonly gl: OGLRenderingContext, private readonly divisions: number) {
|
||||
constructor(
|
||||
private readonly gl: OGLRenderingContext,
|
||||
private readonly divisions: number,
|
||||
) {
|
||||
super();
|
||||
|
||||
this.userData['x'] = 0;
|
||||
|
||||
@@ -23,7 +23,7 @@ import {RouterLink} from '@angular/router';
|
||||
import {PlaygroundTemplate} from '@angular/docs';
|
||||
import {ClickOutside, NavigationList} from '@angular/docs';
|
||||
import {injectAsync} from '../../core/services/inject-async';
|
||||
import {EmbeddedTutorialManager} from '../../editor/index';
|
||||
import {EmbeddedTutorialManager} from '../../editor/index';
|
||||
|
||||
import PLAYGROUND_ROUTE_DATA_JSON from '../../../../src/assets/tutorials/playground/routes.json';
|
||||
import {CdkMenu, CdkMenuItem, CdkMenuTrigger} from '@angular/cdk/menu';
|
||||
@@ -69,9 +69,7 @@ export default class PlaygroundComponent implements AfterViewInit {
|
||||
const [embeddedEditorComponent, nodeRuntimeSandbox] = await Promise.all([
|
||||
import('../../editor/index').then((c) => c.EmbeddedEditor),
|
||||
injectAsync(this.environmentInjector, () =>
|
||||
import('../../editor/index').then(
|
||||
(c) => c.NodeRuntimeSandbox,
|
||||
),
|
||||
import('../../editor/index').then((c) => c.NodeRuntimeSandbox),
|
||||
),
|
||||
]);
|
||||
|
||||
|
||||
+1
-1
@@ -59,7 +59,7 @@ export default class CliReferenceDetailsPage implements OnInit {
|
||||
private setPageContent(): void {
|
||||
this.activatedRoute.data
|
||||
.pipe(
|
||||
map(data => data['docContent']),
|
||||
map((data) => data['docContent']),
|
||||
takeUntilDestroyed(this.destroyRef),
|
||||
)
|
||||
.subscribe((doc: DocContent | undefined) => {
|
||||
|
||||
@@ -18,12 +18,12 @@ import {
|
||||
EMBEDDED_EDITOR_SELECTOR,
|
||||
EmbeddedEditor,
|
||||
EmbeddedTutorialManager,
|
||||
NodeRuntimeSandbox
|
||||
NodeRuntimeSandbox,
|
||||
} from '../../editor';
|
||||
|
||||
import {mockAsyncProvider} from '../../core/services/inject-async';
|
||||
import Tutorial from './tutorial.component';
|
||||
import {TutorialConfig, TutorialType} from '@angular/docs'
|
||||
import {TutorialConfig, TutorialType} from '@angular/docs';
|
||||
|
||||
@Component({
|
||||
selector: EMBEDDED_EDITOR_SELECTOR,
|
||||
|
||||
@@ -38,11 +38,11 @@ import {
|
||||
EmbeddedTutorialManager,
|
||||
LoadingStep,
|
||||
NodeRuntimeState,
|
||||
EmbeddedEditor
|
||||
EmbeddedEditor,
|
||||
} from '../../editor/index';
|
||||
import {SplitResizerHandler} from './split-resizer-handler.service';
|
||||
import { TutorialType } from '@angular/docs';
|
||||
import { TutorialNavigationData, TutorialNavigationItem, } from '@angular/docs'
|
||||
import {TutorialType} from '@angular/docs';
|
||||
import {TutorialNavigationData, TutorialNavigationItem} from '@angular/docs';
|
||||
|
||||
const INTRODUCTION_LABEL = 'Introduction';
|
||||
|
||||
@@ -138,9 +138,7 @@ export default class Tutorial implements AfterViewInit {
|
||||
this.embeddedTutorialManager.revealAnswer();
|
||||
|
||||
const nodeRuntimeSandbox = await injectAsync(this.environmentInjector, () =>
|
||||
import('../../editor/index').then(
|
||||
(s) => s.NodeRuntimeSandbox,
|
||||
),
|
||||
import('../../editor/index').then((s) => s.NodeRuntimeSandbox),
|
||||
);
|
||||
|
||||
await Promise.all(
|
||||
@@ -213,16 +211,10 @@ export default class Tutorial implements AfterViewInit {
|
||||
|
||||
this.shouldRenderContent.set(routeData.type !== TutorialType.EDITOR_ONLY);
|
||||
|
||||
this.nextStepPath = routeData.nextStep
|
||||
? `/${routeData.nextStep}`
|
||||
: undefined;
|
||||
this.previousStepPath = routeData.previousStep
|
||||
? `/${routeData.previousStep}`
|
||||
: undefined;
|
||||
this.nextStepPath = routeData.nextStep ? `/${routeData.nextStep}` : undefined;
|
||||
this.previousStepPath = routeData.previousStep ? `/${routeData.previousStep}` : undefined;
|
||||
|
||||
this.nextTutorialPath.set(
|
||||
routeData.nextTutorial ? `/${routeData.nextTutorial}` : null,
|
||||
);
|
||||
this.nextTutorialPath.set(routeData.nextTutorial ? `/${routeData.nextTutorial}` : null);
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@@ -6,11 +6,7 @@
|
||||
* found in the LICENSE file at https://angular.dev/license
|
||||
*/
|
||||
|
||||
import {
|
||||
contentResolver,
|
||||
flatNavigationData,
|
||||
mapNavigationItemsToRoutes,
|
||||
} from '@angular/docs';
|
||||
import {contentResolver, flatNavigationData, mapNavigationItemsToRoutes} from '@angular/docs';
|
||||
import {Route} from '@angular/router';
|
||||
|
||||
import {DefaultPage, PagePrefix} from './core/enums/pages';
|
||||
@@ -125,7 +121,7 @@ export const routes: Route[] = [
|
||||
{
|
||||
path: '',
|
||||
loadComponent: () => import('./features/home/home.component'),
|
||||
data: {label: 'Home'}
|
||||
data: {label: 'Home'},
|
||||
},
|
||||
{
|
||||
path: PagePrefix.DOCS,
|
||||
|
||||
@@ -943,7 +943,7 @@ export const TUTORIALS_SUB_NAVIGATION_DATA: NavigationItem[] = [
|
||||
{
|
||||
path: DefaultPage.TUTORIALS,
|
||||
contentPath: 'tutorials/home',
|
||||
label: 'Tutorials'
|
||||
label: 'Tutorials',
|
||||
},
|
||||
];
|
||||
|
||||
|
||||
@@ -18,5 +18,4 @@ import {Type} from '@angular/core';
|
||||
* Map of the previews components, values are functions which returns the promise of the component type, which will be displayed as preview in the ExampleViewer component.
|
||||
* Keys has to be equal to paths written down in the docs markdown files.
|
||||
*/
|
||||
export const PREVIEWS_COMPONENTS_MAP: Record<string, () => Promise<Type<unknown>>> = {
|
||||
};
|
||||
export const PREVIEWS_COMPONENTS_MAP: Record<string, () => Promise<Type<unknown>>> = {};
|
||||
|
||||
@@ -82,7 +82,10 @@ export class NgComponentOutletCompleteExample implements OnInit {
|
||||
@ViewChild('svet', {static: true}) svetTemplateRef!: TemplateRef<any>;
|
||||
myContent?: any[][];
|
||||
|
||||
constructor(injector: Injector, private vcr: ViewContainerRef) {
|
||||
constructor(
|
||||
injector: Injector,
|
||||
private vcr: ViewContainerRef,
|
||||
) {
|
||||
this.myInjector = Injector.create({
|
||||
providers: [{provide: Greeter, deps: []}],
|
||||
parent: injector,
|
||||
|
||||
@@ -51,7 +51,10 @@ class DataListProvider {
|
||||
`,
|
||||
})
|
||||
class GiantList {
|
||||
constructor(private ref: ChangeDetectorRef, public dataProvider: DataListProvider) {
|
||||
constructor(
|
||||
private ref: ChangeDetectorRef,
|
||||
public dataProvider: DataListProvider,
|
||||
) {
|
||||
ref.detach();
|
||||
setInterval(() => {
|
||||
this.ref.detectChanges();
|
||||
@@ -81,7 +84,10 @@ class DataProvider {
|
||||
|
||||
@Component({selector: 'live-data', inputs: ['live'], template: 'Data: {{dataProvider.data}}'})
|
||||
class LiveData {
|
||||
constructor(private ref: ChangeDetectorRef, public dataProvider: DataProvider) {}
|
||||
constructor(
|
||||
private ref: ChangeDetectorRef,
|
||||
public dataProvider: DataProvider,
|
||||
) {}
|
||||
|
||||
@Input()
|
||||
set live(value: boolean) {
|
||||
|
||||
+4
-1
@@ -70,7 +70,10 @@ describe('navigate for test examples', () => {
|
||||
`,
|
||||
})
|
||||
class SearchCmp {
|
||||
constructor(readonly route: ActivatedRoute, readonly router: Router) {}
|
||||
constructor(
|
||||
readonly route: ActivatedRoute,
|
||||
readonly router: Router,
|
||||
) {}
|
||||
|
||||
async searchFor(thing: string) {
|
||||
await this.router.navigate([], {queryParams: {query: thing}});
|
||||
|
||||
@@ -1,7 +1,6 @@
|
||||
import { browser, element, by } from 'protractor';
|
||||
import {browser, element, by} from 'protractor';
|
||||
|
||||
describe('Accessibility example e2e tests', () => {
|
||||
|
||||
beforeEach(() => browser.get(''));
|
||||
|
||||
it('should display Accessibility Example', async () => {
|
||||
@@ -13,5 +12,4 @@ describe('Accessibility example e2e tests', () => {
|
||||
expect(await element(by.css('input')).getAttribute('value')).toEqual('16');
|
||||
expect(await element(by.css('app-example-progressbar div')).getCssValue('width')).toBe('48px');
|
||||
});
|
||||
|
||||
});
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
import { AppPage } from './app.po';
|
||||
import { browser, logging } from 'protractor';
|
||||
import {AppPage} from './app.po';
|
||||
import {browser, logging} from 'protractor';
|
||||
|
||||
describe('workspace-project App', () => {
|
||||
let page: AppPage;
|
||||
@@ -13,8 +13,10 @@ describe('workspace-project App', () => {
|
||||
afterEach(async () => {
|
||||
// Assert that there are no errors emitted from the browser
|
||||
const logs = await browser.manage().logs().get(logging.Type.BROWSER);
|
||||
expect(logs).not.toContain(jasmine.objectContaining({
|
||||
level: logging.Level.SEVERE,
|
||||
} as logging.Entry));
|
||||
expect(logs).not.toContain(
|
||||
jasmine.objectContaining({
|
||||
level: logging.Level.SEVERE,
|
||||
} as logging.Entry),
|
||||
);
|
||||
});
|
||||
});
|
||||
|
||||
@@ -1,12 +1,10 @@
|
||||
import { TestBed } from '@angular/core/testing';
|
||||
import { AppComponent } from './app.component';
|
||||
import {TestBed} from '@angular/core/testing';
|
||||
import {AppComponent} from './app.component';
|
||||
|
||||
describe('AppComponent', () => {
|
||||
beforeEach(async () => {
|
||||
await TestBed.configureTestingModule({
|
||||
declarations: [
|
||||
AppComponent
|
||||
],
|
||||
declarations: [AppComponent],
|
||||
}).compileComponents();
|
||||
});
|
||||
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
import { browser } from 'protractor';
|
||||
import { logging } from 'selenium-webdriver';
|
||||
import {browser} from 'protractor';
|
||||
import {logging} from 'selenium-webdriver';
|
||||
import * as openClose from './open-close.po';
|
||||
import * as statusSlider from './status-slider.po';
|
||||
import * as toggle from './toggle.po';
|
||||
@@ -7,8 +7,8 @@ import * as enterLeave from './enter-leave.po';
|
||||
import * as auto from './auto.po';
|
||||
import * as filterStagger from './filter-stagger.po';
|
||||
import * as heroGroups from './hero-groups';
|
||||
import { getLinkById, sleepFor } from './util';
|
||||
import { getComponentSection, getToggleButton } from './querying.po';
|
||||
import {getLinkById, sleepFor} from './util';
|
||||
import {getComponentSection, getToggleButton} from './querying.po';
|
||||
|
||||
describe('Animation Tests', () => {
|
||||
const routingAnimationDuration = 350;
|
||||
@@ -42,7 +42,10 @@ describe('Animation Tests', () => {
|
||||
|
||||
if (text.includes('Closed')) {
|
||||
await toggleButton.click();
|
||||
await browser.wait(async () => await container.getCssValue('height') === openHeight, 2000);
|
||||
await browser.wait(
|
||||
async () => (await container.getCssValue('height')) === openHeight,
|
||||
2000,
|
||||
);
|
||||
}
|
||||
|
||||
text = await container.getText();
|
||||
@@ -59,7 +62,10 @@ describe('Animation Tests', () => {
|
||||
|
||||
if (text.includes('Open')) {
|
||||
await toggleButton.click();
|
||||
await browser.wait(async () => await container.getCssValue('height') === closedHeight, 2000);
|
||||
await browser.wait(
|
||||
async () => (await container.getCssValue('height')) === closedHeight,
|
||||
2000,
|
||||
);
|
||||
}
|
||||
|
||||
text = await container.getText();
|
||||
@@ -76,7 +82,7 @@ describe('Animation Tests', () => {
|
||||
await toggleButton.click();
|
||||
|
||||
const logs = await browser.manage().logs().get(logging.Type.BROWSER);
|
||||
const animationMessages = logs.filter(({ message }) => message.includes('Animation'));
|
||||
const animationMessages = logs.filter(({message}) => message.includes('Animation'));
|
||||
|
||||
expect(animationMessages.length).toBeGreaterThan(0);
|
||||
});
|
||||
@@ -98,7 +104,10 @@ describe('Animation Tests', () => {
|
||||
|
||||
if (text === 'Active') {
|
||||
await toggleButton.click();
|
||||
await browser.wait(async () => await container.getCssValue('backgroundColor') === inactiveColor, 3000);
|
||||
await browser.wait(
|
||||
async () => (await container.getCssValue('backgroundColor')) === inactiveColor,
|
||||
3000,
|
||||
);
|
||||
}
|
||||
|
||||
text = await container.getText();
|
||||
@@ -115,7 +124,10 @@ describe('Animation Tests', () => {
|
||||
|
||||
if (text === 'Inactive') {
|
||||
await toggleButton.click();
|
||||
await browser.wait(async () => await container.getCssValue('backgroundColor') === activeColor, 3000);
|
||||
await browser.wait(
|
||||
async () => (await container.getCssValue('backgroundColor')) === activeColor,
|
||||
3000,
|
||||
);
|
||||
}
|
||||
|
||||
text = await container.getText();
|
||||
@@ -166,7 +178,7 @@ describe('Animation Tests', () => {
|
||||
const hero = heroesList.get(0);
|
||||
|
||||
await hero.click();
|
||||
await browser.wait(async () => await heroesList.count() < total, 2000);
|
||||
await browser.wait(async () => (await heroesList.count()) < total, 2000);
|
||||
});
|
||||
});
|
||||
|
||||
@@ -190,7 +202,7 @@ describe('Animation Tests', () => {
|
||||
const hero = heroesList.get(0);
|
||||
|
||||
await hero.click();
|
||||
await browser.wait(async () => await heroesList.count() < total, 2000);
|
||||
await browser.wait(async () => (await heroesList.count()) < total, 2000);
|
||||
});
|
||||
});
|
||||
|
||||
@@ -214,7 +226,7 @@ describe('Animation Tests', () => {
|
||||
const input = filterStagger.getInput();
|
||||
await input.sendKeys('Mag');
|
||||
|
||||
await browser.wait(async () => await heroesList.count() === 2, 2000);
|
||||
await browser.wait(async () => (await heroesList.count()) === 2, 2000);
|
||||
|
||||
const newTotal = await heroesList.count();
|
||||
expect(newTotal).toBeLessThan(total);
|
||||
@@ -245,7 +257,7 @@ describe('Animation Tests', () => {
|
||||
const hero = heroesList.get(0);
|
||||
|
||||
await hero.click();
|
||||
await browser.wait(async () => await heroesList.count() < total, 2000);
|
||||
await browser.wait(async () => (await heroesList.count()) < total, 2000);
|
||||
});
|
||||
});
|
||||
|
||||
@@ -291,6 +303,5 @@ describe('Animation Tests', () => {
|
||||
await newPageSleepFor(queryingAnimationDuration);
|
||||
expect(await toggleButton.isEnabled()).toBe(true);
|
||||
});
|
||||
|
||||
});
|
||||
});
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
import { by } from 'protractor';
|
||||
import { locate } from './util';
|
||||
import {by} from 'protractor';
|
||||
import {locate} from './util';
|
||||
|
||||
export function getPage() {
|
||||
return by.css('app-hero-list-auto-page');
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
import { by } from 'protractor';
|
||||
import { locate } from './util';
|
||||
import {by} from 'protractor';
|
||||
import {locate} from './util';
|
||||
|
||||
export function getPage() {
|
||||
return by.css('app-hero-list-enter-leave-page');
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
import { by } from 'protractor';
|
||||
import { locate } from './util';
|
||||
import {by} from 'protractor';
|
||||
import {locate} from './util';
|
||||
|
||||
export function getPage() {
|
||||
return by.css('app-hero-list-page');
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
import { by } from 'protractor';
|
||||
import { locate } from './util';
|
||||
import {by} from 'protractor';
|
||||
import {locate} from './util';
|
||||
|
||||
export function getPage() {
|
||||
return by.css('app-hero-list-groups-page');
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
import { by } from 'protractor';
|
||||
import { locate } from './util';
|
||||
import {by} from 'protractor';
|
||||
import {locate} from './util';
|
||||
|
||||
export function getPage() {
|
||||
return by.css('app-open-close-page');
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
import { by } from 'protractor';
|
||||
import { locate } from './util';
|
||||
import {by} from 'protractor';
|
||||
import {locate} from './util';
|
||||
|
||||
export function getComponent() {
|
||||
return by.css('app-querying');
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
import { by } from 'protractor';
|
||||
import { locate } from './util';
|
||||
import {by} from 'protractor';
|
||||
import {locate} from './util';
|
||||
|
||||
export function getPage() {
|
||||
return by.css('app-status-slider-page');
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
import { by } from 'protractor';
|
||||
import { locate } from './util';
|
||||
import {by} from 'protractor';
|
||||
import {locate} from './util';
|
||||
|
||||
export function getPage() {
|
||||
return by.css('app-toggle-animations-child-page');
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
import { Locator, ElementFinder, browser, by, element } from 'protractor';
|
||||
import {Locator, ElementFinder, browser, by, element} from 'protractor';
|
||||
|
||||
/**
|
||||
*
|
||||
@@ -6,8 +6,9 @@ import { Locator, ElementFinder, browser, by, element } from 'protractor';
|
||||
*/
|
||||
export function locate(locator: Locator, ...locators: Locator[]) {
|
||||
return locators.reduce(
|
||||
(current: ElementFinder, next: Locator) => current.element(next),
|
||||
element(locator)) as ElementFinder;
|
||||
(current: ElementFinder, next: Locator) => current.element(next),
|
||||
element(locator),
|
||||
) as ElementFinder;
|
||||
}
|
||||
|
||||
export async function sleepFor(time = 1000) {
|
||||
|
||||
@@ -1,9 +1,9 @@
|
||||
import { Component } from '@angular/core';
|
||||
import {Component} from '@angular/core';
|
||||
|
||||
@Component({
|
||||
standalone: true,
|
||||
selector: 'app-about',
|
||||
templateUrl: './about.component.html',
|
||||
styleUrls: ['./about.component.css']
|
||||
styleUrls: ['./about.component.css'],
|
||||
})
|
||||
export class AboutComponent {}
|
||||
|
||||
@@ -1,15 +1,15 @@
|
||||
// #docplaster
|
||||
// #docregion animation-const, trigger-const
|
||||
import { animation, style, animate, trigger, transition, useAnimation } from '@angular/animations';
|
||||
import {animation, style, animate, trigger, transition, useAnimation} from '@angular/animations';
|
||||
// #enddocregion trigger-const
|
||||
|
||||
export const transitionAnimation = animation([
|
||||
style({
|
||||
height: '{{ height }}',
|
||||
opacity: '{{ opacity }}',
|
||||
backgroundColor: '{{ backgroundColor }}'
|
||||
backgroundColor: '{{ backgroundColor }}',
|
||||
}),
|
||||
animate('{{ time }}')
|
||||
animate('{{ time }}'),
|
||||
]);
|
||||
// #enddocregion animation-const
|
||||
|
||||
@@ -21,9 +21,9 @@ export const triggerAnimation = trigger('openClose', [
|
||||
height: 0,
|
||||
opacity: 1,
|
||||
backgroundColor: 'red',
|
||||
time: '1s'
|
||||
}
|
||||
})
|
||||
])
|
||||
time: '1s',
|
||||
},
|
||||
}),
|
||||
]),
|
||||
]);
|
||||
// #enddocregion trigger-const
|
||||
|
||||
@@ -1,71 +1,71 @@
|
||||
import {
|
||||
animation, trigger, animateChild, group,
|
||||
transition, animate, style, query
|
||||
animation,
|
||||
trigger,
|
||||
animateChild,
|
||||
group,
|
||||
transition,
|
||||
animate,
|
||||
style,
|
||||
query,
|
||||
} from '@angular/animations';
|
||||
|
||||
export const transitionAnimation = animation([
|
||||
style({
|
||||
height: '{{ height }}',
|
||||
opacity: '{{ opacity }}',
|
||||
backgroundColor: '{{ backgroundColor }}'
|
||||
backgroundColor: '{{ backgroundColor }}',
|
||||
}),
|
||||
animate('{{ time }}')
|
||||
animate('{{ time }}'),
|
||||
]);
|
||||
|
||||
// Routable animations
|
||||
// #docregion route-animations
|
||||
export const slideInAnimation =
|
||||
// #docregion style-view
|
||||
// #docregion style-view
|
||||
trigger('routeAnimations', [
|
||||
transition('HomePage <=> AboutPage', [
|
||||
style({ position: 'relative' }),
|
||||
style({position: 'relative'}),
|
||||
query(':enter, :leave', [
|
||||
style({
|
||||
position: 'absolute',
|
||||
top: 0,
|
||||
left: 0,
|
||||
width: '100%'
|
||||
})
|
||||
width: '100%',
|
||||
}),
|
||||
]),
|
||||
// #enddocregion style-view
|
||||
// #docregion query
|
||||
query(':enter', [
|
||||
style({ left: '-100%' })
|
||||
], { optional: true }),
|
||||
query(':leave', animateChild(), { optional: true }),
|
||||
// #enddocregion style-view
|
||||
// #docregion query
|
||||
query(':enter', [style({left: '-100%'})], {optional: true}),
|
||||
query(':leave', animateChild(), {optional: true}),
|
||||
group([
|
||||
query(':leave', [
|
||||
animate('300ms ease-out', style({ left: '100%' }))
|
||||
], { optional: true }),
|
||||
query(':enter', [
|
||||
animate('300ms ease-out', style({ left: '0%' }))
|
||||
], { optional: true }),
|
||||
query(':leave', [animate('300ms ease-out', style({left: '100%'}))], {optional: true}),
|
||||
query(':enter', [animate('300ms ease-out', style({left: '0%'}))], {optional: true}),
|
||||
]),
|
||||
]),
|
||||
transition('* <=> *', [
|
||||
style({ position: 'relative' }),
|
||||
query(':enter, :leave', [
|
||||
style({
|
||||
position: 'absolute',
|
||||
top: 0,
|
||||
left: 0,
|
||||
width: '100%'
|
||||
})
|
||||
], { optional: true }),
|
||||
query(':enter', [
|
||||
style({ left: '-100%' })
|
||||
], { optional: true }),
|
||||
query(':leave', animateChild(), { optional: true }),
|
||||
style({position: 'relative'}),
|
||||
query(
|
||||
':enter, :leave',
|
||||
[
|
||||
style({
|
||||
position: 'absolute',
|
||||
top: 0,
|
||||
left: 0,
|
||||
width: '100%',
|
||||
}),
|
||||
],
|
||||
{optional: true},
|
||||
),
|
||||
query(':enter', [style({left: '-100%'})], {optional: true}),
|
||||
query(':leave', animateChild(), {optional: true}),
|
||||
group([
|
||||
query(':leave', [
|
||||
animate('200ms ease-out', style({ left: '100%', opacity: 0 }))
|
||||
], { optional: true }),
|
||||
query(':enter', [
|
||||
animate('300ms ease-out', style({ left: '0%' }))
|
||||
], { optional: true }),
|
||||
query('@*', animateChild(), { optional: true })
|
||||
query(':leave', [animate('200ms ease-out', style({left: '100%', opacity: 0}))], {
|
||||
optional: true,
|
||||
}),
|
||||
query(':enter', [animate('300ms ease-out', style({left: '0%'}))], {optional: true}),
|
||||
query('@*', animateChild(), {optional: true}),
|
||||
]),
|
||||
])
|
||||
]),
|
||||
// #enddocregion query
|
||||
]);
|
||||
// #enddocregion route-animations
|
||||
// #enddocregion route-animations
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
// #docplaster
|
||||
// #docregion imports
|
||||
import { Component, HostBinding } from '@angular/core';
|
||||
import {Component, HostBinding} from '@angular/core';
|
||||
import {
|
||||
trigger,
|
||||
state,
|
||||
@@ -11,8 +11,8 @@ import {
|
||||
} from '@angular/animations';
|
||||
|
||||
// #enddocregion imports
|
||||
import { ChildrenOutletContexts, RouterLink, RouterOutlet } from '@angular/router';
|
||||
import { slideInAnimation } from './animations';
|
||||
import {ChildrenOutletContexts, RouterLink, RouterOutlet} from '@angular/router';
|
||||
import {slideInAnimation} from './animations';
|
||||
|
||||
// #docregion decorator, toggle-app-animations, define
|
||||
@Component({
|
||||
@@ -22,31 +22,31 @@ import { slideInAnimation } from './animations';
|
||||
styleUrls: ['app.component.css'],
|
||||
imports: [RouterLink, RouterOutlet],
|
||||
animations: [
|
||||
// #enddocregion decorator
|
||||
slideInAnimation
|
||||
// #docregion decorator
|
||||
// #enddocregion toggle-app-animations, define
|
||||
// #enddocregion decorator
|
||||
slideInAnimation,
|
||||
// #docregion decorator
|
||||
// #enddocregion toggle-app-animations, define
|
||||
// animation triggers go here
|
||||
// #docregion toggle-app-animations, define
|
||||
]
|
||||
// #docregion toggle-app-animations, define
|
||||
],
|
||||
})
|
||||
// #enddocregion decorator, define
|
||||
export class AppComponent {
|
||||
@HostBinding('@.disabled')
|
||||
public animationsDisabled = false;
|
||||
// #enddocregion toggle-app-animations
|
||||
// #enddocregion toggle-app-animations
|
||||
|
||||
// #docregion get-route-animations-data
|
||||
// #docregion get-route-animations-data
|
||||
constructor(private contexts: ChildrenOutletContexts) {}
|
||||
|
||||
getRouteAnimationData() {
|
||||
return this.contexts.getContext('primary')?.route?.snapshot?.data?.['animation'];
|
||||
}
|
||||
// #enddocregion get-route-animations-data
|
||||
// #enddocregion get-route-animations-data
|
||||
|
||||
toggleAnimations() {
|
||||
this.animationsDisabled = !this.animationsDisabled;
|
||||
}
|
||||
// #docregion toggle-app-animations
|
||||
// #docregion toggle-app-animations
|
||||
}
|
||||
// #enddocregion toggle-app-animations
|
||||
|
||||
@@ -1,15 +1,14 @@
|
||||
import { ApplicationConfig } from '@angular/core';
|
||||
import { routes } from './app.routes';
|
||||
import { provideRouter } from '@angular/router';
|
||||
import { provideProtractorTestingSupport } from '@angular/platform-browser';
|
||||
import { provideAnimations } from '@angular/platform-browser/animations';
|
||||
|
||||
import {ApplicationConfig} from '@angular/core';
|
||||
import {routes} from './app.routes';
|
||||
import {provideRouter} from '@angular/router';
|
||||
import {provideProtractorTestingSupport} from '@angular/platform-browser';
|
||||
import {provideAnimations} from '@angular/platform-browser/animations';
|
||||
|
||||
export const appConfig: ApplicationConfig = {
|
||||
providers: [
|
||||
// needed for supporting e2e tests
|
||||
provideProtractorTestingSupport(),
|
||||
provideRouter(routes),
|
||||
provideAnimations(),
|
||||
]
|
||||
providers: [
|
||||
// needed for supporting e2e tests
|
||||
provideProtractorTestingSupport(),
|
||||
provideRouter(routes),
|
||||
provideAnimations(),
|
||||
],
|
||||
};
|
||||
|
||||
@@ -1,13 +1,10 @@
|
||||
import { NgModule } from '@angular/core';
|
||||
import { BrowserModule } from '@angular/platform-browser';
|
||||
import { BrowserAnimationsModule } from '@angular/platform-browser/animations';
|
||||
import {NgModule} from '@angular/core';
|
||||
import {BrowserModule} from '@angular/platform-browser';
|
||||
import {BrowserAnimationsModule} from '@angular/platform-browser/animations';
|
||||
|
||||
@NgModule({
|
||||
imports: [
|
||||
BrowserModule,
|
||||
BrowserAnimationsModule
|
||||
],
|
||||
declarations: [ ],
|
||||
bootstrap: [ ]
|
||||
imports: [BrowserModule, BrowserAnimationsModule],
|
||||
declarations: [],
|
||||
bootstrap: [],
|
||||
})
|
||||
export class AppModule { }
|
||||
export class AppModule {}
|
||||
|
||||
@@ -1,73 +1,73 @@
|
||||
import { Routes } from '@angular/router';
|
||||
import { OpenClosePageComponent } from './open-close-page.component';
|
||||
import { StatusSliderPageComponent } from './status-slider-page.component';
|
||||
import { ToggleAnimationsPageComponent } from './toggle-animations-page.component';
|
||||
import { HeroListPageComponent } from './hero-list-page.component';
|
||||
import { HeroListGroupPageComponent } from './hero-list-group-page.component';
|
||||
import { HeroListEnterLeavePageComponent } from './hero-list-enter-leave-page.component';
|
||||
import { HeroListAutoCalcPageComponent } from './hero-list-auto-page.component';
|
||||
import { InsertRemoveComponent } from './insert-remove.component';
|
||||
import { QueryingComponent } from './querying.component';
|
||||
import { HomeComponent } from './home.component';
|
||||
import { AboutComponent } from './about.component';
|
||||
import {Routes} from '@angular/router';
|
||||
import {OpenClosePageComponent} from './open-close-page.component';
|
||||
import {StatusSliderPageComponent} from './status-slider-page.component';
|
||||
import {ToggleAnimationsPageComponent} from './toggle-animations-page.component';
|
||||
import {HeroListPageComponent} from './hero-list-page.component';
|
||||
import {HeroListGroupPageComponent} from './hero-list-group-page.component';
|
||||
import {HeroListEnterLeavePageComponent} from './hero-list-enter-leave-page.component';
|
||||
import {HeroListAutoCalcPageComponent} from './hero-list-auto-page.component';
|
||||
import {InsertRemoveComponent} from './insert-remove.component';
|
||||
import {QueryingComponent} from './querying.component';
|
||||
import {HomeComponent} from './home.component';
|
||||
import {AboutComponent} from './about.component';
|
||||
|
||||
// #docregion route-animation-data
|
||||
export const routes: Routes = [
|
||||
{ path: '', pathMatch: 'full', redirectTo: '/enter-leave' },
|
||||
{
|
||||
path: 'open-close',
|
||||
component: OpenClosePageComponent,
|
||||
data: { animation: 'openClosePage' }
|
||||
},
|
||||
{
|
||||
path: 'status',
|
||||
component: StatusSliderPageComponent,
|
||||
data: { animation: 'statusPage' }
|
||||
},
|
||||
{
|
||||
path: 'toggle',
|
||||
component: ToggleAnimationsPageComponent,
|
||||
data: { animation: 'togglePage' }
|
||||
},
|
||||
{
|
||||
path: 'heroes',
|
||||
component: HeroListPageComponent,
|
||||
data: { animation: 'filterPage' }
|
||||
},
|
||||
{
|
||||
path: 'hero-groups',
|
||||
component: HeroListGroupPageComponent,
|
||||
data: { animation: 'heroGroupPage' }
|
||||
},
|
||||
{
|
||||
path: 'enter-leave',
|
||||
component: HeroListEnterLeavePageComponent,
|
||||
data: { animation: 'enterLeavePage' }
|
||||
},
|
||||
{
|
||||
path: 'auto',
|
||||
component: HeroListAutoCalcPageComponent,
|
||||
data: { animation: 'autoPage' }
|
||||
},
|
||||
{
|
||||
path: 'insert-remove',
|
||||
component: InsertRemoveComponent,
|
||||
data: { animation: 'insertRemovePage' }
|
||||
},
|
||||
{
|
||||
path: 'querying',
|
||||
component: QueryingComponent,
|
||||
data: { animation: 'queryingPage' }
|
||||
},
|
||||
{
|
||||
path: 'home',
|
||||
component: HomeComponent,
|
||||
data: { animation: 'HomePage' }
|
||||
},
|
||||
{
|
||||
path: 'about',
|
||||
component: AboutComponent,
|
||||
data: { animation: 'AboutPage' }
|
||||
},
|
||||
{path: '', pathMatch: 'full', redirectTo: '/enter-leave'},
|
||||
{
|
||||
path: 'open-close',
|
||||
component: OpenClosePageComponent,
|
||||
data: {animation: 'openClosePage'},
|
||||
},
|
||||
{
|
||||
path: 'status',
|
||||
component: StatusSliderPageComponent,
|
||||
data: {animation: 'statusPage'},
|
||||
},
|
||||
{
|
||||
path: 'toggle',
|
||||
component: ToggleAnimationsPageComponent,
|
||||
data: {animation: 'togglePage'},
|
||||
},
|
||||
{
|
||||
path: 'heroes',
|
||||
component: HeroListPageComponent,
|
||||
data: {animation: 'filterPage'},
|
||||
},
|
||||
{
|
||||
path: 'hero-groups',
|
||||
component: HeroListGroupPageComponent,
|
||||
data: {animation: 'heroGroupPage'},
|
||||
},
|
||||
{
|
||||
path: 'enter-leave',
|
||||
component: HeroListEnterLeavePageComponent,
|
||||
data: {animation: 'enterLeavePage'},
|
||||
},
|
||||
{
|
||||
path: 'auto',
|
||||
component: HeroListAutoCalcPageComponent,
|
||||
data: {animation: 'autoPage'},
|
||||
},
|
||||
{
|
||||
path: 'insert-remove',
|
||||
component: InsertRemoveComponent,
|
||||
data: {animation: 'insertRemovePage'},
|
||||
},
|
||||
{
|
||||
path: 'querying',
|
||||
component: QueryingComponent,
|
||||
data: {animation: 'queryingPage'},
|
||||
},
|
||||
{
|
||||
path: 'home',
|
||||
component: HomeComponent,
|
||||
data: {animation: 'HomePage'},
|
||||
},
|
||||
{
|
||||
path: 'about',
|
||||
component: AboutComponent,
|
||||
data: {animation: 'AboutPage'},
|
||||
},
|
||||
];
|
||||
// #enddocregion route-animation-data
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
import { Component } from '@angular/core';
|
||||
import { HEROES } from './mock-heroes';
|
||||
import { HeroListAutoComponent } from './hero-list-auto.component';
|
||||
import {Component} from '@angular/core';
|
||||
import {HEROES} from './mock-heroes';
|
||||
import {HeroListAutoComponent} from './hero-list-auto.component';
|
||||
|
||||
@Component({
|
||||
standalone: true,
|
||||
@@ -12,12 +12,12 @@ import { HeroListAutoComponent } from './hero-list-auto.component';
|
||||
<app-hero-list-auto [heroes]="heroes" (remove)="onRemove($event)"></app-hero-list-auto>
|
||||
</section>
|
||||
`,
|
||||
imports: [HeroListAutoComponent]
|
||||
imports: [HeroListAutoComponent],
|
||||
})
|
||||
export class HeroListAutoCalcPageComponent {
|
||||
heroes = HEROES.slice();
|
||||
|
||||
onRemove(id: number) {
|
||||
this.heroes = this.heroes.filter(hero => hero.id !== id);
|
||||
this.heroes = this.heroes.filter((hero) => hero.id !== id);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,19 +1,8 @@
|
||||
import {
|
||||
Component,
|
||||
Input,
|
||||
Output,
|
||||
EventEmitter
|
||||
} from '@angular/core';
|
||||
import {
|
||||
trigger,
|
||||
state,
|
||||
style,
|
||||
animate,
|
||||
transition
|
||||
} from '@angular/animations';
|
||||
import {Component, Input, Output, EventEmitter} from '@angular/core';
|
||||
import {trigger, state, style, animate, transition} from '@angular/animations';
|
||||
|
||||
import { Hero } from './hero';
|
||||
import { NgFor } from '@angular/common';
|
||||
import {Hero} from './hero';
|
||||
import {NgFor} from '@angular/common';
|
||||
|
||||
@Component({
|
||||
standalone: true,
|
||||
@@ -24,21 +13,18 @@ import { NgFor } from '@angular/common';
|
||||
// #docregion auto-calc
|
||||
animations: [
|
||||
trigger('shrinkOut', [
|
||||
state('in', style({ height: '*' })),
|
||||
transition('* => void', [
|
||||
style({ height: '*' }),
|
||||
animate(250, style({ height: 0 }))
|
||||
])
|
||||
])
|
||||
]
|
||||
state('in', style({height: '*'})),
|
||||
transition('* => void', [style({height: '*'}), animate(250, style({height: 0}))]),
|
||||
]),
|
||||
],
|
||||
// #enddocregion auto-calc
|
||||
})
|
||||
export class HeroListAutoComponent {
|
||||
@Input() heroes: Hero[] = [];
|
||||
@Input() heroes: Hero[] = [];
|
||||
|
||||
@Output() remove = new EventEmitter<number>();
|
||||
@Output() remove = new EventEmitter<number>();
|
||||
|
||||
removeHero(id: number) {
|
||||
this.remove.emit(id);
|
||||
}
|
||||
removeHero(id: number) {
|
||||
this.remove.emit(id);
|
||||
}
|
||||
}
|
||||
|
||||
+5
-5
@@ -1,6 +1,6 @@
|
||||
import { Component } from '@angular/core';
|
||||
import { HEROES } from './mock-heroes';
|
||||
import { HeroListEnterLeaveComponent } from './hero-list-enter-leave.component';
|
||||
import {Component} from '@angular/core';
|
||||
import {HEROES} from './mock-heroes';
|
||||
import {HeroListEnterLeaveComponent} from './hero-list-enter-leave.component';
|
||||
|
||||
@Component({
|
||||
standalone: true,
|
||||
@@ -12,12 +12,12 @@ import { HeroListEnterLeaveComponent } from './hero-list-enter-leave.component';
|
||||
<app-hero-list-enter-leave [heroes]="heroes" (remove)="onRemove($event)"></app-hero-list-enter-leave>
|
||||
</section>
|
||||
`,
|
||||
imports: [HeroListEnterLeaveComponent]
|
||||
imports: [HeroListEnterLeaveComponent],
|
||||
})
|
||||
export class HeroListEnterLeavePageComponent {
|
||||
heroes = HEROES.slice();
|
||||
|
||||
onRemove(id: number) {
|
||||
this.heroes = this.heroes.filter(hero => hero.id !== id);
|
||||
this.heroes = this.heroes.filter((hero) => hero.id !== id);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,19 +1,8 @@
|
||||
import {
|
||||
Component,
|
||||
Input,
|
||||
Output,
|
||||
EventEmitter
|
||||
} from '@angular/core';
|
||||
import {
|
||||
trigger,
|
||||
state,
|
||||
style,
|
||||
animate,
|
||||
transition
|
||||
} from '@angular/animations';
|
||||
import {Component, Input, Output, EventEmitter} from '@angular/core';
|
||||
import {trigger, state, style, animate, transition} from '@angular/animations';
|
||||
|
||||
import { Hero } from './hero';
|
||||
import { NgFor } from '@angular/common';
|
||||
import {Hero} from './hero';
|
||||
import {NgFor} from '@angular/common';
|
||||
|
||||
@Component({
|
||||
standalone: true,
|
||||
@@ -35,16 +24,11 @@ import { NgFor } from '@angular/common';
|
||||
// #docregion animationdef
|
||||
animations: [
|
||||
trigger('flyInOut', [
|
||||
state('in', style({ transform: 'translateX(0)' })),
|
||||
transition('void => *', [
|
||||
style({ transform: 'translateX(-100%)' }),
|
||||
animate(100)
|
||||
]),
|
||||
transition('* => void', [
|
||||
animate(100, style({ transform: 'translateX(100%)' }))
|
||||
])
|
||||
])
|
||||
]
|
||||
state('in', style({transform: 'translateX(0)'})),
|
||||
transition('void => *', [style({transform: 'translateX(-100%)'}), animate(100)]),
|
||||
transition('* => void', [animate(100, style({transform: 'translateX(100%)'}))]),
|
||||
]),
|
||||
],
|
||||
// #enddocregion animationdef
|
||||
})
|
||||
export class HeroListEnterLeaveComponent {
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
import { Component } from '@angular/core';
|
||||
import { HEROES } from './mock-heroes';
|
||||
import { HeroListGroupsComponent } from './hero-list-groups.component';
|
||||
import {Component} from '@angular/core';
|
||||
import {HEROES} from './mock-heroes';
|
||||
import {HeroListGroupsComponent} from './hero-list-groups.component';
|
||||
|
||||
@Component({
|
||||
standalone: true,
|
||||
@@ -12,12 +12,12 @@ import { HeroListGroupsComponent } from './hero-list-groups.component';
|
||||
<app-hero-list-groups [heroes]="heroes" (remove)="onRemove($event)"></app-hero-list-groups>
|
||||
</section>
|
||||
`,
|
||||
imports: [HeroListGroupsComponent]
|
||||
imports: [HeroListGroupsComponent],
|
||||
})
|
||||
export class HeroListGroupPageComponent {
|
||||
heroes = HEROES.slice();
|
||||
|
||||
onRemove(id: number) {
|
||||
this.heroes = this.heroes.filter(hero => hero.id !== id);
|
||||
this.heroes = this.heroes.filter((hero) => hero.id !== id);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,20 +1,8 @@
|
||||
import {
|
||||
Component,
|
||||
Input,
|
||||
Output,
|
||||
EventEmitter
|
||||
} from '@angular/core';
|
||||
import {
|
||||
trigger,
|
||||
state,
|
||||
style,
|
||||
animate,
|
||||
transition,
|
||||
group
|
||||
} from '@angular/animations';
|
||||
import {Component, Input, Output, EventEmitter} from '@angular/core';
|
||||
import {trigger, state, style, animate, transition, group} from '@angular/animations';
|
||||
|
||||
import { Hero } from './hero';
|
||||
import { NgFor } from '@angular/common';
|
||||
import {Hero} from './hero';
|
||||
import {NgFor} from '@angular/common';
|
||||
|
||||
@Component({
|
||||
standalone: true,
|
||||
@@ -36,43 +24,59 @@ import { NgFor } from '@angular/common';
|
||||
// #docregion animationdef
|
||||
animations: [
|
||||
trigger('flyInOut', [
|
||||
state('in', style({
|
||||
width: '*',
|
||||
transform: 'translateX(0)', opacity: 1
|
||||
})),
|
||||
state(
|
||||
'in',
|
||||
style({
|
||||
width: '*',
|
||||
transform: 'translateX(0)',
|
||||
opacity: 1,
|
||||
}),
|
||||
),
|
||||
transition(':enter', [
|
||||
style({ width: 10, transform: 'translateX(50px)', opacity: 0 }),
|
||||
style({width: 10, transform: 'translateX(50px)', opacity: 0}),
|
||||
group([
|
||||
animate('0.3s 0.1s ease', style({
|
||||
transform: 'translateX(0)',
|
||||
width: '*'
|
||||
})),
|
||||
animate('0.3s ease', style({
|
||||
opacity: 1
|
||||
}))
|
||||
])
|
||||
animate(
|
||||
'0.3s 0.1s ease',
|
||||
style({
|
||||
transform: 'translateX(0)',
|
||||
width: '*',
|
||||
}),
|
||||
),
|
||||
animate(
|
||||
'0.3s ease',
|
||||
style({
|
||||
opacity: 1,
|
||||
}),
|
||||
),
|
||||
]),
|
||||
]),
|
||||
transition(':leave', [
|
||||
group([
|
||||
animate('0.3s ease', style({
|
||||
transform: 'translateX(50px)',
|
||||
width: 10
|
||||
})),
|
||||
animate('0.3s 0.2s ease', style({
|
||||
opacity: 0
|
||||
}))
|
||||
])
|
||||
])
|
||||
])
|
||||
]
|
||||
animate(
|
||||
'0.3s ease',
|
||||
style({
|
||||
transform: 'translateX(50px)',
|
||||
width: 10,
|
||||
}),
|
||||
),
|
||||
animate(
|
||||
'0.3s 0.2s ease',
|
||||
style({
|
||||
opacity: 0,
|
||||
}),
|
||||
),
|
||||
]),
|
||||
]),
|
||||
]),
|
||||
],
|
||||
// #enddocregion animationdef
|
||||
})
|
||||
export class HeroListGroupsComponent {
|
||||
@Input() heroes: Hero[] = [];
|
||||
@Input() heroes: Hero[] = [];
|
||||
|
||||
@Output() remove = new EventEmitter<number>();
|
||||
@Output() remove = new EventEmitter<number>();
|
||||
|
||||
removeHero(id: number) {
|
||||
this.remove.emit(id);
|
||||
}
|
||||
removeHero(id: number) {
|
||||
this.remove.emit(id);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,66 +1,65 @@
|
||||
// #docplaster
|
||||
// #docregion
|
||||
import { Component, HostBinding, OnInit } from '@angular/core';
|
||||
import { trigger, transition, animate, style, query, stagger } from '@angular/animations';
|
||||
import { HEROES } from './mock-heroes';
|
||||
import { Hero } from './hero';
|
||||
import { NgFor } from '@angular/common';
|
||||
import {Component, HostBinding, OnInit} from '@angular/core';
|
||||
import {trigger, transition, animate, style, query, stagger} from '@angular/animations';
|
||||
import {HEROES} from './mock-heroes';
|
||||
import {Hero} from './hero';
|
||||
import {NgFor} from '@angular/common';
|
||||
|
||||
// #docregion filter-animations
|
||||
@Component({
|
||||
// #enddocregion filter-animations
|
||||
// #enddocregion filter-animations
|
||||
standalone: true,
|
||||
imports: [NgFor],
|
||||
selector: 'app-hero-list-page',
|
||||
templateUrl: 'hero-list-page.component.html',
|
||||
styleUrls: ['hero-list-page.component.css'],
|
||||
// #docregion page-animations, filter-animations
|
||||
// #docregion page-animations, filter-animations
|
||||
animations: [
|
||||
// #enddocregion filter-animations
|
||||
// #enddocregion filter-animations
|
||||
trigger('pageAnimations', [
|
||||
transition(':enter', [
|
||||
query('.hero', [
|
||||
style({opacity: 0, transform: 'translateY(-100px)'}),
|
||||
stagger(30, [
|
||||
animate('500ms cubic-bezier(0.35, 0, 0.25, 1)',
|
||||
style({ opacity: 1, transform: 'none' }))
|
||||
])
|
||||
])
|
||||
])
|
||||
animate('500ms cubic-bezier(0.35, 0, 0.25, 1)', style({opacity: 1, transform: 'none'})),
|
||||
]),
|
||||
]),
|
||||
]),
|
||||
]),
|
||||
// #enddocregion page-animations
|
||||
// #docregion increment
|
||||
// #docregion filter-animations
|
||||
// #enddocregion page-animations
|
||||
// #docregion increment
|
||||
// #docregion filter-animations
|
||||
trigger('filterAnimation', [
|
||||
transition(':enter, * => 0, * => -1', []),
|
||||
transition(':increment', [
|
||||
query(':enter', [
|
||||
style({ opacity: 0, width: 0 }),
|
||||
stagger(50, [
|
||||
animate('300ms ease-out', style({ opacity: 1, width: '*' })),
|
||||
]),
|
||||
], { optional: true })
|
||||
query(
|
||||
':enter',
|
||||
[
|
||||
style({opacity: 0, width: 0}),
|
||||
stagger(50, [animate('300ms ease-out', style({opacity: 1, width: '*'}))]),
|
||||
],
|
||||
{optional: true},
|
||||
),
|
||||
]),
|
||||
transition(':decrement', [
|
||||
query(':leave', [
|
||||
stagger(50, [
|
||||
animate('300ms ease-out', style({ opacity: 0, width: 0 })),
|
||||
]),
|
||||
])
|
||||
query(':leave', [stagger(50, [animate('300ms ease-out', style({opacity: 0, width: 0}))])]),
|
||||
]),
|
||||
]),
|
||||
// #enddocregion increment
|
||||
]
|
||||
// #enddocregion increment
|
||||
],
|
||||
})
|
||||
export class HeroListPageComponent implements OnInit {
|
||||
// #enddocregion filter-animations
|
||||
// #enddocregion filter-animations
|
||||
@HostBinding('@pageAnimations')
|
||||
public animatePage = true;
|
||||
|
||||
// #docregion filter-animations
|
||||
// #docregion filter-animations
|
||||
heroesTotal = -1;
|
||||
|
||||
get heroes() { return this._heroes; }
|
||||
get heroes() {
|
||||
return this._heroes;
|
||||
}
|
||||
private _heroes: Hero[] = [];
|
||||
|
||||
ngOnInit() {
|
||||
@@ -70,7 +69,9 @@ export class HeroListPageComponent implements OnInit {
|
||||
updateCriteria(criteria: string) {
|
||||
criteria = criteria ? criteria.trim() : '';
|
||||
|
||||
this._heroes = HEROES.filter(hero => hero.name.toLowerCase().includes(criteria.toLowerCase()));
|
||||
this._heroes = HEROES.filter((hero) =>
|
||||
hero.name.toLowerCase().includes(criteria.toLowerCase()),
|
||||
);
|
||||
const newTotal = this.heroes.length;
|
||||
|
||||
if (this.heroesTotal !== newTotal) {
|
||||
|
||||
@@ -1,9 +1,9 @@
|
||||
import { Component } from '@angular/core';
|
||||
import {Component} from '@angular/core';
|
||||
|
||||
@Component({
|
||||
standalone: true,
|
||||
selector: 'app-home',
|
||||
templateUrl: './home.component.html',
|
||||
styleUrls: ['./home.component.css']
|
||||
styleUrls: ['./home.component.css'],
|
||||
})
|
||||
export class HomeComponent {}
|
||||
|
||||
@@ -1,27 +1,22 @@
|
||||
// #docplaster
|
||||
import { Component } from '@angular/core';
|
||||
import { trigger, transition, animate, style } from '@angular/animations';
|
||||
import { NgIf } from '@angular/common';
|
||||
import {Component} from '@angular/core';
|
||||
import {trigger, transition, animate, style} from '@angular/animations';
|
||||
import {NgIf} from '@angular/common';
|
||||
|
||||
@Component({
|
||||
standalone: true,
|
||||
selector: 'app-insert-remove',
|
||||
imports: [NgIf],
|
||||
animations: [
|
||||
// #docregion enter-leave-trigger
|
||||
// #docregion enter-leave-trigger
|
||||
trigger('myInsertRemoveTrigger', [
|
||||
transition(':enter', [
|
||||
style({ opacity: 0 }),
|
||||
animate('100ms', style({ opacity: 1 })),
|
||||
]),
|
||||
transition(':leave', [
|
||||
animate('100ms', style({ opacity: 0 }))
|
||||
])
|
||||
transition(':enter', [style({opacity: 0}), animate('100ms', style({opacity: 1}))]),
|
||||
transition(':leave', [animate('100ms', style({opacity: 0}))]),
|
||||
]),
|
||||
// #enddocregion enter-leave-trigger
|
||||
// #enddocregion enter-leave-trigger
|
||||
],
|
||||
templateUrl: 'insert-remove.component.html',
|
||||
styleUrls: ['insert-remove.component.css']
|
||||
styleUrls: ['insert-remove.component.css'],
|
||||
})
|
||||
export class InsertRemoveComponent {
|
||||
isShown = false;
|
||||
|
||||
@@ -1,14 +1,14 @@
|
||||
// #docregion
|
||||
import { Hero } from './hero';
|
||||
import {Hero} from './hero';
|
||||
|
||||
export const HEROES: Hero[] = [
|
||||
{ id: 12, name: 'Dr. Nice' },
|
||||
{ id: 13, name: 'Bombasto' },
|
||||
{ id: 14, name: 'Celeritas' },
|
||||
{ id: 15, name: 'Magneta' },
|
||||
{ id: 16, name: 'RubberMan' },
|
||||
{ id: 17, name: 'Dynama' },
|
||||
{ id: 18, name: 'Dr. IQ' },
|
||||
{ id: 19, name: 'Magma' },
|
||||
{ id: 20, name: 'Tornado' }
|
||||
{id: 12, name: 'Dr. Nice'},
|
||||
{id: 13, name: 'Bombasto'},
|
||||
{id: 14, name: 'Celeritas'},
|
||||
{id: 15, name: 'Magneta'},
|
||||
{id: 16, name: 'RubberMan'},
|
||||
{id: 17, name: 'Dynama'},
|
||||
{id: 18, name: 'Dr. IQ'},
|
||||
{id: 19, name: 'Magma'},
|
||||
{id: 20, name: 'Tornado'},
|
||||
];
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
import { Component } from '@angular/core';
|
||||
import { OpenCloseComponent } from './open-close.component';
|
||||
import {Component} from '@angular/core';
|
||||
import {OpenCloseComponent} from './open-close.component';
|
||||
|
||||
@Component({
|
||||
standalone: true,
|
||||
@@ -13,7 +13,7 @@ import { OpenCloseComponent } from './open-close.component';
|
||||
<app-open-close [logging]="logging"></app-open-close>
|
||||
</section>
|
||||
`,
|
||||
imports: [OpenCloseComponent]
|
||||
imports: [OpenCloseComponent],
|
||||
})
|
||||
export class OpenClosePageComponent {
|
||||
logging = false;
|
||||
|
||||
@@ -1,36 +1,53 @@
|
||||
import { Component, Input } from '@angular/core';
|
||||
import { trigger, transition, state, animate, style, keyframes, AnimationEvent } from '@angular/animations';
|
||||
import {Component, Input} from '@angular/core';
|
||||
import {
|
||||
trigger,
|
||||
transition,
|
||||
state,
|
||||
animate,
|
||||
style,
|
||||
keyframes,
|
||||
AnimationEvent,
|
||||
} from '@angular/animations';
|
||||
|
||||
@Component({
|
||||
standalone: true,
|
||||
selector: 'app-open-close',
|
||||
animations: [
|
||||
// #docregion trigger
|
||||
// #docregion trigger
|
||||
trigger('openClose', [
|
||||
state('open', style({
|
||||
height: '200px',
|
||||
opacity: 1,
|
||||
backgroundColor: 'yellow'
|
||||
})),
|
||||
state('close', style({
|
||||
height: '100px',
|
||||
opacity: 0.5,
|
||||
backgroundColor: 'green'
|
||||
})),
|
||||
state(
|
||||
'open',
|
||||
style({
|
||||
height: '200px',
|
||||
opacity: 1,
|
||||
backgroundColor: 'yellow',
|
||||
}),
|
||||
),
|
||||
state(
|
||||
'close',
|
||||
style({
|
||||
height: '100px',
|
||||
opacity: 0.5,
|
||||
backgroundColor: 'green',
|
||||
}),
|
||||
),
|
||||
// ...
|
||||
transition('* => *', [
|
||||
animate('1s', keyframes ( [
|
||||
style({ opacity: 0.1, offset: 0.1 }),
|
||||
style({ opacity: 0.6, offset: 0.2 }),
|
||||
style({ opacity: 1, offset: 0.5 }),
|
||||
style({ opacity: 0.2, offset: 0.7 })
|
||||
]))
|
||||
])
|
||||
])
|
||||
// #enddocregion trigger
|
||||
animate(
|
||||
'1s',
|
||||
keyframes([
|
||||
style({opacity: 0.1, offset: 0.1}),
|
||||
style({opacity: 0.6, offset: 0.2}),
|
||||
style({opacity: 1, offset: 0.5}),
|
||||
style({opacity: 0.2, offset: 0.7}),
|
||||
]),
|
||||
),
|
||||
]),
|
||||
]),
|
||||
// #enddocregion trigger
|
||||
],
|
||||
templateUrl: 'open-close.component.html',
|
||||
styleUrls: ['open-close.component.css']
|
||||
styleUrls: ['open-close.component.css'],
|
||||
})
|
||||
export class OpenCloseKeyframeComponent {
|
||||
isOpen = false;
|
||||
|
||||
@@ -1,20 +1,20 @@
|
||||
import { Component } from '@angular/core';
|
||||
import { trigger, transition, state, animate, style } from '@angular/animations';
|
||||
import {Component} from '@angular/core';
|
||||
import {trigger, transition, state, animate, style} from '@angular/animations';
|
||||
|
||||
@Component({
|
||||
standalone: true,
|
||||
selector: 'app-open-close-boolean',
|
||||
// #docregion trigger-boolean
|
||||
// #docregion trigger-boolean
|
||||
animations: [
|
||||
trigger('openClose', [
|
||||
state('true', style({ height: '*' })),
|
||||
state('false', style({ height: '0px' })),
|
||||
transition('false <=> true', animate(500))
|
||||
])
|
||||
state('true', style({height: '*'})),
|
||||
state('false', style({height: '0px'})),
|
||||
transition('false <=> true', animate(500)),
|
||||
]),
|
||||
],
|
||||
// #enddocregion trigger-boolean
|
||||
// #enddocregion trigger-boolean
|
||||
templateUrl: 'open-close.component.2.html',
|
||||
styleUrls: ['open-close.component.css']
|
||||
styleUrls: ['open-close.component.css'],
|
||||
})
|
||||
export class OpenCloseBooleanComponent {
|
||||
isOpen = false;
|
||||
|
||||
@@ -1,8 +1,8 @@
|
||||
// #docplaster
|
||||
// #docregion reusable
|
||||
import { Component, Input } from '@angular/core';
|
||||
import { transition, trigger, useAnimation, AnimationEvent } from '@angular/animations';
|
||||
import { transitionAnimation } from './animations';
|
||||
import {Component, Input} from '@angular/core';
|
||||
import {transition, trigger, useAnimation, AnimationEvent} from '@angular/animations';
|
||||
import {transitionAnimation} from './animations';
|
||||
|
||||
@Component({
|
||||
standalone: true,
|
||||
@@ -15,14 +15,14 @@ import { transitionAnimation } from './animations';
|
||||
height: 0,
|
||||
opacity: 1,
|
||||
backgroundColor: 'red',
|
||||
time: '1s'
|
||||
}
|
||||
})
|
||||
])
|
||||
])
|
||||
time: '1s',
|
||||
},
|
||||
}),
|
||||
]),
|
||||
]),
|
||||
],
|
||||
templateUrl: 'open-close.component.html',
|
||||
styleUrls: ['open-close.component.css']
|
||||
styleUrls: ['open-close.component.css'],
|
||||
})
|
||||
// #enddocregion reusable
|
||||
export class OpenCloseBooleanComponent {
|
||||
@@ -38,4 +38,4 @@ export class OpenCloseBooleanComponent {
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,11 +1,11 @@
|
||||
// #docplaster
|
||||
// #docregion
|
||||
import { Component } from '@angular/core';
|
||||
import { trigger, transition, state, animate, style } from '@angular/animations';
|
||||
import {Component} from '@angular/core';
|
||||
import {trigger, transition, state, animate, style} from '@angular/animations';
|
||||
|
||||
// #docregion toggle-animation
|
||||
@Component({
|
||||
// #enddocregion toggle-animation
|
||||
// #enddocregion toggle-animation
|
||||
standalone: true,
|
||||
selector: 'app-open-close-toggle',
|
||||
templateUrl: 'open-close.component.4.html',
|
||||
@@ -14,28 +14,32 @@ import { trigger, transition, state, animate, style } from '@angular/animations'
|
||||
animations: [
|
||||
trigger('childAnimation', [
|
||||
// ...
|
||||
// #enddocregion toggle-animation
|
||||
state('open', style({
|
||||
width: '250px',
|
||||
opacity: 1,
|
||||
backgroundColor: 'yellow'
|
||||
})),
|
||||
state('closed', style({
|
||||
width: '100px',
|
||||
opacity: 0.8,
|
||||
backgroundColor: 'blue'
|
||||
})),
|
||||
transition('* => *', [
|
||||
animate('1s')
|
||||
]),
|
||||
// #docregion toggle-animation
|
||||
// #enddocregion toggle-animation
|
||||
state(
|
||||
'open',
|
||||
style({
|
||||
width: '250px',
|
||||
opacity: 1,
|
||||
backgroundColor: 'yellow',
|
||||
}),
|
||||
),
|
||||
state(
|
||||
'closed',
|
||||
style({
|
||||
width: '100px',
|
||||
opacity: 0.8,
|
||||
backgroundColor: 'blue',
|
||||
}),
|
||||
),
|
||||
transition('* => *', [animate('1s')]),
|
||||
// #docregion toggle-animation
|
||||
]),
|
||||
],
|
||||
})
|
||||
export class OpenCloseChildComponent {
|
||||
isDisabled = false;
|
||||
isOpen = false;
|
||||
// #enddocregion toggle-animation
|
||||
// #enddocregion toggle-animation
|
||||
toggleAnimations() {
|
||||
this.isDisabled = !this.isDisabled;
|
||||
}
|
||||
@@ -43,6 +47,6 @@ export class OpenCloseChildComponent {
|
||||
toggle() {
|
||||
this.isOpen = !this.isOpen;
|
||||
}
|
||||
// #docregion toggle-animation
|
||||
// #docregion toggle-animation
|
||||
}
|
||||
// #enddocregion toggle-animation
|
||||
|
||||
@@ -1,90 +1,80 @@
|
||||
// #docplaster
|
||||
import { Component, Input } from '@angular/core';
|
||||
import { trigger, transition, state, animate, style, AnimationEvent } from '@angular/animations';
|
||||
import {Component, Input} from '@angular/core';
|
||||
import {trigger, transition, state, animate, style, AnimationEvent} from '@angular/animations';
|
||||
|
||||
// #docregion component, events1
|
||||
@Component({
|
||||
standalone: true,
|
||||
selector: 'app-open-close',
|
||||
// #docregion trigger-wildcard1, trigger-transition
|
||||
// #docregion trigger-wildcard1, trigger-transition
|
||||
animations: [
|
||||
trigger('openClose', [
|
||||
// #docregion state1
|
||||
// #docregion state1
|
||||
// ...
|
||||
// #enddocregion events1
|
||||
state('open', style({
|
||||
height: '200px',
|
||||
opacity: 1,
|
||||
backgroundColor: 'yellow'
|
||||
})),
|
||||
// #enddocregion state1
|
||||
// #docregion state2
|
||||
state('closed', style({
|
||||
height: '100px',
|
||||
opacity: 0.8,
|
||||
backgroundColor: 'blue'
|
||||
})),
|
||||
// #enddocregion state2, trigger-wildcard1
|
||||
// #docregion transition1
|
||||
transition('open => closed', [
|
||||
animate('1s')
|
||||
]),
|
||||
// #enddocregion transition1
|
||||
// #docregion transition2
|
||||
transition('closed => open', [
|
||||
animate('0.5s')
|
||||
]),
|
||||
// #enddocregion transition2, component
|
||||
// #docregion trigger-wildcard1
|
||||
transition('* => closed', [
|
||||
animate('1s')
|
||||
]),
|
||||
transition('* => open', [
|
||||
animate('0.5s')
|
||||
]),
|
||||
// #enddocregion trigger-wildcard1
|
||||
// #docregion trigger-wildcard2
|
||||
transition('open <=> closed', [
|
||||
animate('0.5s')
|
||||
]),
|
||||
// #enddocregion trigger-wildcard2
|
||||
// #docregion transition4
|
||||
transition ('* => open', [
|
||||
animate ('1s',
|
||||
style ({ opacity: '*' }),
|
||||
),
|
||||
]),
|
||||
// #enddocregion transition4
|
||||
transition('* => *', [
|
||||
animate('1s')
|
||||
]),
|
||||
// #enddocregion trigger-transition
|
||||
// #docregion component, trigger-wildcard1, events1
|
||||
// #enddocregion events1
|
||||
state(
|
||||
'open',
|
||||
style({
|
||||
height: '200px',
|
||||
opacity: 1,
|
||||
backgroundColor: 'yellow',
|
||||
}),
|
||||
),
|
||||
// #enddocregion state1
|
||||
// #docregion state2
|
||||
state(
|
||||
'closed',
|
||||
style({
|
||||
height: '100px',
|
||||
opacity: 0.8,
|
||||
backgroundColor: 'blue',
|
||||
}),
|
||||
),
|
||||
// #enddocregion state2, trigger-wildcard1
|
||||
// #docregion transition1
|
||||
transition('open => closed', [animate('1s')]),
|
||||
// #enddocregion transition1
|
||||
// #docregion transition2
|
||||
transition('closed => open', [animate('0.5s')]),
|
||||
// #enddocregion transition2, component
|
||||
// #docregion trigger-wildcard1
|
||||
transition('* => closed', [animate('1s')]),
|
||||
transition('* => open', [animate('0.5s')]),
|
||||
// #enddocregion trigger-wildcard1
|
||||
// #docregion trigger-wildcard2
|
||||
transition('open <=> closed', [animate('0.5s')]),
|
||||
// #enddocregion trigger-wildcard2
|
||||
// #docregion transition4
|
||||
transition('* => open', [animate('1s', style({opacity: '*'}))]),
|
||||
// #enddocregion transition4
|
||||
transition('* => *', [animate('1s')]),
|
||||
// #enddocregion trigger-transition
|
||||
// #docregion component, trigger-wildcard1, events1
|
||||
]),
|
||||
],
|
||||
// #enddocregion trigger-wildcard1
|
||||
// #enddocregion trigger-wildcard1
|
||||
templateUrl: 'open-close.component.html',
|
||||
styleUrls: ['open-close.component.css']
|
||||
styleUrls: ['open-close.component.css'],
|
||||
})
|
||||
// #docregion events
|
||||
export class OpenCloseComponent {
|
||||
// #enddocregion events1, events, component
|
||||
// #enddocregion events1, events, component
|
||||
@Input() logging = false;
|
||||
// #docregion component
|
||||
// #docregion component
|
||||
isOpen = true;
|
||||
|
||||
toggle() {
|
||||
this.isOpen = !this.isOpen;
|
||||
}
|
||||
|
||||
// #enddocregion component
|
||||
// #docregion events1, events
|
||||
// #enddocregion component
|
||||
// #docregion events1, events
|
||||
onAnimationEvent(event: AnimationEvent) {
|
||||
// #enddocregion events1, events
|
||||
// #enddocregion events1, events
|
||||
if (!this.logging) {
|
||||
return;
|
||||
}
|
||||
// #docregion events
|
||||
// #docregion events
|
||||
// openClose is trigger name in this example
|
||||
console.warn(`Animation Trigger: ${event.triggerName}`);
|
||||
|
||||
@@ -102,8 +92,8 @@ export class OpenCloseComponent {
|
||||
|
||||
// the HTML element itself, the button in this case
|
||||
console.warn(`Element: ${event.element}`);
|
||||
// #docregion events1
|
||||
// #docregion events1
|
||||
}
|
||||
// #docregion component
|
||||
// #docregion component
|
||||
}
|
||||
// #enddocregion component
|
||||
|
||||
@@ -1,6 +1,4 @@
|
||||
import {
|
||||
Component,
|
||||
} from '@angular/core';
|
||||
import {Component} from '@angular/core';
|
||||
import {
|
||||
trigger,
|
||||
style,
|
||||
@@ -9,11 +7,11 @@ import {
|
||||
group,
|
||||
query,
|
||||
animateChild,
|
||||
keyframes
|
||||
keyframes,
|
||||
} from '@angular/animations';
|
||||
|
||||
import { HEROES } from './mock-heroes';
|
||||
import { NgIf } from '@angular/common';
|
||||
import {HEROES} from './mock-heroes';
|
||||
import {NgIf} from '@angular/common';
|
||||
|
||||
@Component({
|
||||
standalone: true,
|
||||
@@ -41,44 +39,50 @@ import { NgIf } from '@angular/common';
|
||||
animations: [
|
||||
trigger('query', [
|
||||
transition(':enter', [
|
||||
style({ height: 0 }),
|
||||
style({height: 0}),
|
||||
group([
|
||||
animate(500, style({ height: '*' })),
|
||||
animate(500, style({height: '*'})),
|
||||
query(':enter', [
|
||||
style({ opacity: 0, transform: 'scale(0)'}),
|
||||
animate(2000, style({ opacity: 1, transform: 'scale(1)' }))
|
||||
style({opacity: 0, transform: 'scale(0)'}),
|
||||
animate(2000, style({opacity: 1, transform: 'scale(1)'})),
|
||||
]),
|
||||
query('.hero', [
|
||||
style({ transform: 'translateX(-100%)'}),
|
||||
animate('.7s 500ms ease-in', style({ transform: 'translateX(0)' }))
|
||||
style({transform: 'translateX(-100%)'}),
|
||||
animate('.7s 500ms ease-in', style({transform: 'translateX(0)'})),
|
||||
]),
|
||||
]),
|
||||
query('@animateMe', animateChild()),
|
||||
]),
|
||||
transition(':leave', [
|
||||
style({ height: '*' }),
|
||||
style({height: '*'}),
|
||||
query('@animateMe', animateChild()),
|
||||
group([
|
||||
animate('500ms 500ms', style({ height: '0', padding: '0' })),
|
||||
animate('500ms 500ms', style({height: '0', padding: '0'})),
|
||||
query(':leave', [
|
||||
style({ opacity: 1, transform: 'scale(1)'}),
|
||||
animate('1s', style({ opacity: 0, transform: 'scale(0)' }))
|
||||
style({opacity: 1, transform: 'scale(1)'}),
|
||||
animate('1s', style({opacity: 0, transform: 'scale(0)'})),
|
||||
]),
|
||||
query('.hero', [
|
||||
style({ transform: 'translateX(0)'}),
|
||||
animate('.7s ease-out', style({ transform: 'translateX(-100%)' }))
|
||||
style({transform: 'translateX(0)'}),
|
||||
animate('.7s ease-out', style({transform: 'translateX(-100%)'})),
|
||||
]),
|
||||
]),
|
||||
]),
|
||||
]),
|
||||
trigger('animateMe', [
|
||||
transition('* <=> *', animate('500ms cubic-bezier(.68,-0.73,.26,1.65)', keyframes([
|
||||
style({ backgroundColor: 'transparent', color: '*', offset: 0 }),
|
||||
style({ backgroundColor: 'blue', color: 'white', offset: 0.2 }),
|
||||
style({ backgroundColor: 'transparent', color: '*', offset: 1 })
|
||||
])))
|
||||
transition(
|
||||
'* <=> *',
|
||||
animate(
|
||||
'500ms cubic-bezier(.68,-0.73,.26,1.65)',
|
||||
keyframes([
|
||||
style({backgroundColor: 'transparent', color: '*', offset: 0}),
|
||||
style({backgroundColor: 'blue', color: 'white', offset: 0.2}),
|
||||
style({backgroundColor: 'transparent', color: '*', offset: 1}),
|
||||
]),
|
||||
),
|
||||
),
|
||||
]),
|
||||
]
|
||||
],
|
||||
})
|
||||
export class QueryingComponent {
|
||||
toggleDisabled = false;
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
import { Component } from '@angular/core';
|
||||
import { StatusSliderComponent } from './status-slider.component';
|
||||
import {Component} from '@angular/core';
|
||||
import {StatusSliderComponent} from './status-slider.component';
|
||||
|
||||
@Component({
|
||||
standalone: true,
|
||||
@@ -10,6 +10,6 @@ import { StatusSliderComponent } from './status-slider.component';
|
||||
<app-status-slider></app-status-slider>
|
||||
</section>
|
||||
`,
|
||||
imports: [StatusSliderComponent]
|
||||
imports: [StatusSliderComponent],
|
||||
})
|
||||
export class StatusSliderPageComponent {}
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
import { Component } from '@angular/core';
|
||||
import { trigger, transition, state, animate, style, keyframes } from '@angular/animations';
|
||||
import {Component} from '@angular/core';
|
||||
import {trigger, transition, state, animate, style, keyframes} from '@angular/animations';
|
||||
|
||||
@Component({
|
||||
standalone: true,
|
||||
@@ -8,37 +8,46 @@ import { trigger, transition, state, animate, style, keyframes } from '@angular/
|
||||
styleUrls: ['status-slider.component.css'],
|
||||
animations: [
|
||||
trigger('slideStatus', [
|
||||
state('inactive', style({ backgroundColor: 'blue' })),
|
||||
state('active', style({ backgroundColor: '#754600' })),
|
||||
state('inactive', style({backgroundColor: 'blue'})),
|
||||
state('active', style({backgroundColor: '#754600'})),
|
||||
|
||||
// #docregion keyframesWithOffsets
|
||||
// #docregion keyframesWithOffsets
|
||||
transition('* => active', [
|
||||
animate('2s', keyframes([
|
||||
style({ backgroundColor: 'blue', offset: 0}),
|
||||
style({ backgroundColor: 'red', offset: 0.8}),
|
||||
style({ backgroundColor: '#754600', offset: 1.0})
|
||||
])),
|
||||
animate(
|
||||
'2s',
|
||||
keyframes([
|
||||
style({backgroundColor: 'blue', offset: 0}),
|
||||
style({backgroundColor: 'red', offset: 0.8}),
|
||||
style({backgroundColor: '#754600', offset: 1.0}),
|
||||
]),
|
||||
),
|
||||
]),
|
||||
transition('* => inactive', [
|
||||
animate('2s', keyframes([
|
||||
style({ backgroundColor: '#754600', offset: 0}),
|
||||
style({ backgroundColor: 'red', offset: 0.2}),
|
||||
style({ backgroundColor: 'blue', offset: 1.0})
|
||||
]))
|
||||
animate(
|
||||
'2s',
|
||||
keyframes([
|
||||
style({backgroundColor: '#754600', offset: 0}),
|
||||
style({backgroundColor: 'red', offset: 0.2}),
|
||||
style({backgroundColor: 'blue', offset: 1.0}),
|
||||
]),
|
||||
),
|
||||
]),
|
||||
// #enddocregion keyframesWithOffsets
|
||||
// #enddocregion keyframesWithOffsets
|
||||
|
||||
// #docregion keyframes
|
||||
// #docregion keyframes
|
||||
transition('* => active', [
|
||||
animate('2s', keyframes([
|
||||
style({ backgroundColor: 'blue' }),
|
||||
style({ backgroundColor: 'red' }),
|
||||
style({ backgroundColor: 'orange' })
|
||||
]))
|
||||
// #enddocregion keyframes
|
||||
animate(
|
||||
'2s',
|
||||
keyframes([
|
||||
style({backgroundColor: 'blue'}),
|
||||
style({backgroundColor: 'red'}),
|
||||
style({backgroundColor: 'orange'}),
|
||||
]),
|
||||
),
|
||||
// #enddocregion keyframes
|
||||
]),
|
||||
])
|
||||
]
|
||||
]),
|
||||
],
|
||||
})
|
||||
export class StatusSliderComponent {
|
||||
status: 'active' | 'inactive' = 'inactive';
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
import { Component } from '@angular/core';
|
||||
import { OpenCloseChildComponent } from './open-close.component.4';
|
||||
import {Component} from '@angular/core';
|
||||
import {OpenCloseChildComponent} from './open-close.component.4';
|
||||
|
||||
@Component({
|
||||
standalone: true,
|
||||
@@ -11,6 +11,6 @@ import { OpenCloseChildComponent } from './open-close.component.4';
|
||||
<app-open-close-toggle></app-open-close-toggle>
|
||||
</section>
|
||||
`,
|
||||
imports: [OpenCloseChildComponent]
|
||||
imports: [OpenCloseChildComponent],
|
||||
})
|
||||
export class ToggleAnimationsPageComponent {}
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
import { bootstrapApplication } from '@angular/platform-browser';
|
||||
import { AppComponent } from './app/app.component';
|
||||
import { appConfig } from './app/app.config';
|
||||
import {bootstrapApplication} from '@angular/platform-browser';
|
||||
import {AppComponent} from './app/app.component';
|
||||
import {appConfig} from './app/app.config';
|
||||
|
||||
bootstrapApplication(AppComponent, appConfig);
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
import { protractor, browser, element, by, ElementFinder } from 'protractor';
|
||||
import {protractor, browser, element, by, ElementFinder} from 'protractor';
|
||||
|
||||
const nameSuffix = 'X';
|
||||
|
||||
@@ -8,7 +8,6 @@ interface Hero {
|
||||
}
|
||||
|
||||
describe('Architecture', () => {
|
||||
|
||||
const expectedTitle = 'Architecture of Angular';
|
||||
const expectedH2 = ['Hero List', 'Sales Tax Calculator'];
|
||||
|
||||
@@ -28,8 +27,7 @@ describe('Architecture', () => {
|
||||
});
|
||||
|
||||
function heroTests() {
|
||||
|
||||
const targetHero: Hero = { id: 2, name: 'Dr Nice' };
|
||||
const targetHero: Hero = {id: 2, name: 'Dr Nice'};
|
||||
|
||||
it('has the right number of heroes', async () => {
|
||||
const page = getPageElts();
|
||||
@@ -80,7 +78,7 @@ function getPageElts() {
|
||||
heroes: element.all(by.css('app-root li')),
|
||||
heroDetail: element(by.css('app-root app-hero-detail')),
|
||||
salesTaxAmountInput: element(by.css('app-root app-sales-tax input')),
|
||||
salesTaxDetail: element(by.css('app-root app-sales-tax div'))
|
||||
salesTaxDetail: element(by.css('app-root app-sales-tax div')),
|
||||
};
|
||||
}
|
||||
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
// #docregion import
|
||||
import { Component } from '@angular/core';
|
||||
import {Component} from '@angular/core';
|
||||
// #enddocregion import
|
||||
|
||||
@Component({
|
||||
@@ -8,6 +8,6 @@ import { Component } from '@angular/core';
|
||||
<h1>Architecture Example</h1>
|
||||
<app-hero-list></app-hero-list>
|
||||
<app-sales-tax></app-sales-tax>
|
||||
`
|
||||
`,
|
||||
})
|
||||
export class AppComponent { }
|
||||
export class AppComponent {}
|
||||
|
||||
@@ -1,34 +1,22 @@
|
||||
import { BrowserModule } from '@angular/platform-browser';
|
||||
import { FormsModule } from '@angular/forms';
|
||||
import {BrowserModule} from '@angular/platform-browser';
|
||||
import {FormsModule} from '@angular/forms';
|
||||
// #docregion imports
|
||||
import { NgModule } from '@angular/core';
|
||||
import { AppComponent } from './app.component';
|
||||
import {NgModule} from '@angular/core';
|
||||
import {AppComponent} from './app.component';
|
||||
// #enddocregion imports
|
||||
import { HeroDetailComponent } from './hero-detail.component';
|
||||
import { HeroListComponent } from './hero-list.component';
|
||||
import { SalesTaxComponent } from './sales-tax.component';
|
||||
import { HeroService } from './hero.service';
|
||||
import { BackendService } from './backend.service';
|
||||
import { Logger } from './logger.service';
|
||||
import {HeroDetailComponent} from './hero-detail.component';
|
||||
import {HeroListComponent} from './hero-list.component';
|
||||
import {SalesTaxComponent} from './sales-tax.component';
|
||||
import {HeroService} from './hero.service';
|
||||
import {BackendService} from './backend.service';
|
||||
import {Logger} from './logger.service';
|
||||
|
||||
@NgModule({
|
||||
imports: [
|
||||
BrowserModule,
|
||||
FormsModule
|
||||
],
|
||||
declarations: [
|
||||
AppComponent,
|
||||
HeroDetailComponent,
|
||||
HeroListComponent,
|
||||
SalesTaxComponent
|
||||
],
|
||||
providers: [
|
||||
BackendService,
|
||||
HeroService,
|
||||
Logger
|
||||
],
|
||||
bootstrap: [ AppComponent ]
|
||||
imports: [BrowserModule, FormsModule],
|
||||
declarations: [AppComponent, HeroDetailComponent, HeroListComponent, SalesTaxComponent],
|
||||
providers: [BackendService, HeroService, Logger],
|
||||
bootstrap: [AppComponent],
|
||||
})
|
||||
// #docregion export
|
||||
export class AppModule { }
|
||||
export class AppModule {}
|
||||
// #enddocregion export
|
||||
|
||||
@@ -1,13 +1,13 @@
|
||||
import { Injectable, Type } from '@angular/core';
|
||||
import {Injectable, Type} from '@angular/core';
|
||||
|
||||
import { Logger } from './logger.service';
|
||||
import { Hero } from './hero';
|
||||
import {Logger} from './logger.service';
|
||||
import {Hero} from './hero';
|
||||
|
||||
const HEROES = [
|
||||
new Hero('Windstorm', 'Weather mastery'),
|
||||
new Hero('Dr Nice', 'Killing them with kindness'),
|
||||
new Hero('Magneta', 'Manipulates metallic objects')
|
||||
];
|
||||
new Hero('Windstorm', 'Weather mastery'),
|
||||
new Hero('Dr Nice', 'Killing them with kindness'),
|
||||
new Hero('Magneta', 'Manipulates metallic objects'),
|
||||
];
|
||||
|
||||
@Injectable()
|
||||
export class BackendService {
|
||||
|
||||
@@ -1,10 +1,10 @@
|
||||
import { Component, Input } from '@angular/core';
|
||||
import {Component, Input} from '@angular/core';
|
||||
|
||||
import { Hero } from './hero';
|
||||
import {Hero} from './hero';
|
||||
|
||||
@Component({
|
||||
selector: 'app-hero-detail',
|
||||
templateUrl: './hero-detail.component.html'
|
||||
templateUrl: './hero-detail.component.html',
|
||||
})
|
||||
export class HeroDetailComponent {
|
||||
@Input() hero!: Hero;
|
||||
|
||||
@@ -1,13 +1,13 @@
|
||||
import { Component, OnInit } from '@angular/core';
|
||||
import {Component, OnInit} from '@angular/core';
|
||||
|
||||
import { Hero } from './hero';
|
||||
import { HeroService } from './hero.service';
|
||||
import {Hero} from './hero';
|
||||
import {HeroService} from './hero.service';
|
||||
|
||||
// #docregion metadata, providers
|
||||
@Component({
|
||||
selector: 'app-hero-list',
|
||||
selector: 'app-hero-list',
|
||||
templateUrl: './hero-list.component.html',
|
||||
providers: [ HeroService ]
|
||||
providers: [HeroService],
|
||||
})
|
||||
// #enddocregion providers
|
||||
// #docregion class
|
||||
@@ -17,13 +17,15 @@ export class HeroListComponent implements OnInit {
|
||||
selectedHero: Hero | undefined;
|
||||
|
||||
// #docregion ctor
|
||||
constructor(private service: HeroService) { }
|
||||
constructor(private service: HeroService) {}
|
||||
// #enddocregion ctor
|
||||
|
||||
ngOnInit() {
|
||||
this.heroes = this.service.getHeroes();
|
||||
}
|
||||
|
||||
selectHero(hero: Hero) { this.selectedHero = hero; }
|
||||
selectHero(hero: Hero) {
|
||||
this.selectedHero = hero;
|
||||
}
|
||||
// #docregion metadata
|
||||
}
|
||||
|
||||
@@ -1,8 +1,8 @@
|
||||
import { Injectable } from '@angular/core';
|
||||
import {Injectable} from '@angular/core';
|
||||
|
||||
import { Hero } from './hero';
|
||||
import { BackendService } from './backend.service';
|
||||
import { Logger } from './logger.service';
|
||||
import {Hero} from './hero';
|
||||
import {BackendService} from './backend.service';
|
||||
import {Logger} from './logger.service';
|
||||
|
||||
@Injectable()
|
||||
// #docregion class
|
||||
@@ -11,10 +11,11 @@ export class HeroService {
|
||||
|
||||
constructor(
|
||||
private backend: BackendService,
|
||||
private logger: Logger) { }
|
||||
private logger: Logger,
|
||||
) {}
|
||||
|
||||
getHeroes() {
|
||||
this.backend.getAll(Hero).then( (heroes: Hero[]) => {
|
||||
this.backend.getAll(Hero).then((heroes: Hero[]) => {
|
||||
this.logger.log(`Fetched ${heroes.length} heroes.`);
|
||||
this.heroes.push(...heroes); // fill cache
|
||||
});
|
||||
|
||||
@@ -4,7 +4,8 @@ export class Hero {
|
||||
id: number;
|
||||
constructor(
|
||||
public name: string,
|
||||
public power?: string) {
|
||||
this.id = nextId++;
|
||||
}
|
||||
public power?: string,
|
||||
) {
|
||||
this.id = nextId++;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,9 +1,15 @@
|
||||
import { Injectable } from '@angular/core';
|
||||
import {Injectable} from '@angular/core';
|
||||
|
||||
@Injectable()
|
||||
// #docregion class
|
||||
export class Logger {
|
||||
log(msg: any) { console.log(msg); }
|
||||
error(msg: any) { console.error(msg); }
|
||||
warn(msg: any) { console.warn(msg); }
|
||||
log(msg: any) {
|
||||
console.log(msg);
|
||||
}
|
||||
error(msg: any) {
|
||||
console.error(msg);
|
||||
}
|
||||
warn(msg: any) {
|
||||
console.warn(msg);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,17 +1,19 @@
|
||||
// #docplaster
|
||||
// A mini-application
|
||||
import { Injectable } from '@angular/core';
|
||||
import {Injectable} from '@angular/core';
|
||||
|
||||
@Injectable()
|
||||
export class Logger {
|
||||
log(message: string) { console.log(message); }
|
||||
log(message: string) {
|
||||
console.log(message);
|
||||
}
|
||||
}
|
||||
|
||||
import { Component } from '@angular/core';
|
||||
import {Component} from '@angular/core';
|
||||
|
||||
@Component({
|
||||
selector: 'app-root',
|
||||
template: 'Welcome to Angular'
|
||||
selector: 'app-root',
|
||||
template: 'Welcome to Angular',
|
||||
})
|
||||
export class AppComponent {
|
||||
constructor(logger: Logger) {
|
||||
@@ -20,22 +22,22 @@ export class AppComponent {
|
||||
}
|
||||
|
||||
// #docregion module
|
||||
import { NgModule } from '@angular/core';
|
||||
import {NgModule} from '@angular/core';
|
||||
// #docregion import-browser-module
|
||||
import { BrowserModule } from '@angular/platform-browser';
|
||||
import {BrowserModule} from '@angular/platform-browser';
|
||||
// #enddocregion import-browser-module
|
||||
@NgModule({
|
||||
// #docregion ngmodule-imports
|
||||
imports: [ BrowserModule ],
|
||||
// #enddocregion ngmodule-imports
|
||||
providers: [ Logger ],
|
||||
declarations: [ AppComponent ],
|
||||
exports: [ AppComponent ],
|
||||
bootstrap: [ AppComponent ]
|
||||
// #docregion ngmodule-imports
|
||||
imports: [BrowserModule],
|
||||
// #enddocregion ngmodule-imports
|
||||
providers: [Logger],
|
||||
declarations: [AppComponent],
|
||||
exports: [AppComponent],
|
||||
bootstrap: [AppComponent],
|
||||
})
|
||||
export class AppModule { }
|
||||
export class AppModule {}
|
||||
// #enddocregion module
|
||||
|
||||
import { platformBrowserDynamic } from '@angular/platform-browser-dynamic';
|
||||
import {platformBrowserDynamic} from '@angular/platform-browser-dynamic';
|
||||
|
||||
platformBrowserDynamic().bootstrapModule(AppModule);
|
||||
|
||||
@@ -1,10 +1,10 @@
|
||||
import { Component } from '@angular/core';
|
||||
import {Component} from '@angular/core';
|
||||
|
||||
import { SalesTaxService } from './sales-tax.service';
|
||||
import { TaxRateService } from './tax-rate.service';
|
||||
import {SalesTaxService} from './sales-tax.service';
|
||||
import {TaxRateService} from './tax-rate.service';
|
||||
|
||||
@Component({
|
||||
selector: 'app-sales-tax',
|
||||
selector: 'app-sales-tax',
|
||||
template: `
|
||||
<h2>Sales Tax Calculator</h2>
|
||||
<p><em>Enter a number and press enter to calculate tax.</em></p>
|
||||
@@ -15,10 +15,10 @@ import { TaxRateService } from './tax-rate.service';
|
||||
{{ getTax(amountBox.value) | currency:'USD':true:'1.2-2' }}</p>
|
||||
</div>
|
||||
`,
|
||||
providers: [SalesTaxService, TaxRateService]
|
||||
providers: [SalesTaxService, TaxRateService],
|
||||
})
|
||||
export class SalesTaxComponent {
|
||||
constructor(private salesTaxService: SalesTaxService) { }
|
||||
constructor(private salesTaxService: SalesTaxService) {}
|
||||
|
||||
getTax(value: string | number) {
|
||||
return this.salesTaxService.getVAT(value);
|
||||
|
||||
@@ -1,14 +1,13 @@
|
||||
import { Injectable } from '@angular/core';
|
||||
import {Injectable} from '@angular/core';
|
||||
|
||||
import { TaxRateService } from './tax-rate.service';
|
||||
import {TaxRateService} from './tax-rate.service';
|
||||
|
||||
@Injectable()
|
||||
export class SalesTaxService {
|
||||
constructor(private rateService: TaxRateService) { }
|
||||
constructor(private rateService: TaxRateService) {}
|
||||
|
||||
getVAT(value: string | number) {
|
||||
const amount = (typeof value === 'string') ?
|
||||
parseFloat(value) : value;
|
||||
const amount = typeof value === 'string' ? parseFloat(value) : value;
|
||||
return (amount || 0) * this.rateService.getRate('VAT');
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,6 +1,8 @@
|
||||
import { Injectable } from '@angular/core';
|
||||
import {Injectable} from '@angular/core';
|
||||
|
||||
@Injectable()
|
||||
export class TaxRateService {
|
||||
getRate(rateName: string) { return 0.10; } // 10% everywhere
|
||||
getRate(rateName: string) {
|
||||
return 0.1;
|
||||
} // 10% everywhere
|
||||
}
|
||||
|
||||
@@ -1,7 +1,8 @@
|
||||
// #docregion
|
||||
import { platformBrowserDynamic } from '@angular/platform-browser-dynamic';
|
||||
import {platformBrowserDynamic} from '@angular/platform-browser-dynamic';
|
||||
|
||||
import { AppModule } from './app/app.module';
|
||||
import {AppModule} from './app/app.module';
|
||||
|
||||
platformBrowserDynamic().bootstrapModule(AppModule)
|
||||
.catch(err => console.error(err));
|
||||
platformBrowserDynamic()
|
||||
.bootstrapModule(AppModule)
|
||||
.catch((err) => console.error(err));
|
||||
|
||||
@@ -1,7 +1,6 @@
|
||||
import { browser, element, by } from 'protractor';
|
||||
import {browser, element, by} from 'protractor';
|
||||
|
||||
describe('Attribute binding example', () => {
|
||||
|
||||
beforeEach(() => browser.get(''));
|
||||
|
||||
it('should display Property Binding with Angular', async () => {
|
||||
@@ -13,7 +12,9 @@ describe('Attribute binding example', () => {
|
||||
});
|
||||
|
||||
it('should display an Aria button', async () => {
|
||||
expect(await element.all(by.css('button')).get(0).getText()).toBe('Create and set an attribute with Aria');
|
||||
expect(await element.all(by.css('button')).get(0).getText()).toBe(
|
||||
'Create and set an attribute with Aria',
|
||||
);
|
||||
});
|
||||
|
||||
it('should display a black background on div', async () => {
|
||||
@@ -31,5 +32,4 @@ describe('Attribute binding example', () => {
|
||||
expect(await div.getAttribute('class')).toContain('special');
|
||||
expect(await div.getAttribute('class')).toContain('clearance');
|
||||
});
|
||||
|
||||
});
|
||||
|
||||
+1
-1
@@ -1,4 +1,4 @@
|
||||
import { Component } from "@angular/core";
|
||||
import {Component} from '@angular/core';
|
||||
|
||||
@Component({
|
||||
standalone: true,
|
||||
|
||||
@@ -1,7 +1,6 @@
|
||||
import { browser, element, by } from 'protractor';
|
||||
import {browser, element, by} from 'protractor';
|
||||
|
||||
describe('Attribute directives', () => {
|
||||
|
||||
const title = 'My First Attribute Directive';
|
||||
|
||||
beforeAll(() => browser.get(''));
|
||||
@@ -23,6 +22,6 @@ describe('Attribute directives', () => {
|
||||
|
||||
// Wait for up to 4s for the background color to be updated,
|
||||
// to account for slow environments (e.g. CI).
|
||||
await browser.wait(async () => await getBgColor() === lightGreen, 4000);
|
||||
await browser.wait(async () => (await getBgColor()) === lightGreen, 4000);
|
||||
});
|
||||
});
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
import {Component} from '@angular/core';
|
||||
import { HighlightDirective } from './highlight.directive';
|
||||
import {HighlightDirective} from './highlight.directive';
|
||||
|
||||
@Component({
|
||||
standalone: true,
|
||||
|
||||
@@ -1,19 +1,16 @@
|
||||
import { browser, element, by } from 'protractor';
|
||||
import { logging } from 'selenium-webdriver';
|
||||
import {browser, element, by} from 'protractor';
|
||||
import {logging} from 'selenium-webdriver';
|
||||
|
||||
describe('Binding syntax e2e tests', () => {
|
||||
|
||||
beforeEach(() => browser.get(''));
|
||||
|
||||
|
||||
// helper function used to test what's logged to the console
|
||||
async function logChecker(contents: string) {
|
||||
const logs = await browser.manage().logs().get(logging.Type.BROWSER);
|
||||
const messages = logs.filter(({ message }) => message.indexOf(contents) !== -1 ? true : false);
|
||||
const messages = logs.filter(({message}) => (message.indexOf(contents) !== -1 ? true : false));
|
||||
expect(messages.length).toBeGreaterThan(0);
|
||||
}
|
||||
|
||||
|
||||
it('should display Binding syntax', async () => {
|
||||
expect(await element(by.css('h1')).getText()).toEqual('Binding syntax');
|
||||
});
|
||||
@@ -23,7 +20,9 @@ describe('Binding syntax e2e tests', () => {
|
||||
});
|
||||
|
||||
it('should display HTML attributes and DOM properties', async () => {
|
||||
expect(await element.all(by.css('h2')).get(1).getText()).toBe('HTML attributes and DOM properties');
|
||||
expect(await element.all(by.css('h2')).get(1).getText()).toBe(
|
||||
'HTML attributes and DOM properties',
|
||||
);
|
||||
});
|
||||
|
||||
it('should display 1. Use the inspector...', async () => {
|
||||
@@ -31,10 +30,11 @@ describe('Binding syntax e2e tests', () => {
|
||||
});
|
||||
|
||||
it('should display Disabled property vs. attribute', async () => {
|
||||
expect(await element.all(by.css('h3')).get(0).getText()).toBe('Disabled property vs. attribute');
|
||||
expect(await element.all(by.css('h3')).get(0).getText()).toBe(
|
||||
'Disabled property vs. attribute',
|
||||
);
|
||||
});
|
||||
|
||||
|
||||
it('should log a message including Sarah', async () => {
|
||||
const attributeButton = element.all(by.css('button')).get(1);
|
||||
await attributeButton.click();
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
import { AppPage } from './app.po';
|
||||
import {AppPage} from './app.po';
|
||||
|
||||
describe('feature-modules App', () => {
|
||||
let page: AppPage;
|
||||
|
||||
@@ -1,9 +1,9 @@
|
||||
import { Component } from '@angular/core';
|
||||
import {Component} from '@angular/core';
|
||||
|
||||
@Component({
|
||||
selector: 'app-root',
|
||||
templateUrl: './app.component.html',
|
||||
styleUrls: ['./app.component.css']
|
||||
styleUrls: ['./app.component.css'],
|
||||
})
|
||||
export class AppComponent {
|
||||
title = 'app works!';
|
||||
|
||||
@@ -1,32 +1,24 @@
|
||||
// #docplaster
|
||||
// imports
|
||||
import { BrowserModule } from '@angular/platform-browser';
|
||||
import { NgModule } from '@angular/core';
|
||||
import { FormsModule } from '@angular/forms';
|
||||
import { HttpClientModule } from '@angular/common/http';
|
||||
import {BrowserModule} from '@angular/platform-browser';
|
||||
import {NgModule} from '@angular/core';
|
||||
import {FormsModule} from '@angular/forms';
|
||||
import {HttpClientModule} from '@angular/common/http';
|
||||
|
||||
import { AppComponent } from './app.component';
|
||||
import {AppComponent} from './app.component';
|
||||
// #docregion directive-import
|
||||
import { ItemDirective } from './item.directive';
|
||||
import {ItemDirective} from './item.directive';
|
||||
// #enddocregion directive-import
|
||||
|
||||
|
||||
// @NgModule decorator with its metadata
|
||||
@NgModule({
|
||||
// #docregion declarations
|
||||
declarations: [
|
||||
AppComponent,
|
||||
ItemDirective
|
||||
],
|
||||
// #docregion declarations
|
||||
declarations: [AppComponent, ItemDirective],
|
||||
// #enddocregion declarations
|
||||
// #docregion imports
|
||||
imports: [
|
||||
BrowserModule,
|
||||
FormsModule,
|
||||
HttpClientModule
|
||||
],
|
||||
imports: [BrowserModule, FormsModule, HttpClientModule],
|
||||
// #enddocregion imports
|
||||
providers: [],
|
||||
bootstrap: [AppComponent]
|
||||
bootstrap: [AppComponent],
|
||||
})
|
||||
export class AppModule { }
|
||||
export class AppModule {}
|
||||
|
||||
@@ -1,15 +1,13 @@
|
||||
// #docplaster
|
||||
// #docregion directive
|
||||
|
||||
|
||||
import { Directive } from '@angular/core';
|
||||
import {Directive} from '@angular/core';
|
||||
|
||||
@Directive({
|
||||
selector: '[appItem]'
|
||||
selector: '[appItem]',
|
||||
})
|
||||
export class ItemDirective {
|
||||
// code goes here
|
||||
constructor() { }
|
||||
|
||||
// code goes here
|
||||
constructor() {}
|
||||
}
|
||||
// #enddocregion directive
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
import { platformBrowserDynamic } from '@angular/platform-browser-dynamic';
|
||||
import {platformBrowserDynamic} from '@angular/platform-browser-dynamic';
|
||||
|
||||
import { AppModule } from './app/app.module';
|
||||
import {AppModule} from './app/app.module';
|
||||
|
||||
platformBrowserDynamic().bootstrapModule(AppModule)
|
||||
.catch(err => console.error(err));
|
||||
platformBrowserDynamic()
|
||||
.bootstrapModule(AppModule)
|
||||
.catch((err) => console.error(err));
|
||||
|
||||
@@ -1,7 +1,6 @@
|
||||
import { browser, element, by } from 'protractor';
|
||||
import {browser, element, by} from 'protractor';
|
||||
|
||||
describe('Built-in Directives', () => {
|
||||
|
||||
beforeAll(() => browser.get(''));
|
||||
|
||||
it('should have title Built-in Directives', async () => {
|
||||
@@ -18,7 +17,6 @@ describe('Built-in Directives', () => {
|
||||
expect(await firstLabel.getText()).toEqual('Current item name: Teapotabc');
|
||||
});
|
||||
|
||||
|
||||
it('should modify sentence when modified checkbox checked', async () => {
|
||||
const modifiedChkbxLabel = element.all(by.css('input[type="checkbox"]')).get(1);
|
||||
const modifiedSentence = element.all(by.css('div')).get(1);
|
||||
@@ -68,6 +66,4 @@ describe('Built-in Directives', () => {
|
||||
await fishbowlRadioButton.click();
|
||||
expect(await fishbowlDiv.getText()).toContain('mysterious');
|
||||
});
|
||||
|
||||
});
|
||||
|
||||
|
||||
@@ -2,25 +2,20 @@ export class Item {
|
||||
static nextId = 0;
|
||||
|
||||
static items: Item[] = [
|
||||
new Item(
|
||||
0,
|
||||
'Teapot',
|
||||
'stout'
|
||||
),
|
||||
new Item(0, 'Teapot', 'stout'),
|
||||
new Item(1, 'Lamp', 'bright'),
|
||||
new Item(2, 'Phone', 'slim' ),
|
||||
new Item(3, 'Television', 'vintage' ),
|
||||
new Item(4, 'Fishbowl')
|
||||
new Item(2, 'Phone', 'slim'),
|
||||
new Item(3, 'Television', 'vintage'),
|
||||
new Item(4, 'Fishbowl'),
|
||||
];
|
||||
|
||||
|
||||
constructor(
|
||||
public id: number,
|
||||
public name?: string,
|
||||
public feature?: string,
|
||||
public url?: string,
|
||||
public rate = 100,
|
||||
) {
|
||||
) {
|
||||
this.id = id ? id : Item.nextId++;
|
||||
}
|
||||
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
import { browser, element, by } from 'protractor';
|
||||
import {browser, element, by} from 'protractor';
|
||||
|
||||
describe('Built Template Functions Example', () => {
|
||||
beforeAll(() => browser.get(''));
|
||||
@@ -12,5 +12,4 @@ describe('Built Template Functions Example', () => {
|
||||
const header = element(by.css('h2'));
|
||||
expect(await header.getText()).toContain('$any( )');
|
||||
});
|
||||
|
||||
});
|
||||
|
||||
@@ -1,9 +1,9 @@
|
||||
// #docregion
|
||||
import { Architect } from '@angular-devkit/architect';
|
||||
import { TestingArchitectHost } from '@angular-devkit/architect/testing';
|
||||
import { schema } from '@angular-devkit/core';
|
||||
import { promises as fs } from 'fs';
|
||||
import { join } from 'path';
|
||||
import {Architect} from '@angular-devkit/architect';
|
||||
import {TestingArchitectHost} from '@angular-devkit/architect/testing';
|
||||
import {schema} from '@angular-devkit/core';
|
||||
import {promises as fs} from 'fs';
|
||||
import {join} from 'path';
|
||||
|
||||
describe('Copy File Builder', () => {
|
||||
let architect: Architect;
|
||||
|
||||
@@ -1,9 +1,9 @@
|
||||
// #docplaster
|
||||
// #docregion builder, builder-skeleton
|
||||
import { BuilderContext, BuilderOutput, createBuilder } from '@angular-devkit/architect';
|
||||
import { JsonObject } from '@angular-devkit/core';
|
||||
import {BuilderContext, BuilderOutput, createBuilder} from '@angular-devkit/architect';
|
||||
import {JsonObject} from '@angular-devkit/core';
|
||||
// #enddocregion builder-skeleton
|
||||
import { promises as fs } from 'fs';
|
||||
import {promises as fs} from 'fs';
|
||||
// #docregion builder-skeleton
|
||||
|
||||
interface Options extends JsonObject {
|
||||
@@ -13,10 +13,7 @@ interface Options extends JsonObject {
|
||||
|
||||
export default createBuilder(copyFileBuilder);
|
||||
|
||||
async function copyFileBuilder(
|
||||
options: Options,
|
||||
context: BuilderContext,
|
||||
): Promise<BuilderOutput> {
|
||||
async function copyFileBuilder(options: Options, context: BuilderContext): Promise<BuilderOutput> {
|
||||
// #enddocregion builder, builder-skeleton
|
||||
// #docregion progress-reporting
|
||||
context.reportStatus(`Copying ${options.source} to ${options.destination}.`);
|
||||
@@ -38,7 +35,7 @@ async function copyFileBuilder(
|
||||
|
||||
context.reportStatus('Done.');
|
||||
// #docregion builder
|
||||
return { success: true };
|
||||
return {success: true};
|
||||
// #enddocregion progress-reporting
|
||||
// #docregion builder-skeleton
|
||||
}
|
||||
|
||||
@@ -1,7 +1,6 @@
|
||||
import { browser, by, element } from 'protractor';
|
||||
import {browser, by, element} from 'protractor';
|
||||
|
||||
describe('Component Communication Cookbook Tests', () => {
|
||||
|
||||
beforeEach(() => browser.get(browser.baseUrl));
|
||||
|
||||
describe('Parent-to-child communication', () => {
|
||||
@@ -101,7 +100,7 @@ describe('Component Communication Cookbook Tests', () => {
|
||||
async function getActual() {
|
||||
const versionTag = element(by.tagName('app-version-child'));
|
||||
const label = await versionTag.element(by.tagName('h3')).getText();
|
||||
const ul = versionTag.element((by.tagName('ul')));
|
||||
const ul = versionTag.element(by.tagName('ul'));
|
||||
const logs = ul.all(by.tagName('li'));
|
||||
|
||||
return {
|
||||
@@ -124,8 +123,11 @@ describe('Component Communication Cookbook Tests', () => {
|
||||
|
||||
it('should process Agree vote', async () => {
|
||||
const voteLabel = element(by.tagName('app-vote-taker')).element(by.tagName('h3'));
|
||||
const agreeButton1 = element.all(by.tagName('app-voter')).get(0)
|
||||
.all(by.tagName('button')).get(0);
|
||||
const agreeButton1 = element
|
||||
.all(by.tagName('app-voter'))
|
||||
.get(0)
|
||||
.all(by.tagName('button'))
|
||||
.get(0);
|
||||
|
||||
await agreeButton1.click();
|
||||
|
||||
@@ -134,8 +136,11 @@ describe('Component Communication Cookbook Tests', () => {
|
||||
|
||||
it('should process Disagree vote', async () => {
|
||||
const voteLabel = element(by.tagName('app-vote-taker')).element(by.tagName('h3'));
|
||||
const agreeButton1 = element.all(by.tagName('app-voter')).get(1)
|
||||
.all(by.tagName('button')).get(1);
|
||||
const agreeButton1 = element
|
||||
.all(by.tagName('app-voter'))
|
||||
.get(1)
|
||||
.all(by.tagName('button'))
|
||||
.get(1);
|
||||
|
||||
await agreeButton1.click();
|
||||
|
||||
@@ -235,5 +240,4 @@ describe('Component Communication Cookbook Tests', () => {
|
||||
// ...
|
||||
// #enddocregion bidirectional-service
|
||||
});
|
||||
|
||||
});
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
import { Component } from '@angular/core';
|
||||
import {Component} from '@angular/core';
|
||||
|
||||
@Component({
|
||||
selector: 'app-root',
|
||||
templateUrl: './app.component.html'
|
||||
templateUrl: './app.component.html',
|
||||
})
|
||||
export class AppComponent { }
|
||||
export class AppComponent {}
|
||||
|
||||
@@ -1,25 +1,25 @@
|
||||
import { NgModule } from '@angular/core';
|
||||
import { BrowserModule } from '@angular/platform-browser';
|
||||
|
||||
import { AppComponent } from './app.component';
|
||||
import { AstronautComponent } from './astronaut.component';
|
||||
import { CountdownLocalVarParentComponent, CountdownViewChildParentComponent } from './countdown-parent.component';
|
||||
import { CountdownTimerComponent } from './countdown-timer.component';
|
||||
import { HeroChildComponent } from './hero-child.component';
|
||||
import { HeroParentComponent } from './hero-parent.component';
|
||||
import { MissionControlComponent } from './missioncontrol.component';
|
||||
import { NameChildComponent } from './name-child.component';
|
||||
import { NameParentComponent } from './name-parent.component';
|
||||
import { VersionChildComponent } from './version-child.component';
|
||||
import { VersionParentComponent } from './version-parent.component';
|
||||
import { VoterComponent } from './voter.component';
|
||||
import { VoteTakerComponent } from './votetaker.component';
|
||||
import {NgModule} from '@angular/core';
|
||||
import {BrowserModule} from '@angular/platform-browser';
|
||||
|
||||
import {AppComponent} from './app.component';
|
||||
import {AstronautComponent} from './astronaut.component';
|
||||
import {
|
||||
CountdownLocalVarParentComponent,
|
||||
CountdownViewChildParentComponent,
|
||||
} from './countdown-parent.component';
|
||||
import {CountdownTimerComponent} from './countdown-timer.component';
|
||||
import {HeroChildComponent} from './hero-child.component';
|
||||
import {HeroParentComponent} from './hero-parent.component';
|
||||
import {MissionControlComponent} from './missioncontrol.component';
|
||||
import {NameChildComponent} from './name-child.component';
|
||||
import {NameParentComponent} from './name-parent.component';
|
||||
import {VersionChildComponent} from './version-child.component';
|
||||
import {VersionParentComponent} from './version-parent.component';
|
||||
import {VoterComponent} from './voter.component';
|
||||
import {VoteTakerComponent} from './votetaker.component';
|
||||
|
||||
@NgModule({
|
||||
imports: [
|
||||
BrowserModule,
|
||||
],
|
||||
imports: [BrowserModule],
|
||||
declarations: [
|
||||
AppComponent,
|
||||
AstronautComponent,
|
||||
@@ -36,6 +36,6 @@ import { VoteTakerComponent } from './votetaker.component';
|
||||
VoterComponent,
|
||||
VoteTakerComponent,
|
||||
],
|
||||
bootstrap: [ AppComponent ],
|
||||
bootstrap: [AppComponent],
|
||||
})
|
||||
export class AppModule { }
|
||||
export class AppModule {}
|
||||
|
||||
@@ -1,8 +1,8 @@
|
||||
// #docregion
|
||||
import { Component, Input, OnDestroy } from '@angular/core';
|
||||
import {Component, Input, OnDestroy} from '@angular/core';
|
||||
|
||||
import { MissionService } from './mission.service';
|
||||
import { Subscription } from 'rxjs';
|
||||
import {MissionService} from './mission.service';
|
||||
import {Subscription} from 'rxjs';
|
||||
|
||||
@Component({
|
||||
selector: 'app-astronaut',
|
||||
@@ -16,7 +16,7 @@ import { Subscription } from 'rxjs';
|
||||
Confirm
|
||||
</button>
|
||||
</p>
|
||||
`
|
||||
`,
|
||||
})
|
||||
export class AstronautComponent implements OnDestroy {
|
||||
@Input() astronaut = '';
|
||||
@@ -26,11 +26,10 @@ export class AstronautComponent implements OnDestroy {
|
||||
subscription: Subscription;
|
||||
|
||||
constructor(private missionService: MissionService) {
|
||||
this.subscription = missionService.missionAnnounced$.subscribe(
|
||||
mission => {
|
||||
this.mission = mission;
|
||||
this.announced = true;
|
||||
this.confirmed = false;
|
||||
this.subscription = missionService.missionAnnounced$.subscribe((mission) => {
|
||||
this.mission = mission;
|
||||
this.announced = true;
|
||||
this.confirmed = false;
|
||||
});
|
||||
}
|
||||
|
||||
|
||||
+16
-11
@@ -1,9 +1,9 @@
|
||||
// #docplaster
|
||||
// #docregion vc
|
||||
import { AfterViewInit, ViewChild } from '@angular/core';
|
||||
import {AfterViewInit, ViewChild} from '@angular/core';
|
||||
// #docregion lv
|
||||
import { Component } from '@angular/core';
|
||||
import { CountdownTimerComponent } from './countdown-timer.component';
|
||||
import {Component} from '@angular/core';
|
||||
import {CountdownTimerComponent} from './countdown-timer.component';
|
||||
|
||||
// #enddocregion lv
|
||||
// #enddocregion vc
|
||||
@@ -19,9 +19,9 @@ import { CountdownTimerComponent } from './countdown-timer.component';
|
||||
<div class="seconds">{{timer.seconds}}</div>
|
||||
<app-countdown-timer #timer></app-countdown-timer>
|
||||
`,
|
||||
styleUrls: ['../assets/demo.css']
|
||||
styleUrls: ['../assets/demo.css'],
|
||||
})
|
||||
export class CountdownLocalVarParentComponent { }
|
||||
export class CountdownLocalVarParentComponent {}
|
||||
// #enddocregion lv
|
||||
|
||||
//// View Child version
|
||||
@@ -35,23 +35,28 @@ export class CountdownLocalVarParentComponent { }
|
||||
<div class="seconds">{{ seconds() }}</div>
|
||||
<app-countdown-timer></app-countdown-timer>
|
||||
`,
|
||||
styleUrls: ['../assets/demo.css']
|
||||
styleUrls: ['../assets/demo.css'],
|
||||
})
|
||||
export class CountdownViewChildParentComponent implements AfterViewInit {
|
||||
|
||||
@ViewChild(CountdownTimerComponent)
|
||||
private timerComponent!: CountdownTimerComponent;
|
||||
|
||||
seconds() { return 0; }
|
||||
seconds() {
|
||||
return 0;
|
||||
}
|
||||
|
||||
ngAfterViewInit() {
|
||||
// Redefine `seconds()` to get from the `CountdownTimerComponent.seconds` ...
|
||||
// but wait a tick first to avoid one-time devMode
|
||||
// unidirectional-data-flow-violation error
|
||||
setTimeout(() => this.seconds = () => this.timerComponent.seconds, 0);
|
||||
setTimeout(() => (this.seconds = () => this.timerComponent.seconds), 0);
|
||||
}
|
||||
|
||||
start() { this.timerComponent.start(); }
|
||||
stop() { this.timerComponent.stop(); }
|
||||
start() {
|
||||
this.timerComponent.start();
|
||||
}
|
||||
stop() {
|
||||
this.timerComponent.stop();
|
||||
}
|
||||
}
|
||||
// #enddocregion vc
|
||||
|
||||
+12
-6
@@ -1,18 +1,22 @@
|
||||
// #docregion
|
||||
import { Component, OnDestroy } from '@angular/core';
|
||||
import {Component, OnDestroy} from '@angular/core';
|
||||
|
||||
@Component({
|
||||
selector: 'app-countdown-timer',
|
||||
template: '<p>{{message}}</p>'
|
||||
template: '<p>{{message}}</p>',
|
||||
})
|
||||
export class CountdownTimerComponent implements OnDestroy {
|
||||
message = '';
|
||||
seconds = 11;
|
||||
|
||||
ngOnDestroy() { this.clearTimer?.(); }
|
||||
ngOnDestroy() {
|
||||
this.clearTimer?.();
|
||||
}
|
||||
|
||||
start() { this.countDown(); }
|
||||
stop() {
|
||||
start() {
|
||||
this.countDown();
|
||||
}
|
||||
stop() {
|
||||
this.clearTimer?.();
|
||||
this.message = `Holding at T-${this.seconds} seconds`;
|
||||
}
|
||||
@@ -26,7 +30,9 @@ export class CountdownTimerComponent implements OnDestroy {
|
||||
if (this.seconds === 0) {
|
||||
this.message = 'Blast off!';
|
||||
} else {
|
||||
if (this.seconds < 0) { this.seconds = 10; } // reset
|
||||
if (this.seconds < 0) {
|
||||
this.seconds = 10;
|
||||
} // reset
|
||||
this.message = `T-${this.seconds} seconds and counting`;
|
||||
}
|
||||
}, 1000);
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user