Compare commits

...

15 Commits

Author SHA1 Message Date
Костя 2b5bee5a49 Merge branch 'master' into TEST-fork 2025-06-25 11:59:30 +03:00
Костя 4e70ada409 test MASTER commit test fork 2025-06-25 11:58:35 +03:00
Костя 0a03162b96 test fork 2025-06-25 11:57:17 +03:00
Костя 80c0236f5e add new value for repair cod /hero-detail.component.ts 2025-06-25 11:46:40 +03:00
Костя b0153ebb86 add Chaining RxJS operators 2025-06-25 10:52:42 +03:00
Костя f6d361eb84 add The searchTerms RxJS subject 2025-06-25 10:45:49 +03:00
Костя ef2309f0f1 add Edit the HeroSearchComponent class 2025-06-25 10:37:00 +03:00
Костя 644139b42c add Create HeroSearchComponent 2025-06-25 10:32:40 +03:00
Костя 64c40998b9 Add search to the dashboard 2025-06-25 10:24:52 +03:00
Костя 5f12d19dbc add Delete a hero 2025-06-24 13:08:02 +03:00
Костя 973524fc7e add Add a new hero 2025-06-24 12:58:13 +03:00
DESKTOP-8HAFCLV\Yugr 8168d2023c Merge branch 'Fixed'
# Conflicts:
#	src/app/app.config.ts
#	src/app/hero-detail/hero-detail.component.html
#	src/app/hero.service.ts
#	src/app/in-memory-data.service.ts
2025-06-24 13:27:23 +04:00
Костя 34ef92e03f analys 2025-06-24 08:45:22 +03:00
Костя 299aeb7d14 add less 6 Get hero by id 2025-06-23 19:55:58 +03:00
Костя 01299fd1e9 add lesson 6 Tap into the Observable 2025-06-23 19:39:15 +03:00
13 changed files with 215 additions and 15 deletions

View File

