Previously, we looked at creating and setting up a new Angular project. In this article we will analyze the basic structure.
Let me remind you that the series is devoted to the development of a web application for searching for airline tickets and hotels. The project is based on a project from Alfa Travel - travel.alfabank.ru
The site consists of the following blocks:
This allows us to highlight the main parts:
Change the AppComponent so that it only outputs routerOutlet.
import { ChangeDetectionStrategy, Component } from '@angular/core'; import { RouterOutlet } from '@angular/router'; @Component({ selector: 'baf-root', standalone: true, imports: [RouterOutlet], template: '<router-outlet/>', changeDetection: ChangeDetectionStrategy.OnPush, }) export class AppComponent {}
Delete unused files: app.component.spec.ts, app.component.scss and app.component.html.
Add configuration for the browser version in app.config.browser.ts:
import { ApplicationConfig, mergeApplicationConfig } from '@angular/core'; import { provideAnimations } from '@angular/platform-browser/animations'; import { appConfig } from './app.config'; const browserConfig: ApplicationConfig = { providers: [provideAnimations()], }; export const config = mergeApplicationConfig(appConfig, browserConfig);
And import it into main.ts:
import { bootstrapApplication } from '@angular/platform-browser'; import { AppComponent } from './app/app.component'; import { config } from './app/app.config.browser'; bootstrapApplication(AppComponent, config).catch((err) => console.error(err));
For the mobile version we need to work with touches and swipes, so we use hammerjs
Install the dependency:
yarn add -D hammerjs @types/hammerjs
Connect animation and hammerjs in the browser:
import 'hammerjs'; import { ApplicationConfig, mergeApplicationConfig } from '@angular/core'; import { provideAnimations } from '@angular/platform-browser/animations'; import { appConfig } from './app.config'; const browserConfig: ApplicationConfig = { providers: [provideAnimations()], }; export const config = mergeApplicationConfig(appConfig, browserConfig);
You need to set the configuration for hammerjs.
Create a new core folder, in which we will store everything that is an integral part of the project.
mkdir src/app/core mkdir src/app/core/lib echo >src/app/core/index.ts mkdir src/app/core/lib/hammer echo >src/app/core/lib/hammer/hammer.ts
In hammer.ts we specify the config:
import { EnvironmentProviders, importProvidersFrom, Injectable, Provider } from '@angular/core'; import { HAMMER_GESTURE_CONFIG, HammerGestureConfig, HammerModule } from '@angular/platform-browser'; @Injectable() export class HammerConfig extends HammerGestureConfig { override overrides = { swipe: { velocity: 0.4, threshold: 20 }, pinch: { enable: false }, rotate: { enable: false }, }; } export function provideHammer(): (Provider | EnvironmentProviders)[] { return [ importProvidersFrom(HammerModule), { provide: HAMMER_GESTURE_CONFIG, useClass: HammerConfig, }, ]; }
Export to src/app/core/index.ts:
export * from './lib/hammer/hammer';
For quick access, add an alias to tsconfig.json:
{ "compileOnSave": false, "compilerOptions": { "outDir": "./dist/out-tsc", "strict": true, "noImplicitOverride": true, "noPropertyAccessFromIndexSignature": true, "noImplicitReturns": true, "noFallthroughCasesInSwitch": true, "skipLibCheck": true, "esModuleInterop": true, "sourceMap": true, "declaration": false, "experimentalDecorators": true, "moduleResolution": "bundler", "importHelpers": true, "target": "ES2022", "module": "ES2022", "useDefineForClassFields": false, "lib": ["ES2022", "dom"], "baseUrl": ".", "paths": { "@baf/core": ["src/app/core/index.ts"] } }, "angularCompilerOptions": { "enableI18nLegacyMessageIdFormat": false, "strictInjectionParameters": true, "strictInputAccessModifiers": true, "strictTemplates": true } }
Note that you also need to specify the baseUrl.
Connect in the browser version:
import { ApplicationConfig, mergeApplicationConfig } from '@angular/core'; import { provideAnimations } from '@angular/platform-browser/animations'; import { provideHammer } from '@baf/core'; import { appConfig } from './app.config'; const browserConfig: ApplicationConfig = { providers: [provideAnimations(), provideHammer()], }; export const config = mergeApplicationConfig(appConfig, browserConfig);
The layout is common to the entire web application. Let's add a new UI folder in which we will store the components.
mkdir src/app/ui mkdir src/app/ui/layout/lib echo >src/app/ui/layout/index.ts
Run the command:
yarn ng g c layout
Move the content to src/app/ui/layout/lib.
We see that everything is created without the attributes we need and with test files:
import { Component } from '@angular/core'; @Component({ selector: 'baf-layout', standalone: true, imports: [], templateUrl: './layout.component.html', styleUrl: './layout.component.scss' }) export class LayoutComponent {}
In angular.json we will specify the properties:
{ "@schematics/angular:component": { "style": "scss", "changeDetection": "OnPush", "skipTests": true } }
Edit LayoutComponent:
import { ChangeDetectionStrategy, Component } from '@angular/core'; import { RouterOutlet } from '@angular/router'; @Component({ selector: 'baf-results', standalone: true, imports: [RouterOutlet], templateUrl: './layout.component.html', styleUrl: './layout.component.scss', changeDetection: ChangeDetectionStrategy.OnPush, }) export class LayoutComponent {}
Add a header, content and footer:
<router-outlet name="top" /> <header> <router-outlet name="header" /> </header> <main> <router-outlet name="main-top" /> <router-outlet /> <router-outlet name="main-bottom" /> </main> <footer> <router-outlet name="footer" /> </footer> <router-outlet name="bottom" />
A few styles:
:host { display: flex; min-height: 100vh; flex-direction: column; } header, footer { flex-shrink: 0; } main { flex-grow: 1; overflow-x: hidden; }
Export the component to src/app/ui/layout/index.ts:
export * from './lib/layout.component';
And write the alias in tsconfig.json:
{ "paths": { "@baf/core": ["src/app/core/index.ts"], "@baf/ui/layout": ["src/app/ui/layout/index.ts"] } }
Before displaying the layout, you need to configure the styles in the application.
To reset the default appearance in the browser, just the following:
/* You can add global styles to this file, and also import other style files */ @use '@angular/cdk' as cdk; // Hack for global CDK dialogs styles @include cdk.overlay(); *, *::before, *::after { box-sizing: border-box; } html { -moz-text-size-adjust: none; -webkit-text-size-adjust: none; text-size-adjust: none; } blockquote { margin: 0; padding: 1rem; } h1 { margin-block-start: 1.45rem; margin-block-end: 1.45rem; } h2 { margin-block-start: 1.25rem; margin-block-end: 1.25rem; } h3 { margin-block-start: 1.175rem; margin-block-end: 1.175rem; } h4 { margin-block-start: 1.15rem; margin-block-end: 1.15rem; } figure { margin: 0; } p { margin-block-start: 1rem; margin-block-end: 1rem; } ul[role='list'], ol[role='list'] { list-style: none; } body { margin: 0; min-height: 100vh; line-height: 1.5; font-family: Arial, ui-sans-serif, system-ui, -apple-system, BlinkMacSystemFont, sans-serif; font-size: 16px; } h1, h2, h3, h4, button, input, label { line-height: 1.1; } h1, h2, h3, h4 { text-wrap: balance; } a:not([class]) { text-decoration-skip-ink: auto; color: currentColor; } img, picture { max-width: 100%; display: block; } input, button, textarea, select { font: inherit; } textarea:not([rows]) { min-height: 10rem; } :target { scroll-margin-block: 5ex; }
Reset will be placed in styles.scss.
Edit index.html:
<!doctype html> <html lang="en"> <head> <meta charset="utf-8" /> <title>BuyAndFly</title> <base href="/" /> <meta name="viewport" content="width=device-width, initial-scale=1" /> <link rel="preconnect" href="https://fonts.googleapis.com" /> <link rel="preconnect" href="https://fonts.gstatic.com" crossorigin /> <link href="https://fonts.googleapis.com/css2?family=Roboto:wght@300;400;500&display=swap" rel="stylesheet" /> <meta name="description" content="Example Angular 18 application for search for cheap flights and hotels." /> <link rel="preconnect" href="https://photo.hotellook.com" /> <link rel="apple-touch-icon" sizes="180x180" href="/favicons/apple-touch-icon.png" /> <link rel="icon" type="image/png" sizes="32x32" href="/favicons/favicon-32x32.png" /> <link rel="icon" type="image/png" sizes="16x16" href="/favicons/favicon-16x16.png" /> <link rel="manifest" href="/site.webmanifest" /> <link rel="mask-icon" href="/favicons/safari-pinned-tab.svg" color="#172659" /> <meta name="msapplication-config" content="/browserconfig.xml" /> <meta name="msapplication-TileColor" content="#172659" /> <meta name="theme-color" content="#ffffff" /> </head> <body> <baf-root></baf-root> </body> </html>
Add the generated favicons to public, as well as other files:
browserconfig.xml:
<?xml version="1.0" encoding="utf-8"?> <browserconfig> <msapplication> <tile> <square150x150logo src="/favicons/mstile-150x150.png"/> <TileColor>#172659</TileColor> </tile> </msapplication> </browserconfig>
site.webmanifest:
{ "name": "Buy & Fly", "short_name": "Buy & Fly", "icons": [ { "src": "/favicons/android-chrome-192x192.png", "sizes": "192x192", "type": "image/png" }, { "src": "/favicons/android-chrome-512x512.png", "sizes": "512x512", "type": "image/png" } ], "theme_color": "#ffffff", "background_color": "#ffffff", "display": "standalone", "start_url": ".", "description": "Search for cheap flights and hotels.", "categories": ["travel", "education"], "screenshots": [ { "src": "screenshot.webp", "sizes": "1280x720", "type": "image/webp" } ] }
robots.txt:
User-agent: * Disallow: /api User-agent: Yandex Disallow: /api Clean-param: bonus&utm_source&utm_medium&utm_campaign&utm_term&utm_content&click_id&appstore&platform Host: https://buy-and-fly.fafn.ru Sitemap: https://buy-and-fly.fafn.ru/sitemap.xml
At the end we use the layout in src/app/app.routes.ts:
import { Routes } from '@angular/router'; export const routes: Routes = [ { path: '', loadComponent: () => import('@baf/ui/layout').then((m) => m.LayoutComponent), children: [], }, ];
Launch the application:
yarn serve
We will see a white screen :)
Создадим шапку и подвал:
yarn ng g c header yarn ng g c footer
Перенесем в ui/layout и экспортируем:
export * from './lib/footer/footer.component'; export * from './lib/header/header.component'; export * from './lib/layout.component';
Подключим их в приложении:
import { Routes } from '@angular/router'; export const routes: Routes = [ { path: '', loadComponent: () => import('@baf/ui/layout').then((m) => m.LayoutComponent), children: [ { path: '', loadComponent: () => import('@baf/ui/layout').then((m) => m.HeaderComponent), outlet: 'header', }, { path: '', loadComponent: () => import('@baf/ui/layout').then((m) => m.FooterComponent), outlet: 'footer', }, ], }, ];
Запустим проект:
yarn serve
Видим созданные компоненты.
В следующей статье добавим core сервисы и интерфейсы.
Все исходники находятся на github, в репозитории - github.com/Fafnur/buy-and-fly
Демо можно посмотреть здесь - buy-and-fly.fafn.ru/
Мои группы: telegram, medium, vk, x.com, linkedin, site
The above is the detailed content of Creating a Basic Framework for Angular 18. For more information, please follow other related articles on the PHP Chinese website!