Projectepersonaangular

Tutorial: Crear un Projecte Angular amb la Classe Persona

Introducció

En aquest tutorial veuràs com resoldre l'exercici que hem plantejat dia 28/11/2025 a classe. Bàsicament volíem crear un projecte Angular des de zero que inclou:

  • Una classe Persona amb tres atributs

  • Un formulari per crear persones noves

  • Una llista per mostrar les persones creades

  • Validació de dades (mínimes)

Requisits Previs

Assegura't de tenir instal·lat:

  • Node.js i npm (des de nodejs.org) - Versió 20 o superior recomanada

  • Angular CLI (comanda: npm install -g @angular/cli) - Versió v19+ requerida per a aquest tutorial

Verifica les versions en la terminal:

node --version # Hauria de ser v20+

npm --version # Hauria de ser v10+

ng version # Hauria de ser v19+

Si tens una versió més antiga d'Angular CLI, actualitza-la:

npm install -g @angular/cli@latest

Pas 1: Crear el Projecte Angular

Obri una terminal al directori on vulguis crear el projecte i executa:

ng new gestio-persones

Important: A partir d'Angular v19+, la instrucció ng new ja no te fa les mateixes preguntes interactives que abans. Les configuracions més importants ja venen per defecte:

  • Standalone components actiu (no necessita NgModules)

  • Zoneless change detection actiu (millor rendiment)

  • TypeScript estricte actiu

  • CSS com a format d'estils per defecte

Si vols fer el setup més ràpid sense esperar la instal·lació de paquets, pots usar:

ng new gestio-persones --skip-install

Segon, entra al directori del projecte:

cd gestio-persones npm install

Si has usat --skip-install, executa npm install per descarregar les dependències.

Pas 2: Crear la Classe Persona

Crea una carpeta models dins de src/app (opcional, però és una bona pràctica organitzar el codi):

mkdir src/app/models

Usa la comanda Angular CLI per generar la classe:

ng generate class models/Persona --skip-tests

O amb l'alias curt:

ng g class models/Persona --skip-tests

La CLI crearà l'arxiu src/app/models/persona.ts amb una estructura base. Edita l'arxiu i afegeix els atributs i el constructor:

export class Persona {
    nom : string;
    edat: number;
    email: string;

    constructor(nom: string = '', edat: number = 0, email: string = '') {
        this.nom = nom;
        this.edat = edat;
        this.email = email;
    }
}

Explicació:

  • ng generate class models/Persona → Crea la classe en la carpeta models amb el nom Persona

  • --skip-tests → No crea l'arxiu de tests (.spec.ts), el podem afegir després si necessitem

Atributs:

  • nom: String que emmagatzema el nom de la persona

  • edat: Number que emmagatzema l'edat

  • email: String que emmagatzema l'email de contacte

Constructor: Inicialitza els atributs amb valors per defecte (buids o 0)

Pas 3: Crear el Component Principal

Genera un component que estarà encarregat de gestionar el formulari i la llista:

ng generate component components/gestor-persones

Alternativament, crea manualment els arxius:

  • src/app/components/gestor-persones/gestor-persones.component.ts

  • src/app/components/gestor-persones/gestor-persones.component.html

  • src/app/components/gestor-persones/gestor-persones.component.css

Pas 4: Configurar el Component TypeScript

Edita

src/app/components/gestor-persones/gestor-persones.component.ts;

import { Component } from '@angular/core';
import { CommonModule } from '@angular/common';
import { FormsModule } from '@angular/forms';
import { Persona } from '../../models/persona';

@Component({
    selector: 'app-gestor-persones',
    standalone: true,
    imports: [CommonModule, FormsModule],
    templateUrl: './gestor-persones.component.html',
    styleUrls: ['./gestor-persones.component.css']
})
export class GestorPersonesComponent {
// Array per emmagatzemar les persones
    persones: Persona[] = [];

// Objecte persona buida per al formulari
    novaPersona: Persona = new Persona();

// Mètode per afegir una persona
    agregarPersona() {
// Validació bàsica
        if (this.novaPersona.nom.trim() === '' ||
            this.novaPersona.edat <= 0 ||
            this.novaPersona.email.trim() === '') {
            alert('Si us plau, omple tots els camps correctament');
            return;
        }

// Afegir nova persona al array
        this.persones.push(
            new Persona(
                this.novaPersona.nom,
                this.novaPersona.edat,
                this.novaPersona.email
            )
        );

// Netejar el formulari
        this.novaPersona = new Persona();


    }

// Mètode per eliminar una persona
    eliminarPersona(index: number) {
        this.persones.splice(index, 1);
    }
}