@ -1,8 +1,8 @@
import { Component } from '@angular/core';
import { MessagesComponent } from "./messages/messages.component";
import { RouterLink, RouterOutlet } from '@angular/router';
@Component({
selector: 'app-root',
templateUrl: './app.component.html',

View File

@ -11,6 +11,6 @@ export const appConfig: ApplicationConfig = {
importProvidersFrom(InMemoryWebApiModule.forRoot(InMemoryDataService, { delay: 150 })),
provideBrowserGlobalErrorListeners(),
provideZonelessChangeDetection(),
provideRouter(routes)
provideRouter(routes),
]
};

View File

@ -5,3 +5,5 @@
{{hero.name}}
</a>
</div>
<app-hero-search></app-hero-search>

View File

@ -3,10 +3,11 @@ import { Component, OnInit } from '@angular/core';
import { Hero } from '../hero';
import { HeroService } from '../hero.service';
import { RouterLink } from '@angular/router';
import { HeroSearchComponent } from "../hero-search/hero-search.component";
@Component({
selector: 'app-dashboard.component',
imports: [CommonModule, RouterLink],
imports: [CommonModule, RouterLink, HeroSearchComponent],
templateUrl: './dashboard.component.html',
styleUrl: './dashboard.component.css'
})
@ -17,6 +18,7 @@ export class DashboardComponent implements OnInit {
ngOnInit(): void {
this.getHeroes();
console.log(this.heroes)
}
getHeroes(): void {

View File

@ -0,0 +1,47 @@
/* HeroSearch private styles */
label {
display: block;
font-weight: bold;
font-size: 1.2rem;
margin-top: 1rem;
margin-bottom: .5rem;
}
input {
padding: .5rem;
width: 100%;
max-width: 600px;
box-sizing: border-box;
display: block;
}
input:focus {
outline: #336699 auto 1px;
}
li {
list-style-type: none;
}
.search-result li a {
border-bottom: 1px solid gray;
border-left: 1px solid gray;
border-right: 1px solid gray;
display: inline-block;
width: 100%;
max-width: 600px;
padding: .5rem;
box-sizing: border-box;
text-decoration: none;
color: black;
}
.search-result li a:hover {
background-color: #435A60;
color: white;
}
ul.search-result {
margin-top: 0;
padding-left: 0;
}

View File

@ -0,0 +1,14 @@
<div id="search-component">
<label for="search-box">Hero Search</label>
<input #searchBox id="search-box" (input)="search(searchBox.value)" />
<ul class="search-result">
<li *ngFor="let hero of heroes$ | async" >
<a routerLink="/detail/{{hero.id}}">
{{hero.name}}
</a>
</li>
</ul>
</div>
<!--a> тест ветки </a-->

View File

@ -0,0 +1,44 @@
//test fork
import { Component, OnInit } from '@angular/core';
import { Observable, Subject } from 'rxjs';
import {
debounceTime, distinctUntilChanged, switchMap
} from 'rxjs/operators';
import { Hero } from '../hero';
import { HeroService } from '../hero.service';
import { CommonModule } from '@angular/common'; //добавил библиотеку
import { RouterLink } from '@angular/router'; //добавил библиотеку
@Component({
selector: 'app-hero-search',
imports: [CommonModule, RouterLink],
templateUrl: './hero-search.component.html',
styleUrls: [ './hero-search.component.css' ]
})
export class HeroSearchComponent implements OnInit {
heroes$!: Observable<Hero[]>;
private searchTerms = new Subject<string>();
constructor(private heroService: HeroService) {}
ngOnInit(): void {
this.heroes$ = this.searchTerms.pipe(
// wait 300ms after each keystroke before considering the term
debounceTime(300),
// ignore new term if same as previous term
distinctUntilChanged(),
// switch to new search observable each time the term changes
switchMap((term: string) => this.heroService.searchHeroes(term)),
);
}
// Push a search term into the observable stream.
search(term: string): void {
this.searchTerms.next(term);
}
}

View File

@ -1,10 +1,9 @@
import { Injectable } from '@angular/core';
import { Hero } from './hero';
import { HEROES } from './mock-heroes';
import { Observable, of } from 'rxjs';
import { MessageService } from './message.service';
import { HttpClient, HttpHeaders } from '@angular/common/http';
import { catchError, map, tap } from 'rxjs/operators';
import { Observable, of } from 'rxjs';
@Injectable({
providedIn: 'root'
@ -49,6 +48,39 @@ export class HeroService {
);
}
/** POST: add a new hero to the server */
addHero(hero: Hero): Observable<Hero> {
return this.http.post<Hero>(this.heroesUrl, hero, this.httpOptions).pipe(
tap((newHero: Hero) => this.log(`added hero w/ id=${newHero.id}`)),
catchError(this.handleError<Hero>('addHero'))
);
}
/** DELETE: delete the hero from the server */
deleteHero(id: number): Observable<Hero> {
const url = `${this.heroesUrl}/${id}`;
return this.http.delete<Hero>(url, this.httpOptions).pipe(
tap(_ => this.log(`deleted hero id=${id}`)),
catchError(this.handleError<Hero>('deleteHero'))
);
}
/* GET heroes whose name contains search term */
searchHeroes(term: string): Observable<Hero[]> {
if (!term.trim()) {
// if not search term, return empty hero array.
return of([]);
}
return this.http.get<Hero[]>(`${this.heroesUrl}/?name=${term}`)
.pipe(
tap(x => x.length ?
this.log(`found heroes matching "${term}"`) :
this.log(`no heroes matching "${term}"`)),
catchError(this.handleError<Hero[]>('searchHeroes', []))
);
}
/**
* Handle Http operation that failed.
* Let the app continue.
@ -74,6 +106,5 @@ export class HeroService {
private log(message: string) {
this.messageService.add(`HeroService: ${message}`);
}
}

View File

@ -5,6 +5,15 @@
padding: 0;
width: 15em;
}
input {
display: block;
width: 100%;
padding: .5rem;
margin: 1rem 0;
box-sizing: border-box;
}
.heroes li {
position: relative;
cursor: pointer;
@ -52,3 +61,30 @@
margin-right: .8em;
border-radius: 4px 0 0 4px;
}
.add-button {
padding: .5rem 1.5rem;
font-size: 1rem;
margin-bottom: 2rem;
}
.add-button:hover {
color: white;
background-color: #42545C;
}
button.delete {
position: absolute;
left: 210px;
top: 5px;
background-color: white;
color: #525252;
font-size: 1.1rem;
margin: 0;
padding: 1px 10px 3px 10px;
}
button.delete:hover {
background-color: #525252;
color: white;
}

View File

@ -4,5 +4,17 @@
<a routerLink="/detail/{{hero.id}}">
<span class="badge">{{hero.id}}</span> {{hero.name}}
</a>
<button type="button" class="delete" title="delete hero"
(click)="delete(hero)">x</button>
</li>
</ul>
<div>
<label for="new-hero">Hero name: </label>
<input id="new-hero" #heroName />
<!-- (click) passes input value to add() and then clears the input -->
<button type="button" class="add-button" (click)="add(heroName.value); heroName.value=''">
Add hero
</button>
</div>

View File

@ -3,7 +3,6 @@ import { Hero } from '../hero';
import { CommonModule } from '@angular/common';
import { FormsModule } from '@angular/forms';
import { HeroService } from '../hero.service'; //новая библиотека добавлена вместо HEROES
import { HeroDetailComponent } from '../hero-detail/hero-detail.component';
import { MessageService } from '../message.service';
import { RouterLink } from '@angular/router';
@ -26,10 +25,23 @@ export class HeroesComponent implements OnInit {
this.getHeroes();
}
getHeroes(): void {
this.heroService.getHeroes()
.subscribe(heroes => this.heroes = heroes);
}
add(name: string): void {
name = name.trim();
if (!name) { return; }
this.heroService.addHero({ name } as Hero)
.subscribe(hero => {
this.heroes.push(hero);
});
}
delete(hero: Hero): void {
this.heroes = this.heroes.filter(h => h !== hero);
this.heroService.deleteHero(hero.id).subscribe();
}
}