├── .editorconfig ├── .gitignore ├── .vscode ├── extensions.json ├── launch.json └── tasks.json ├── LICENSE ├── README.md ├── angular.json ├── package-lock.json ├── package.json ├── public └── favicon.ico ├── src ├── app │ ├── app.component.html │ ├── app.component.scss │ ├── app.component.spec.ts │ ├── app.component.ts │ ├── app.config.ts │ ├── app.routes.ts │ ├── core │ │ ├── guards │ │ │ ├── auth.guard.spec.ts │ │ │ └── auth.guard.ts │ │ ├── interceptors │ │ │ ├── error-handling.interceptor.ts │ │ │ ├── jwt.interceptor.spec.ts │ │ │ └── jwt.interceptor.ts │ │ ├── models │ │ │ └── sample-model.model.ts │ │ └── services │ │ │ ├── auth.service.spec.ts │ │ │ └── auth.service.ts │ ├── modules │ │ └── sample-module │ │ │ ├── components │ │ │ └── sample │ │ │ │ ├── sample.component.html │ │ │ │ ├── sample.component.scss │ │ │ │ ├── sample.component.spec.ts │ │ │ │ └── sample.component.ts │ │ │ ├── models │ │ │ └── sample-model.model.ts │ │ │ ├── sample.routes.ts │ │ │ └── services │ │ │ ├── sample.service.spec.ts │ │ │ └── sample.service.ts │ └── shared │ │ └── services │ │ ├── alert.service.spec.ts │ │ └── alert.service.ts ├── index.html ├── main.ts └── styles.scss ├── tsconfig.app.json ├── tsconfig.json └── tsconfig.spec.json /.editorconfig: -------------------------------------------------------------------------------- 1 | # Editor configuration, see https://editorconfig.org 2 | root = true 3 | 4 | [*] 5 | charset = utf-8 6 | indent_style = space 7 | indent_size = 2 8 | insert_final_newline = true 9 | trim_trailing_whitespace = true 10 | 11 | [*.ts] 12 | quote_type = single 13 | 14 | [*.md] 15 | max_line_length = off 16 | trim_trailing_whitespace = false 17 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | # See https://docs.github.com/get-started/getting-started-with-git/ignoring-files for more about ignoring files. 2 | 3 | # Compiled output 4 | /dist 5 | /tmp 6 | /out-tsc 7 | /bazel-out 8 | 9 | # Node 10 | /node_modules 11 | npm-debug.log 12 | yarn-error.log 13 | 14 | # IDEs and editors 15 | .idea/ 16 | .project 17 | .classpath 18 | .c9/ 19 | *.launch 20 | .settings/ 21 | *.sublime-workspace 22 | 23 | # Visual Studio Code 24 | .vscode/* 25 | !.vscode/settings.json 26 | !.vscode/tasks.json 27 | !.vscode/launch.json 28 | !.vscode/extensions.json 29 | .history/* 30 | 31 | # Miscellaneous 32 | /.angular/cache 33 | .sass-cache/ 34 | /connect.lock 35 | /coverage 36 | /libpeerconnection.log 37 | testem.log 38 | /typings 39 | 40 | # System files 41 | .DS_Store 42 | Thumbs.db 43 | -------------------------------------------------------------------------------- /.vscode/extensions.json: -------------------------------------------------------------------------------- 1 | { 2 | // For more information, visit: https://go.microsoft.com/fwlink/?linkid=827846 3 | "recommendations": ["angular.ng-template"] 4 | } 5 | -------------------------------------------------------------------------------- /.vscode/launch.json: -------------------------------------------------------------------------------- 1 | { 2 | // For more information, visit: https://go.microsoft.com/fwlink/?linkid=830387 3 | "version": "0.2.0", 4 | "configurations": [ 5 | { 6 | "name": "ng serve", 7 | "type": "chrome", 8 | "request": "launch", 9 | "preLaunchTask": "npm: start", 10 | "url": "http://localhost:4200/" 11 | }, 12 | { 13 | "name": "ng test", 14 | "type": "chrome", 15 | "request": "launch", 16 | "preLaunchTask": "npm: test", 17 | "url": "http://localhost:9876/debug.html" 18 | } 19 | ] 20 | } 21 | -------------------------------------------------------------------------------- /.vscode/tasks.json: -------------------------------------------------------------------------------- 1 | { 2 | // For more information, visit: https://go.microsoft.com/fwlink/?LinkId=733558 3 | "version": "2.0.0", 4 | "tasks": [ 5 | { 6 | "type": "npm", 7 | "script": "start", 8 | "isBackground": true, 9 | "problemMatcher": { 10 | "owner": "typescript", 11 | "pattern": "$tsc", 12 | "background": { 13 | "activeOnStart": true, 14 | "beginsPattern": { 15 | "regexp": "(.*?)" 16 | }, 17 | "endsPattern": { 18 | "regexp": "bundle generation complete" 19 | } 20 | } 21 | } 22 | }, 23 | { 24 | "type": "npm", 25 | "script": "test", 26 | "isBackground": true, 27 | "problemMatcher": { 28 | "owner": "typescript", 29 | "pattern": "$tsc", 30 | "background": { 31 | "activeOnStart": true, 32 | "beginsPattern": { 33 | "regexp": "(.*?)" 34 | }, 35 | "endsPattern": { 36 | "regexp": "bundle generation complete" 37 | } 38 | } 39 | } 40 | } 41 | ] 42 | } 43 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2024 Amin-Karimi 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # Angular 18.1 Sample Project 2 | 3 |