Explicació del codi:

  • persones[]: Array que emmagatzema totes les persones creades

  • novaPersona: Objecte Persona buida que es vincula al formulari

  • agregarPersona(): Valida i afegeix una nova persona

  • eliminarPersona(): Elimina una persona de la llista per índex

Pas 5: Crear la Plantilla HTML

Edita src/app/components/gestor-persones/gestor-persones.component.html

<div class="contenedor">
    <h1>Gestor de Persones</h1>

    *<!-- Formulari -->
    *<div class="formulario">
    <h2>Afegir Nova Persona</h2>
    <form (ngSubmit)="agregarPersona()">
        *<!-- Camp Nom -->
        *<div class="form-group">
        <label for="nom">Nom:</label>
        <input
        type="text"
        id="nom"
        placeholder="Introdueix el nom"
        [(ngModel)]="novaPersona.nom"
        name="nom"
        required
        />
    </div>

        *<!-- Camp Edat -->
        *<div class="form-group">
        <label for="edat">Edat:</label>
        <input
        type="number"
        id="edat"
        placeholder="Introdueix l'edat"
        [(ngModel)]="novaPersona.edat"
        name="edat"
        required
        />
    </div>

        *<!-- Camp Email -->
        *<div class="form-group">
        <label for="email">Email:</label>
        <input
        type="email"
        id="email"
        placeholder="Introdueix l'email"
        [(ngModel)]="novaPersona.email"
        name="email"
        required
        />
    </div>

        *<!-- Botó d'enviament -->
        *<button type="submit" class="btn-submit">Afegir
        Persona</button>
    </form>
</div>

    *<!-- Llista de persones -->
    *<div class="llista" **ngIf*="persones.length > 0">
    <h2>Persones Registrades ({{ persones.length }})</h2>
    <table>
        <thead>
        <tr>
            <th>Nom</th>
            <th>Edat</th>
            <th>Email</th>
            <th>Accions</th>
        </tr>
        </thead>
        <tbody>
        <tr **ngFor*="let persona of persones; let i = index">
            <td>{{ persona.nom }}</td>
            <td>{{ persona.edat }}</td>
            <td>{{ persona.email }}</td>
            <td>
                <button
                class="btn-eliminar"
                (click)="eliminarPersona(i)"
                >
                Eliminar
                </button>
            </td>
        </tr>
        </tbody>
    </table>
</div>

    *<!-- Missatge quan no hi ha persones -->
    *<div class="missatge-buit" **ngIf*="persones.length === 0">
    <p>No hi ha persones registrades. Crea una nova!</p>
</div>
</div>

Explicació dels elements:

  • [(ngModel)]: Two-way data binding que vincula els inputs amb les propietats

  • (ngSubmit)="agregarPersona()": Crida el mètode quan s'envia el formulari

  • *ngFor: Directiva que itera sobre el array de persones

  • {{ variable }}: Interpolació per mostrar dades

  • *ngIf: Mostra o amaga elements segons la condició

Pas 6: Estilos CSS

Edita src/app/components/gestor-persones/gestor-persones.component.css

