I am doing a project related to API and I am using Angular, Angular Material, Typescrit and RXJS, the error is when trying to highlight a search bar, in this fragment of html code I get the error seen in the image
this is the complete html5
div id="pagina">
<br>
<br>
<video src="../../../../assets/videos/background-video.mp4" autoplay loop muted type="video/mp4"></video>
<div id="titulo">
<h1>LOS CAMPEONES</h1>
<br>
<h2>Conoce a los campeones de las distintas regiones de Runeterra.</h2>
<blockquote>¡Haz click en el botón saber más para descubrir más detalles o busca a tu campeón favorito!</blockquote>
</div>
<div id="separador">
<img src="../../../../assets/images/decorator-hr-lg.png" alt="decorator-hr">
</div>
<div id="busqueda">
<mat-form-field class="buscar">
<input class="campo" type="text" matInput placeholder="Buscar un campeón" aria-label="Buscar un campeón"
(keyup)="searchChampion.next($event.target?.value)">
<!--cada vez que se presione una teclla(on key up s) se envia/emite ael valor de esa letra presionada
($even.target.value)y $event es para manejar eventos (con esto manejo onkeyup), atarget es
la propiedad de event (equivale ha hacer un document.getElement , document.querySelector,
es el DOM de angular , mas bien es el elemnto que disparo ese evento (la tecla pulsada valla)
avalue es el valor del target p es p r es r lol es lol)
modo resumido cada vez que el usuario presiona una tecla y levanta el dedo(keyup) se searchCampion
lo emite(next), es decir se emite el valor de la tecla que el usuario pulse
funciona gracias a rxjs principalmente-->
<button mat-button matSuffix>
<mat-icon>search</mat-icon>
</button>
</mat-form-field>
</div>
<div id="container">
<ng-template ngIf="isLoad">
<div class="cartas" *ngFor="let champion of champions ">
<mat-card>
<mat-card-header id="campeones">
<img mat-card-image [alt]="champion.name" [src]="'../../../../assets/img/icons/'+champion.name+'.jpeg'">
</mat-card-header>
<mat-card-content>
<mat-card-title id="nombre"><h3>{{champion.name}}</h3></mat-card-title>
</mat-card-content>
</mat-card>
</div>
</ng-template>
</div>
and this is the typescript
import { Component } from '@angular/core';
import { LolService } from '../../services/lol.service';
import {Datum } from '../../interfaces/champions.interface';
import { Subject } from 'rxjs';
@Component({
selector: 'card-component',
templateUrl: './card-component.component.html',
styleUrl: './card-component.component.scss'
})
export class CardComponent{
isLoad=false;
searchChampion=new Subject<string>();//esto servira para manejar los eventos del buscador a apartir de obserables
champions:Datum[]=[];
championsFilter:Datum[]=[];//esto lo usare para filtar campeones en la barra de busqueda
constructor(private lolService:LolService ){
this.obtenerInfo();
}
searchChampions():void{//estafuncion es para buscar por nombre
this.searchChampion.subscribe(key =>{//el subject search champion se suscribe a cada observable que emite en cardcomponent html
this.championsFilter = this.champions.filter(champ => champ.name.toLowerCase().includes(key.toLowerCase()));
//despues lo va filtrandon y guardando en un arreglo de objetos
//de cada campeon (cada objeto del array ) coje el nombre(la propiedad name de cada objeto) la vuelve minuscula(uso la funcion toLoweCase para poner el nombre de cada la propiedad name de cada objeto champion del arreglo champions en miniscula )
//despues uso include para combaprobar si el nombre recibido(el string key convertido en minusculas) es gual al nombre del campeon actual(a la propiedad name del objeto actual champ)
})
}
obtenerInfo(){
this.lolService.obtenerChampInfo()
.subscribe( champion=>{
console.log(Object.values(champion.data))//
this.champions=Object.values(champion.data);
console.log(this.champions)
this.isLoad=true
// for (let champion of this.champions){ //para que no se me pete la memoria con las descargas al hacer un cambio u otro
// let url='https://gameriv.com/wp-content/uploads/2023/08/'+champion.name+'-Icon.jpeg'
// let nombreImagen:string=champion.name+'.jpeg';
// this.lolService.descargarImg(url,nombreImagen)
// console.log('imagen descargada')
// }
})
}
}
How i can fix the error?
I put it optional because first it told me that it could be null
For this particular scenario, it's best you wrap $any()
. This is the HTML equivalent of setting as any
type, the event (TypeDefinition) does not have value
we know it has a value (actual object).
<input class="campo" type="text" placeholder="Buscar un campeón" aria-label="Buscar un campeón"
(keyup)="searchChampion.next($any($event.target).value)">
An alternative will be to just define a method, which will wrap the target and perform the same action.
Here I use TypeScript intersection operator &
to define the type as EventTarget
and also has a value
property of any
type and assigned it to a type Target
. We can use this to get rid of the error:
import { Component } from '@angular/core';
import { bootstrapApplication } from '@angular/platform-browser';
import { Subject } from 'rxjs';
import 'zone.js';
export type Target = EventTarget & { value: string };
@Component({
selector: 'app-root',
standalone: true,
template: `
<input class="campo" type="text" placeholder="Buscar un campeón" aria-label="Buscar un campeón"
(keyup)="searchChampionEvent($event)">
`,
})
export class App {
name = 'Angular';
searchChampion = new Subject<string>();
searchChampionEvent(event: Event) {
const stringValue = (event.target as Target)?.value ?? '';
this.searchChampion.next(stringValue);
}
}
bootstrapApplication(App);