4 | Angular Logo 5 |

6 | 7 | This repository provides a **simple yet scalable** Angular 18.1 project setup. It is designed as an **open-source template** for developers looking for a quick and organized start with Angular. 8 | 9 | ## Features 10 | 11 | - **Angular 18.1**: Built with the latest Angular version for modern web development. 12 | - **Modular Architecture**: Clear separation of components, services, and models for easy maintenance. 13 | - **Monolithic Design**: Optimized for simple applications with scalability in mind. 14 | - **Unit Testing**: Preconfigured with Jasmine and Karma. 15 | - **Responsive Structure**: Easily adaptable for desktop and mobile. 16 | 17 | ## Getting Started 18 | 19 | 1. Clone the repository: 20 | ```bash 21 | git clone https://github.com/Amin-Karimi/angular-sample-small-project.git 22 | ``` 23 | 2. Navigate to the project folder: 24 | ```bash 25 | cd angular-sample-small-project 26 | ``` 27 | 3. Install dependencies: 28 | ```bash 29 | npm install 30 | ``` 31 | 4. Start the development server: 32 | ```bash 33 | ng serve 34 | ``` 35 | 36 | ## How to Use 37 | 38 | - Use this template as a foundation for your Angular projects. 39 | - Customize components, services, and routing to fit your needs. 40 | - Run tests with the built-in configuration. 41 | 42 | ## Contributing 43 | 44 | Feel free to fork this repository and make your own contributions! Suggestions and improvements are always welcome. 45 | 46 | ## License 47 | 48 | This project is licensed under the [MIT License](LICENSE). 49 | 50 | --- 51 | 52 | **Angular 18.1**, **open-source**, **modular architecture**, **template**, 53 | -------------------------------------------------------------------------------- /angular.json: -------------------------------------------------------------------------------- 1 | { 2 | "$schema": "./node_modules/@angular/cli/lib/config/schema.json", 3 | "version": 1, 4 | "newProjectRoot": "projects", 5 | "projects": { 6 | "angular-sample-small-project": { 7 | "projectType": "application", 8 | "schematics": { 9 | "@schematics/angular:component": { 10 | "style": "scss" 11 | } 12 | }, 13 | "root": "", 14 | "sourceRoot": "src", 15 | "prefix": "app", 16 | "architect": { 17 | "build": { 18 | "builder": "@angular-devkit/build-angular:application", 19 | "options": { 20 | "outputPath": "dist/angular-sample-small-project", 21 | "index": "src/index.html", 22 | "browser": "src/main.ts", 23 | "polyfills": [ 24 | "zone.js" 25 | ], 26 | "tsConfig": "tsconfig.app.json", 27 | "inlineStyleLanguage": "scss", 28 | "assets": [ 29 | { 30 | "glob": "**/*", 31 | "input": "public" 32 | } 33 | ], 34 | "styles": [ 35 | "src/styles.scss" 36 | ], 37 | "scripts": [] 38 | }, 39 | "configurations": { 40 | "production": { 41 | "budgets": [ 42 | { 43 | "type": "initial", 44 | "maximumWarning": "500kB", 45 | "maximumError": "1MB" 46 | }, 47 | { 48 | "type": "anyComponentStyle", 49 | "maximumWarning": "2kB", 50 | "maximumError": "4kB" 51 | } 52 | ], 53 | "outputHashing": "all" 54 | }, 55 | "development": { 56 | "optimization": false, 57 | "extractLicenses": false, 58 | "sourceMap": true 59 | } 60 | }, 61 | "defaultConfiguration": "production" 62 | }, 63 | "serve": { 64 | "builder": "@angular-devkit/build-angular:dev-server", 65 | "configurations": { 66 | "production": { 67 | "buildTarget": "angular-sample-small-project:build:production" 68 | }, 69 | "development": { 70 | "buildTarget": "angular-sample-small-project:build:development" 71 | } 72 | }, 73 | "defaultConfiguration": "development" 74 | }, 75 | "extract-i18n": { 76 | "builder": "@angular-devkit/build-angular:extract-i18n" 77 | }, 78 | "test": { 79 | "builder": "@angular-devkit/build-angular:karma", 80 | "options": { 81 | "polyfills": [ 82 | "zone.js", 83 | "zone.js/testing" 84 | ], 85 | "tsConfig": "tsconfig.spec.json", 86 | "inlineStyleLanguage": "scss", 87 | "assets": [ 88 | { 89 | "glob": "**/*", 90 | "input": "public" 91 | } 92 | ], 93 | "styles": [ 94 | "src/styles.scss" 95 | ], 96 | "scripts": [] 97 | } 98 | } 99 | } 100 | } 101 | } 102 | } 103 | -------------------------------------------------------------------------------- /package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "angular-sample-small-project", 3 | "version": "1.0.0", 4 | "license": "MIT", 5 | "author": "Amin Karimi ", 6 | "repository": { 7 | "type": "git", 8 | "url": "https://github.com/Amin-Karimi/angular-sample-small-project.git" 9 | }, 10 | "scripts": { 11 | "ng": "ng", 12 | "start": "ng serve", 13 | "build": "ng build", 14 | "watch": "ng build --watch --configuration development", 15 | "test": "ng test" 16 | }, 17 | "private": true, 18 | "dependencies": { 19 | "@angular/animations": "^19.0.5", 20 | "@angular/common": "^19.0.5", 21 | "@angular/compiler": "^19.0.5", 22 | "@angular/core": "^19.0.5", 23 | "@angular/forms": "^19.0.5", 24 | "@angular/platform-browser": "^19.0.5", 25 | "@angular/platform-browser-dynamic": "^19.0.5", 26 | "@angular/router": "^19.0.5", 27 | "ngx-toastr": "^19.0.0", 28 | "rxjs": "~7.8.1", 29 | "tslib": "^2.8.1", 30 | "zone.js": "~0.15.0" 31 | }, 32 | "devDependencies": { 33 | "@angular-devkit/build-angular": "^19.0.6", 34 | "@angular/cli": "^19.0.6", 35 | "@angular/compiler-cli": "^19.0.5", 36 | "@types/jasmine": "~5.1.5", 37 | "jasmine-core": "~5.5.0", 38 | "karma": "~6.4.4", 39 | "karma-chrome-launcher": "~3.2.0", 40 | "karma-coverage": "~2.2.1", 41 | "karma-jasmine": "~5.1.0", 42 | "karma-jasmine-html-reporter": "~2.1.0", 43 | "typescript": "~5.7.2" 44 | } 45 | } 46 | -------------------------------------------------------------------------------- /public/favicon.ico: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/milad-hub/angular-sample-small-project/21cc97b75fbffbad72e497b76e67ba6629260fbd/public/favicon.ico -------------------------------------------------------------------------------- /src/app/app.component.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | sample 4 | 5 | for 6 | 7 | small 8 | 9 | projects 10 | 11 | 12 | 15 | 16 |
17 | 18 |
-------------------------------------------------------------------------------- /src/app/app.component.scss: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/milad-hub/angular-sample-small-project/21cc97b75fbffbad72e497b76e67ba6629260fbd/src/app/app.component.scss -------------------------------------------------------------------------------- /src/app/app.component.spec.ts: -------------------------------------------------------------------------------- 1 | import { TestBed } from '@angular/core/testing'; 2 | import { AppComponent } from './app.component'; 3 | 4 | describe('AppComponent', () => { 5 | beforeEach(async () => { 6 | await TestBed.configureTestingModule({ 7 | imports: [AppComponent], 8 | }).compileComponents(); 9 | }); 10 | 11 | it('should create the app', () => { 12 | const fixture = TestBed.createComponent(AppComponent); 13 | const app = fixture.componentInstance; 14 | expect(app).toBeTruthy(); 15 | }); 16 | 17 | it(`should have the 'angular-sample-small-project' title`, () => { 18 | const fixture = TestBed.createComponent(AppComponent); 19 | const app = fixture.componentInstance; 20 | expect(app.title).toEqual('angular-sample-small-project'); 21 | }); 22 | 23 | it('should render title', () => { 24 | const fixture = TestBed.createComponent(AppComponent); 25 | fixture.detectChanges(); 26 | const compiled = fixture.nativeElement as HTMLElement; 27 | expect(compiled.querySelector('h1')?.textContent).toContain('Hello, angular-sample-small-project'); 28 | }); 29 | }); 30 | -------------------------------------------------------------------------------- /src/app/app.component.ts: -------------------------------------------------------------------------------- 1 | import { Component } from '@angular/core'; 2 | import { RouterLink, RouterOutlet } from '@angular/router'; 3 | 4 | @Component({ 5 | selector: 'app-root', 6 | standalone: true, 7 | imports: [RouterOutlet, RouterLink], 8 | templateUrl: './app.component.html', 9 | styleUrl: './app.component.scss' 10 | }) 11 | export class AppComponent { 12 | title = 'angular-sample-small-project'; 13 | } 14 | -------------------------------------------------------------------------------- /src/app/app.config.ts: -------------------------------------------------------------------------------- 1 | import { ApplicationConfig, provideZoneChangeDetection } from '@angular/core'; 2 | import { provideRouter } from '@angular/router'; 3 | 4 | import { routes } from './app.routes'; 5 | import { jwtInterceptor } from './core/interceptors/jwt.interceptor'; 6 | import { provideHttpClient, withInterceptors } from '@angular/common/http'; 7 | import { provideToastr } from 'ngx-toastr'; 8 | 9 | export const appConfig: ApplicationConfig = { 10 | providers: [provideZoneChangeDetection({ eventCoalescing: true }), provideRouter(routes), 11 | provideHttpClient(withInterceptors([jwtInterceptor])), provideToastr() 12 | ] 13 | }; 14 | -------------------------------------------------------------------------------- /src/app/app.routes.ts: -------------------------------------------------------------------------------- 1 | import { Routes } from '@angular/router'; 2 | 3 | export const routes: Routes = [ 4 | { 5 | path: '', redirectTo: 'dashboard', pathMatch: "full" 6 | }, 7 | { 8 | path: 'sample', loadChildren: () => import('./modules/sample-module/sample.routes') 9 | }, 10 | ]; 11 | -------------------------------------------------------------------------------- /src/app/core/guards/auth.guard.spec.ts: -------------------------------------------------------------------------------- 1 | import { TestBed } from '@angular/core/testing'; 2 | import { CanActivateFn } from '@angular/router'; 3 | 4 | import { authGuard } from './auth.guard'; 5 | 6 | describe('authGuard', () => { 7 | const executeGuard: CanActivateFn = (...guardParameters) => 8 | TestBed.runInInjectionContext(() => authGuard(...guardParameters)); 9 | 10 | beforeEach(() => { 11 | TestBed.configureTestingModule({}); 12 | }); 13 | 14 | it('should be created', () => { 15 | expect(executeGuard).toBeTruthy(); 16 | }); 17 | }); 18 | -------------------------------------------------------------------------------- /src/app/core/guards/auth.guard.ts: -------------------------------------------------------------------------------- 1 | import { CanActivateFn } from '@angular/router'; 2 | import { AuthService } from '../services/auth.service'; 3 | import { inject } from '@angular/core'; 4 | 5 | export const authGuard: CanActivateFn = (route, state) => { 6 | const authService: AuthService = inject(AuthService) 7 | return authService.userIsLogin(); 8 | }; 9 | -------------------------------------------------------------------------------- /src/app/core/interceptors/error-handling.interceptor.ts: -------------------------------------------------------------------------------- 1 | import { HttpErrorResponse, HttpInterceptorFn } from '@angular/common/http'; 2 | import { catchError, throwError } from 'rxjs'; 3 | import { inject } from '@angular/core'; 4 | import { AlertService } from '@shared/services/alert.service'; 5 | 6 | export const errorHandlingInterceptor: HttpInterceptorFn = (req, next) => { 7 | const alertService = inject(AlertService) 8 | return next(req).pipe( 9 | catchError( 10 | (error: HttpErrorResponse) => { 11 | switch (error.status) { 12 | case 400: 13 | alertService.failedAlert('Operation Failed') 14 | return throwError(() => error) 15 | 16 | case 401: 17 | alertService.failedAlert('unauthorized') 18 | return throwError(() => error) 19 | 20 | case 403: 21 | alertService.failedAlert('Access denied') 22 | return throwError(() => error) 23 | 24 | case 404: 25 | alertService.failedAlert('Operation Failed') 26 | return throwError(() => error) 27 | 28 | case 500: 29 | alertService.failedAlert('Server error') 30 | return throwError(() => error) 31 | } 32 | 33 | 34 | return throwError(() => error) 35 | })) 36 | 37 | }; 38 | 39 | -------------------------------------------------------------------------------- /src/app/core/interceptors/jwt.interceptor.spec.ts: -------------------------------------------------------------------------------- 1 | import { TestBed } from '@angular/core/testing'; 2 | import { HttpInterceptorFn } from '@angular/common/http'; 3 | 4 | import { jwtInterceptor } from './jwt.interceptor'; 5 | 6 | describe('jwtInterceptor', () => { 7 | const interceptor: HttpInterceptorFn = (req, next) => 8 | TestBed.runInInjectionContext(() => jwtInterceptor(req, next)); 9 | 10 | beforeEach(() => { 11 | TestBed.configureTestingModule({}); 12 | }); 13 | 14 | it('should be created', () => { 15 | expect(interceptor).toBeTruthy(); 16 | }); 17 | }); 18 | -------------------------------------------------------------------------------- /src/app/core/interceptors/jwt.interceptor.ts: -------------------------------------------------------------------------------- 1 | import { HttpInterceptorFn } from '@angular/common/http'; 2 | import { AuthService } from '../services/auth.service'; 3 | import { inject } from '@angular/core'; 4 | 5 | export const jwtInterceptor: HttpInterceptorFn = (req, next) => { 6 | const authService: AuthService = inject(AuthService) 7 | 8 | if (authService.token) { 9 | const jwtRequest = req.clone({ 10 | headers: req.headers.set('Authorization', authService.token), 11 | }); 12 | 13 | return next(jwtRequest); 14 | } 15 | 16 | return next(req); 17 | 18 | }; 19 | -------------------------------------------------------------------------------- /src/app/core/models/sample-model.model.ts: -------------------------------------------------------------------------------- 1 | export interface IUser { 2 | name: string, 3 | phone: string 4 | } -------------------------------------------------------------------------------- /src/app/core/services/auth.service.spec.ts: -------------------------------------------------------------------------------- 1 | import { TestBed } from '@angular/core/testing'; 2 | 3 | import { AuthService } from './auth.service'; 4 | 5 | describe('AuthService', () => { 6 | let service: AuthService; 7 | 8 | beforeEach(() => { 9 | TestBed.configureTestingModule({}); 10 | service = TestBed.inject(AuthService); 11 | }); 12 | 13 | it('should be created', () => { 14 | expect(service).toBeTruthy(); 15 | }); 16 | }); 17 | -------------------------------------------------------------------------------- /src/app/core/services/auth.service.ts: -------------------------------------------------------------------------------- 1 | import { Injectable } from '@angular/core'; 2 | 3 | @Injectable({ 4 | providedIn: 'root' 5 | }) 6 | export class AuthService { 7 | token: string = '' 8 | constructor() { } 9 | 10 | userIsLogin(): boolean { 11 | return true 12 | } 13 | 14 | setToken(token: string) { 15 | this.token = token 16 | } 17 | } 18 | -------------------------------------------------------------------------------- /src/app/modules/sample-module/components/sample/sample.component.html: -------------------------------------------------------------------------------- 1 |

