Contenido del curso
Maquetando con Tailwind
Componentes interactivos con Angular CDK
Drag and drop
Modales y listas
Table CDK
Próximos pasos para completar el Clon de Trello
Listas con scroll
Contenido del curso
Listas con scroll
Carlos Mario Ortiz Moreno
studentJosé Nicolás Aristizabal Ramírez
studentMATEO FLOREZ ARROYO
studentBrenda Sutara
studentMax Andy Diaz Neyra
studentReinaldo Mendoza
studentJorge Morales
studentPara los que estan en angular 18 y HttpClientModule ya esta en desuso para hacer la peticion http tienen que ir a app.config.ts y poner el providers provideHttpClient de la siguiente manera :
import { ApplicationConfig, provideZoneChangeDetection } from '@angular/core';import { provideRouter } from '@angular/router'; import { routes } from './app.routes';import { provideHttpClient } from '@angular/common/http'; export const appConfig: ApplicationConfig = { providers: [provideZoneChangeDetection({ eventCoalescing: true }), provideRouter(routes), provideHttpClient()]};
y listo, desde el componente ya se puede hacer peticiones http.
Como buena práctica es recomendable separar las funcionalidades segú el uso, para el caso de las peticiones http deberiamos crear un servicio con ng y para el caso de las interfaces deberiamos incluirlas dentro de nuestra carpeta models.
<div class="flex flex-col h-screen"> <app-navbar></app-navbar> <div class="w-full grow bg-sky-600 p-6"> <div class="flex gap-4"> <div class="w-1/2"> <h1 class="text-white">List A (Normal scroll)</h2> <div class="h-64 w-full border overflow-y-scroll bg-white rounded mt-2"> <div class="flex items-center space-x-4" *ngFor="let product of products"> <img class="w-10 h-10 rounded-full" [src]="product.images[0]" alt=""> <div class="space-y-1 font-medium dark:text-white"> <div>{{ product.title }}</div> <div class="text-sm text-gray-500 dark:text-gray-400">${{product.price}}</div> </div> </div> </div> </div> <div class="w-1/2"> <h1 class="text-white">List B (Virtual scroll)</h2> </div> </div> </div> </div>
En la nueva versión de angular no tenemos el archivo app.module.ts Directamente lo incorporamos en el .ts del componente o la página que creamos. Dejo mi código a continuación, también cambió la forma de escribir los *ngFor pero se puede utilizar la antigua, eso no afecta en nada
archivo scroll.component.ts
import { Component } from '@angular/core'; import {ScrollingModule} from '@angular/cdk/scrolling'; import { CommonModule } from '@angular/common'; import { NavbarComponent } from '../../components/navbar/navbar.component'; import { HttpClient, HttpClientModule } from '@angular/common/http'; interface Product { id: string; title: string; price: string; images: string[]; } @Component({ selector: 'app-scroll', standalone: true, imports: [CommonModule, ScrollingModule, NavbarComponent, HttpClientModule], templateUrl: './scroll.component.html' }) export class ScrollComponent { products: Product[] = []; constructor( private http: HttpClient ) { } ngOnInit(): void { this.http.get<Product[]>('https://api.escuelajs.co/api/v1/products') .subscribe(data => { this.products = data; }) } }
archivo scroll.component.html
<div class="felx flex-col h-screen"> <app-navbar></app-navbar> <div class="w-full grow bg-sky-600 p-6 h-full"> <div class="flex gap-4"> <div class="w-1/2"> <div class="text-white"> <h2>List A (Normal scroll)</h2> <div class="h-64 w-full border overflow-y-scroll bg-white rounded-lg mt-2"> @for (product of products; track product.id) { <div class="flex items-center gap-4" > <img class="w-10 h-10 rounded-full" [src]="product.images[0]" alt=""> <div class="font-medium dark:text-white"> <div>{{ product.title }}</div> <div class="text-sm text-gray-500 dark:text-gray-400">{{ product.price }}</div> </div> </div> } </div> </div> </div> <div class="w-1/2"> <div class="text-white"> <h2>List B (Virtual scroll)</h2> </div> </div> </div> </div> </div>
Excelente aporte dejo mi codigo version Angular 19: archivo scroll.component.ts
import { Component, inject } from '@angular/core'; import { rxResource } from '@angular/core/rxjs-interop'; import { NavbarComponent } from '../../components/navbar/navbar.component'; import { ProductService } from '../../services/product.service'; @Component({ selector: 'app-scroll', imports: [NavbarComponent], templateUrl: './scroll.component.html', }) export class ScrollComponent { private productService = inject(ProductService); products = rxResource({ loader: () => this.productService.getProducts(), }); }
archivo scroll.component.html
<div class="flex flex-col h-screen"> <app-navbar></app-navbar> <div class="w-full grow bg-sky-600 p-6 h-full"> <div class="flex gap-4"> <div class="w-1/2"> <div class="text-white"> <h3>List A (Normal scroll)</h3> <div class="h-64 w-full border overflow-y-auto bg-white rounded mt-2"> @for (product of products.value(); track product.id) { <div class="flex items-center gap-4"> <img class="w-10 h-10 rounded-full" [src]="product.images[0]" alt="" /> <div class="font-medium dark:text-white"> <div class="text-black">{{ product.title }}</div> <div class="text-sm text-gray-500 dark:text-gray-400"> {{ product.price }} </div> </div> </div> } </div> </div> </div> <div class="w-1/2"> <div class="text-white"> <h3>List B (Virtual scroll)</h3> </div> </div> </div> </div> </div>
servicio:
import { HttpClient } from '@angular/common/http'; import { inject, Injectable } from '@angular/core'; interface Product { id: string; title: string; price: string; images: string[]; } @Injectable({ providedIn: 'root', }) export class ProductService { private http = inject(HttpClient); getProducts() { return this.http.get<Product[]>('https://api.escuelajs.co/api/v1/products'); } }
Llegamos al punto dulce del curso
scroll.component.ts
import { Component, inject, signal } from '@angular/core'; import { NavbarComponent } from '../../components/navbar/navbar.component'; import { CommonModule } from '@angular/common'; import { ProductService } from '../../services/product.service'; interface Product { id: string; title: string; price: string; images: string[]; } @Component({ selector: 'app-scroll', standalone: true, imports: [CommonModule, NavbarComponent], templateUrl: './scroll.component.html', }) export class ScrollComponent { products: Product[] = []; private productService = inject(ProductService); constructor() {} ngOnInit() { this.getProducts(); } private getProducts(): void { this.productService.getProducts().subscribe((data) => { this.products = data; }); } } ```**product.service.ts** ```js import { HttpClient } from '@angular/common/http'; import { Injectable, inject } from '@angular/core'; interface Product { id: string; title: string; price: string; images: string[]; } @Injectable({ providedIn: 'root', }) export class ProductService { private http = inject(HttpClient); constructor() {} getProducts() { const url = new URL(`https://api.escuelajs.co/api/v1/products`); return this.http.get<Product[]>(url.toString()); } }