.contenidor {
    max-width: 800px;
    margin: 30px auto;
    padding: 20px;
    font-family: Arial, sans-serif;
    background-color: #f5f5f5;
    border-radius: 8px;
}
h1 {
    text-align: center;
    color: #333;
    margin-bottom: 30px;
}
h2 {
    color: #555;
    border-bottom: 2px solid #007bff;
    padding-bottom: 10px;
    margin-top: 30px;
}
*/* Estils del formulari */
*.formulari {
    background-color: white;
    padding: 20px;
    border-radius: 8px;
    box-shadow: 0 2px 4px rgba(0, 0, 0, 0.1);
    margin-bottom: 30px;
}
.form-group {
    margin-bottom: 15px;
}
label {
    display: block;
    margin-bottom: 5px;
    font-weight: bold;
    color: #333;
}
input {
    width: 100%;
    padding: 8px 12px;
    border: 1px solid #ddd;
    border-radius: 4px;
    font-size: 14px;
    box-sizing: border-box;
    transition: border-color 0.3s;
}
input:focus {
    outline: none;
    border-color: #007bff;
    box-shadow: 0 0 5px rgba(0, 123, 255, 0.3);
}
.btn-submit {
    width: 100%;
    padding: 10px;
    background-color: #007bff;
    color: white;
    border: none;
    border-radius: 4px;
    font-size: 16px;
    font-weight: bold;
    cursor: pointer;
    transition: background-color 0.3s;
}
.btn-submit:hover {
    background-color: #0056b3;
}
*/* Estils de la taula */
*.llista {
    background-color: white;
    padding: 20px;
    border-radius: 8px;
    box-shadow: 0 2px 4px rgba(0, 0, 0, 0.1);
    overflow-x: auto;
}
table {
    width: 100%;
    border-collapse: collapse;
}
thead {
    background-color: #f0f0f0;
}
th {
    padding: 12px;
    text-align: left;
    font-weight: bold;
    color: #333;
    border-bottom: 2px solid #ddd;
}
td {
    padding: 12px;
    border-bottom: 1px solid #ddd;
    color: #555;
}
tr:hover {
    background-color: #f9f9f9;
}
.btn-eliminar {
    padding: 6px 12px;
    background-color: #dc3545;
    color: white;
    border: none;
    border-radius: 4px;
    cursor: pointer;
    font-size: 14px;
    transition: background-color 0.3s;
}
.btn-eliminar:hover {
    background-color: #c82333;
}
*/* Missatge quan no hi ha dades */
*.missatge-buit {
    text-align: center;
    padding: 30px;
    color: #999;
    font-style: italic;
    background-color: white;
    border-radius: 8px;
}

Pas 7: Actualitzar App Component

Edita src/app/app.component.ts

import {Component} from '@angular/core';
import { GestorPersonesComponent } from './components/gestor-persones/gestor-persones.component';
@Component({
    selector: 'app-root',
    standalone: true,
    imports: [GestorPersonesComponent],
    template: '<app-gestor-persones></app-gestor-persones>'
})
export class AppComponent {
    title = 'gestio-persones';
}

Explicació:

  • standalone: true → El component funciona sense NgModules (estàndard a Angular v19+)

  • imports: [GestorPersonesComponent] → Importa el component de gestió de persones

  • template → Aquí hem posat directament el template en una sola línia

Pas 8: Executar l'Aplicació

A la terminal, dins del directori del projecte, executa:

ng serve

O per obrir automàticament el navegador:

ng serve --open

L'aplicació s'obrirà a http://localhost:4200/

Notes importants per a Angular v21:

  • Els components standalone ja venen configurats per defecte

  • No calen imports de modules (NgModules) addicionals

  • La detecció de canvis és zoneless per defecte (més ràpid)

  • Els imports necessaris (CommonModule, FormsModule) ja estan en el component

Estructura Final del Projecte

gestio-persones/
├── src/
│ ├── app/
│ │ ├── components/
│ │ │ └── gestor-persones/
│ │ │ ├── gestor-persones.component.ts
│ │ │ ├── gestor-persones.component.html
│ │ │ └── gestor-persones.component.css
│ │ ├── models/
│ │ │ └── persona.ts
│ │ ├── app.component.ts
│ │ └── app.config.ts
│ ├── main.ts
│ └── index.html
├── angular.json
├── package.json
└── tsconfig.json

Funcionalitats Implementades

Classe Persona: Amb constructor i tres atributs (nom, edat, email)

Formulari Reactiu: Permite afegir persones noves

Two-way Binding: Els inputs es vinculen automàticament amb l'objecte

Validació: Comprova que els camps no estiguin buits

Llista Dinàmica: Mostra les persones afegides en una taula

Eliminació: Botó per eliminar persones de la llista

Estilos: Interface atractiu i responsiu

Millores Futures

Pots ampliar aquest projecte amb:

  • Validació més avançada (email vàlid, edat positiva)

  • Guardar dades a localStorage o una base de dades

  • Edició de persones existents

  • Busca i filtratge

  • Paginació de la llista

  • Confirmació d'eliminació

  • Importar/Exportar dades (CSV, JSON)

Referències i Recursos