sample Component works!

2 |
3 | Sample service => {{sampleService.sample()}} 4 |
-------------------------------------------------------------------------------- /src/app/modules/sample-module/components/sample/sample.component.scss: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/milad-hub/angular-sample-small-project/21cc97b75fbffbad72e497b76e67ba6629260fbd/src/app/modules/sample-module/components/sample/sample.component.scss -------------------------------------------------------------------------------- /src/app/modules/sample-module/components/sample/sample.component.spec.ts: -------------------------------------------------------------------------------- 1 | import { ComponentFixture, TestBed } from '@angular/core/testing'; 2 | import SampleComponent from './sample.component'; 3 | 4 | describe('SampleComponent', () => { 5 | let component: SampleComponent; 6 | let fixture: ComponentFixture; 7 | 8 | beforeEach(async () => { 9 | await TestBed.configureTestingModule({ 10 | imports: [SampleComponent] 11 | }) 12 | .compileComponents(); 13 | 14 | fixture = TestBed.createComponent(SampleComponent); 15 | component = fixture.componentInstance; 16 | fixture.detectChanges(); 17 | }); 18 | 19 | it('should create', () => { 20 | expect(component).toBeTruthy(); 21 | }); 22 | }); 23 | -------------------------------------------------------------------------------- /src/app/modules/sample-module/components/sample/sample.component.ts: -------------------------------------------------------------------------------- 1 | import { Component, inject } from '@angular/core'; 2 | import { SampleService } from '../../services/sample.service'; 3 | 4 | @Component({ 5 | selector: 'app-sample', 6 | standalone: true, 7 | imports: [], 8 | templateUrl: './sample.component.html', 9 | styleUrl: './sample.component.scss' 10 | }) 11 | export default class SampleComponent { 12 | sampleService: SampleService = inject(SampleService) 13 | 14 | 15 | } 16 | -------------------------------------------------------------------------------- /src/app/modules/sample-module/models/sample-model.model.ts: -------------------------------------------------------------------------------- 1 | export interface ISample { 2 | sample: string, 3 | } -------------------------------------------------------------------------------- /src/app/modules/sample-module/sample.routes.ts: -------------------------------------------------------------------------------- 1 | import { Routes } from "@angular/router"; 2 | 3 | const SAMPLE: Routes = [ 4 | { 5 | path: '', 6 | loadComponent: () => import('./components/sample/sample.component'), 7 | }, 8 | ] 9 | 10 | export default SAMPLE 11 | -------------------------------------------------------------------------------- /src/app/modules/sample-module/services/sample.service.spec.ts: -------------------------------------------------------------------------------- 1 | import { TestBed } from '@angular/core/testing'; 2 | 3 | import { SampleService } from './sample.service'; 4 | 5 | describe('SampleService', () => { 6 | let service: SampleService; 7 | 8 | beforeEach(() => { 9 | TestBed.configureTestingModule({}); 10 | service = TestBed.inject(SampleService); 11 | }); 12 | 13 | it('should be created', () => { 14 | expect(service).toBeTruthy(); 15 | }); 16 | }); 17 | -------------------------------------------------------------------------------- /src/app/modules/sample-module/services/sample.service.ts: -------------------------------------------------------------------------------- 1 | import { Injectable } from '@angular/core'; 2 | 3 | @Injectable({ 4 | providedIn: 'root' 5 | }) 6 | export class SampleService { 7 | 8 | constructor() { } 9 | 10 | sample(): boolean { 11 | return true 12 | } 13 | } 14 | -------------------------------------------------------------------------------- /src/app/shared/services/alert.service.spec.ts: -------------------------------------------------------------------------------- 1 | import { TestBed } from '@angular/core/testing'; 2 | 3 | import { AlertService } from './alert.service'; 4 | 5 | describe('AlertService', () => { 6 | let service: AlertService; 7 | 8 | beforeEach(() => { 9 | TestBed.configureTestingModule({}); 10 | service = TestBed.inject(AlertService); 11 | }); 12 | 13 | it('should be created', () => { 14 | expect(service).toBeTruthy(); 15 | }); 16 | }); 17 | -------------------------------------------------------------------------------- /src/app/shared/services/alert.service.ts: -------------------------------------------------------------------------------- 1 | import { inject, Injectable } from '@angular/core'; 2 | import { ToastrService } from 'ngx-toastr'; 3 | 4 | @Injectable({ 5 | providedIn: 'root' 6 | }) 7 | export class AlertService { 8 | 9 | toastService = inject(ToastrService) 10 | constructor() { } 11 | 12 | failedAlert(text: string = 'Operation Failed') { 13 | this.toastService.error(text, 'failed'); 14 | } 15 | } 16 | -------------------------------------------------------------------------------- /src/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | AngularSampleSmallProject 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | -------------------------------------------------------------------------------- /src/main.ts: -------------------------------------------------------------------------------- 1 | import { bootstrapApplication } from '@angular/platform-browser'; 2 | import { appConfig } from './app/app.config'; 3 | import { AppComponent } from './app/app.component'; 4 | 5 | bootstrapApplication(AppComponent, appConfig) 6 | .catch((err) => console.error(err)); 7 | -------------------------------------------------------------------------------- /src/styles.scss: -------------------------------------------------------------------------------- 1 | /* You can add global styles to this file, and also import other style files */ 2 | -------------------------------------------------------------------------------- /tsconfig.app.json: -------------------------------------------------------------------------------- 1 | /* To learn more about Typescript configuration file: https://www.typescriptlang.org/docs/handbook/tsconfig-json.html. */ 2 | /* To learn more about Angular compiler options: https://angular.dev/reference/configs/angular-compiler-options. */ 3 | { 4 | "extends": "./tsconfig.json", 5 | "compilerOptions": { 6 | "outDir": "./out-tsc/app", 7 | "types": [] 8 | }, 9 | "files": [ 10 | "src/main.ts" 11 | ], 12 | "include": [ 13 | "src/**/*.d.ts" 14 | ] 15 | } 16 | -------------------------------------------------------------------------------- /tsconfig.json: -------------------------------------------------------------------------------- 1 | /* To learn more about Typescript configuration file: https://www.typescriptlang.org/docs/handbook/tsconfig-json.html. */ 2 | /* To learn more about Angular compiler options: https://angular.dev/reference/configs/angular-compiler-options. */ 3 | { 4 | "compileOnSave": false, 5 | "compilerOptions": { 6 | "baseUrl": "src", 7 | "outDir": "./dist/out-tsc", 8 | "strict": true, 9 | "noImplicitOverride": true, 10 | "noPropertyAccessFromIndexSignature": true, 11 | "noImplicitReturns": true, 12 | "noFallthroughCasesInSwitch": true, 13 | "skipLibCheck": true, 14 | "esModuleInterop": true, 15 | "sourceMap": true, 16 | "declaration": false, 17 | "experimentalDecorators": true, 18 | "moduleResolution": "bundler", 19 | "importHelpers": true, 20 | "target": "ES2022", 21 | "module": "ES2022", 22 | "lib": [ 23 | "ES2022", 24 | "dom" 25 | ], 26 | "paths": { 27 | "@shared/*": [ 28 | "app/shared/*" 29 | ], 30 | } 31 | }, 32 | "angularCompilerOptions": { 33 | "enableI18nLegacyMessageIdFormat": false, 34 | "strictInjectionParameters": true, 35 | "strictInputAccessModifiers": true, 36 | "strictTemplates": true 37 | } 38 | } -------------------------------------------------------------------------------- /tsconfig.spec.json: -------------------------------------------------------------------------------- 1 | /* To learn more about Typescript configuration file: https://www.typescriptlang.org/docs/handbook/tsconfig-json.html. */ 2 | /* To learn more about Angular compiler options: https://angular.dev/reference/configs/angular-compiler-options. */ 3 | { 4 | "extends": "./tsconfig.json", 5 | "compilerOptions": { 6 | "outDir": "./out-tsc/spec", 7 | "types": [ 8 | "jasmine" 9 | ] 10 | }, 11 | "include": [ 12 | "src/**/*.spec.ts", 13 | "src/**/*.d.ts" 14 | ] 15 | } 16 | --------------------------------------------------------------------------------