Diskussionsthread zur Schulung #1
Replies: 28 comments 3 replies
-
<div class="container">
<h1>
<img
width="100"
alt="Angular Logo"
src="data:image/png;base64,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"
/>
{{ title }}
</h1>
<!-- <router-outlet></router-outlet> -->
</div> |
Beta Was this translation helpful? Give feedback.
-
npm install --location=global @angular/cli@latest ng version
|
Beta Was this translation helpful? Give feedback.
-
|
Beta Was this translation helpful? Give feedback.
-
|
Beta Was this translation helpful? Give feedback.
-
Beta Was this translation helpful? Give feedback.
-
"lokale AI" mit Ollama und VSCode-Extension
|
Beta Was this translation helpful? Give feedback.
-
Hausaufgaben
|
Beta Was this translation helpful? Give feedback.
-
<div class="card mb-4">
<div class="card-body bg-light">
<img class="img-thumbnail float-end" alt=""
src="https://api.angular.schule/avatar/{{ book().rating }}">
<div class="card-title">
<h2>
{{ book().title }}
<span class="badge bg-secondary">{{ book().rating }}</span>
</h2>
</div>
<p>{{ book().description }}</p>
</div>
</div> |
Beta Was this translation helpful? Give feedback.
-
![]() |
Beta Was this translation helpful? Give feedback.
-
describe('In der Mathematik', () => {
let summand: number;
beforeEach(() => {
// Arrange
summand = 1;
});
it('soll 1 + 1 immer 2', () => {
// Act
const result = summand + 1;
// Assert
expect(result).toBe(2)
});
}); |
Beta Was this translation helpful? Give feedback.
-
|
Beta Was this translation helpful? Give feedback.
-
Doch wieder "Service" ^^
|
Beta Was this translation helpful? Give feedback.
-
Test import { Book } from './book';
import { BookRatingService } from './book-rating.service';
fdescribe('BookRatingService', () => {
let service: BookRatingService;
let book: Book;
beforeEach(() => {
service = new BookRatingService();
book = {
isbn: 'test',
title: 'Test',
description: 'Test',
rating: 3
};
});
it('should rate up a book by one', () => {
const ratedBook = service.rateUp(book);
expect(ratedBook.rating).toBe(4);
});
it('should rate down a book by one', () => {
const ratedBook = service.rateDown(book);
expect(ratedBook.rating).toBe(2);
});
it('should not be allowed to have a rating greater than 5', () => {
book.rating = 5;
const ratedBook = service.rateUp(book);
expect(ratedBook.rating).toBe(5);
});
it('should not be allowed to have a rating smaller than 1', () => {
book.rating = 1;
const ratedBook = service.rateDown(book);
expect(ratedBook.rating).toBe(1);
});
it('should not mutate the book', () => {
const frozenBook = Object.freeze(book);
expect(() => service.rateUp(frozenBook)).not.toThrow();
expect(() => service.rateDown(frozenBook)).not.toThrow();
});
}); Service: import { Injectable } from '@angular/core';
import { Book } from './book';
@Injectable({
providedIn: 'root'
})
export class BookRatingService {
rateUp(book: Book): Book {
return book; // TODO: implementation
}
rateDown(book: Book): Book {
return book; // TODO: implementation
}
} |
Beta Was this translation helpful? Give feedback.
-
Hausaufgabea) Teste die Oberfläche mit einem e2e Tool ( ODER b) Teste einen weitere Aspekt der Software (mit einem LLM). |
Beta Was this translation helpful? Give feedback.
-
https://refactoring.guru/design-patterns
|
Beta Was this translation helpful? Give feedback.
-
Hands on!Durch die Logik im Template der Option:
|
Beta Was this translation helpful? Give feedback.
-
<form>
<div class="form-group">
<label for="isbn">ISBN</label>
<input type="text" class="form-control" id="isbn">
@if (false) {
<div class="feedback-error">The ISBN is not valid!</div>
}
</div>
<div class="form-group">
<label for="title">Title</label>
<input type="text" class="form-control" id="title">
</div>
<div class="form-group">
<label for="description">Description</label>
<textarea class="form-control" id="description"></textarea>
</div>
<button
type="submit" class="btn btn-primary mb-4">Create</button>
</form> |
Beta Was this translation helpful? Give feedback.
-
🎮 NEU: RxJS PlaygroundDu kannst dir entweder
cd rxjs-playground
npm install
ng serve Öffne den Browser unter der URL http://localhost:4300 (!), um die Anwendung zu sehen. |
Beta Was this translation helpful? Give feedback.
-
|
Beta Was this translation helpful? Give feedback.
-
Miss the old angular.io/resources? We brought it back!The old list of valuable resources from angular.io is gone. Here you can find a mirror. |
Beta Was this translation helpful? Give feedback.
-
Generating Angular API clients with OpenAPI GeneratorIn this article, we'll show how to use OpenAPI Generator to automatically generate Angular HTTP services from your OpenAPI spec. https://angular.schule/blog/2025-06-openapi-generator Beispiel im Übungsprojekt: https://github.com/angular-schule/2025-06-angular-workshop-muenchen/tree/openapi-generator-playground |
Beta Was this translation helpful? Give feedback.
-
LLM prompts and AI IDE setuphttps://angular.dev/ai/develop-with-ai Best Pratices: https://angular.dev/context/best-practices.md |
Beta Was this translation helpful? Give feedback.
-
Hausaufgabe: Typeahead-SucheImplementiere eine Typeahead-Suche. Nutze als Basis dafür den Datenstrom
|
Beta Was this translation helpful? Give feedback.
-
Mein @service()-Decorator für AngularAls Antwort auf eure Frage. Ja, es geht! :-D https://github.com/angular-buch/website-articles/pull/38/files |
Beta Was this translation helpful? Give feedback.
-
import {Component, inject} from '@angular/core';
import {FormControl, FormGroup, ReactiveFormsModule} from "@angular/forms";
import {BookStore} from '../shared/book-store';
import {toSignal} from '@angular/core/rxjs-interop';
import {debounceTime, filter, switchMap} from 'rxjs';
@Component({
selector: 'app-book-search',
imports: [
ReactiveFormsModule
],
templateUrl: './book-search.html',
styleUrl: './book-search.scss'
})
export class BookSearch {
bs = inject(BookStore);
searchForm = new FormGroup({
search: new FormControl('')
});
typeAhead = toSignal(this.searchForm.controls.search.valueChanges.pipe(
debounceTime(400),
filter(t => t !== null),
filter(t => t.length >= 3),
switchMap(t => this.bs.search(t))
));
} @let d = searchForm.controls;
<h3>Suche nach Büchern</h3>
<form [formGroup]="searchForm">
<div class="form-group">
<label for="search">Filter-Zeichenkette</label>
<input [formControl]="d.search" class="form-control" id="search">
</div>
</form>
<h3>Suchergebnisse</h3>
<ul>
@for (x of typeAhead(); track $index) {
<li>
{{ x.title }}
</li>
}
</ul> Beispiellösung aus dem Kurs |
Beta Was this translation helpful? Give feedback.
-
import { JsonPipe } from '@angular/common';
import { HttpErrorResponse } from '@angular/common/http';
import { Component, inject } from '@angular/core';
import { toSignal } from '@angular/core/rxjs-interop';
import { ActivatedRoute, RouterLink } from '@angular/router';
import { catchError, map, of, switchMap } from 'rxjs';
import { BookStore } from '../shared/book-store';
@Component({
selector: 'app-book-details-page',
imports: [JsonPipe, RouterLink],
templateUrl: './book-details-page.html',
styleUrl: './book-details-page.scss'
})
export class BookDetailsPage {
bs = inject(BookStore);
router = inject(ActivatedRoute);
book = toSignal(this.router.paramMap.pipe(
map(x => x.get('isbn') || ''),
switchMap(isbn => this.bs.getSingle(isbn).pipe(
catchError((err: HttpErrorResponse) => of({
title: 'Fehler',
description: err.message
}))
))
));
// withComponentInputBinding() in app.config.ts
// isbn = input.required();
// logEffect = effect(() => console.log('Die ISBN lautet', this.isbn()));
} <pre>
{{ book() | json }}
</pre>
<a routerLink="/books/9783864909467">Gehe zu Angular</a><br>
<a routerLink="/books/9783864905520">Gehe zu React</a><br>
<a routerLink="/books/404">Gehe zu Fehler</a><br> |
Beta Was this translation helpful? Give feedback.
-
i18n von AngularPer Translocohttps://github.com/ngneat/transloco ngx-translate |
Beta Was this translation helpful? Give feedback.
-
Achtung, ngrx/platform#4787 (PSA: Angular v20 and NgRx v20)
Bei der Anwendung NgRx einrichten npm install @ngrx/store@latest --save --legacy-peer-deps
npm install @ngrx/schematics@latest --save --legacy-peer-deps
npm install @ngrx/effects@latest --save --legacy-peer-deps
npm install @ngrx/store-devtools@latest --save --legacy-peer-deps Und in der "cli": {
"schematicCollections": [
"@schematics/angular",
"@ngrx/schematics"
]
} danach: ng g feature books/store/book --entity=false --api --defaults folgende Anpassungen in der import { ApplicationConfig, provideBrowserGlobalErrorListeners, provideZonelessChangeDetection, isDevMode } from '@angular/core';
import { provideRouter, withComponentInputBinding } from '@angular/router';
import { routes } from './app.routes';
import { provideHttpClient } from '@angular/common/http';
import { provideEffects } from '@ngrx/effects';
import { provideStoreDevtools } from '@ngrx/store-devtools';
import { bookFeature } from './books/store/book.reducer';
import { BookEffects } from './books/store/book.effects';
import { provideState, provideStore } from '@ngrx/store';
export const appConfig: ApplicationConfig = {
providers: [
provideBrowserGlobalErrorListeners(),
provideZonelessChangeDetection(),
provideRouter(routes,
/* withDebugTracing() */
/* withInMemoryScrolling({ scrollPositionRestoration: 'top'}) */
withComponentInputBinding()),
provideHttpClient(),
// NgRx Neu Einfügen:
provideStore(),
provideEffects(),
provideStoreDevtools({ maxAge: 25, logOnly: !isDevMode() }),
provideState(bookFeature),
provideEffects(BookEffects)
]
}; |
Beta Was this translation helpful? Give feedback.
Uh oh!
There was an error while loading. Please reload this page.
-
Herzlich Willkommen! 🎉 Hier können wir während der Schulung Links und Codeschnipsel teilen.
Beta Was this translation helpful? Give feedback.
All reactions