Conoce la importancia de los formularios para tu sitio web

1

Versiones de Angular Forms

2

驴Por qu茅 aprender Angular Forms?

3

Presentaci贸n del proyecto: tour por los formularios de Platzi Store

4

Novedades de Angular 10: c贸mo migrar proyectos de Angular 8 o 9 a la versi贸n 10

Primeros pasos con Angular Forms

5

Template Forms vs. Reactive Forms

6

Dominando el FormControl y sus estados

7

C贸mo usar inputs de texto y la importancia del type

8

Manejo y binding de selects y selects m煤ltiples

9

Manejo y binding de inputs radio y checkbox

10

Aplica validaciones a un FormControl

11

Integraci贸n y validaciones con CSS para mostrar errores

Descubre todas las validaciones de Angular Forms

12

Usando FormGroup para agrupar multiples campos

13

Reactive Forms con FormBuilder

14

Los 11 validadores de Angular (y expresiones regulares)

15

Manejando m煤ltiples FormsGroups

16

Usando componentes de Angular Material

17

Errores comunes de usabilidad en formularios

18

Validaciones personalizadas: mejorando nuestro formulario de registro

Implemeta validaciones avanzadas en PlatziStore

19

C贸mo hacer validaciones grupales en Angular Forms

20

Validaciones condicionadas y reactividad a variaciones en la UI

21

Proyecto: formulario para crear categor铆as de productos

22

Proyecto: conectando nuestro formulario y la API

23

Proyecto: subir im谩genes a Firebase Storage

24

Validaciones asincr贸nicas

25

PatchValue: crear vs. editar

26

Proyecto: creando el m茅todo de editar categor铆as

Construye formularios din谩micos conectando una API

27

Smart vs. dumb components: un patr贸n para dividir responsabilidades

28

Implementando smart y dumb components en PlatziStore

29

Proyecto: mejorando nuestro formulario de productos

30

Select din谩mico: carga opciones desde una API

31

Select din谩mico: trabajando con objetos

32

驴C贸mo crear campos on demand? Forms din谩micos con FormArray

Estrategias avanzadas y optimizaci贸n de formularios

33

Crea tu propia librer铆a de componentes con CVA o Control Value Accesor

34

Crea un buscador de gifs usando la API de Giphy

35

Optimiza un input de b煤squedas con RxJS y debounce

36

Examina la accesibilidad de tus formularios

37

Siguientes pasos en tu carrera de desarrollo web profesional con Angular

You don't have access to this class

Keep learning! Join and start boosting your career

Aprovecha el precio especial y haz tu profesi贸n a prueba de IA

Antes: $249

Currency
$209
Suscr铆bete

Termina en:

0 D铆as
18 Hrs
11 Min
56 Seg

Proyecto: subir im谩genes a Firebase Storage

23/37
Resources

How to upload images to FiberStorage from a form in Angular?

Uploading images to a server using a form may seem like a complex task, but with the right tools, everything becomes simpler. In this section, we will explore how to integrate FiberStorage into an Angular project to upload images efficiently, and how to use reactive forms to manage this functionality.

What is FiberStorage and why use it?

FiberStorage is a service that allows you to store files in the cloud, providing URLs that can be used later in web applications. This service is especially useful for managing images:

  • Ease of use: it easily integrates with Angular projects.
  • Scalability: It allows you to manage large volumes of files without additional complexity.
  • URL security: Provides URLs that ensure controlled access to files.

How to modify the file upload form?

To allow image uploads, we need to modify the HTML form and file management logic in Angular:

  1. Remove unneeded components: since Angular Material does not provide a specific component for the file type, we will use a standard HTML input.
<input type="file" (change)="uploadFile($event)">
  1. Add change events: implement an event to catch when a user selects a file.
uploadFile(event: Event) { const file = (event.target as HTMLInputElement).files[0]; const fileName = 'category.png'; // Consider a random name to avoid conflicts}

How to integrate Angular FiberStorage.

To handle cloud storage, it is necessary to import and configure Angular FiberStorage inside our project:

  1. Import and inject the service:
import { AngularFireStorage } from '@angular/fire/storage';
constructor(private storage: AngularFireStorage) {}
  1. Create reference and upload the file:
const fileRef = this.storage.ref(fileName);const uploadTask = this.storage.upload(fileName, file);
  1. Observe and get the URL of the uploaded file:
uploadTask.snapshotChanges().pipe( finalize(() => { fileRef.getDownloadURL().subscribe(url => { console.log('File available at: ', url);', url); }); }) ).subscribe();

How to display a preview of the uploaded image?

To improve the user experience, it is advisable to provide a preview of the image:

  1. Add preview in the HTML:
<img*ngIf="imagePreview" [src]="imagePreview">
  1. Update the logic to upload and display the image:
uploadFile(event: Event) { const file = (event.target as HTMLInputElement).files[0]; const reader = new FileReader(); reader.onload = () => { this.imagePreview = reader.result as string; }; reader.readAsDataURL(file);}

Challenges to improve the implementation:

  1. Stylize the category listing: make sure images are displayed correctly when editing and deleting categories.

  2. Generate randomized file names: Avoid conflicts by generating a unique, randomized name for each uploaded image.

  3. Improve file upload input styling: Implement a visually appealing design for the file selector with CSS or by using style libraries.

Explore these enhancements to fully master the FiberStorage integration and optimize your forms in Angular. Constant practice will allow you to effectively manage file uploads, vital for modern applications. Keep learning and overcoming challenges!

Contributions 8

Questions 4

Sort by:

Want to see more contributions, questions and answers from the community?

Tercer reto: Mejorar aspecto del input. Bonus: Barra de carga que se va llenando gracias al Observable task.percentageChanges()

**Reto 1 **

<a mat-raised-button color="accent" routerLink="create">Crear categor铆a</a>
<div class="product-grid">
    <div *ngFor="let category of categories">
        <mat-card>
            <mat-card-header>
              <mat-card-title>{{ category.name | uppercase }}</mat-card-title>
            </mat-card-header>
            <div class="crop-image">
              <img [src]="category.image" alt="">
            </div>
            <mat-card-content>
                <p>
                    Lorem ipsum dolor sit amet, 
                    consectetur adipiscing elit. 
                    Nunc convallis eget ante ut imperdiet. 
                    Nunc ipsum lorem, accumsan eu lobortis 
                    ac, luctus at leo. Nullam tortor sapien,
                    mollis quis suscipit nec, tincidunt sed
                    quam. Orci varius natoque penatibus et 
                    magnis dis parturient montes, nascetur
                    ridiculus mus. Mauris id pretium augue. 
                    Integer lacinia mi lorem, a blandit enim 
                    hendrerit vitae. Cras vestibulum diam urna, 
                    fermentum ante elementum sed.
                </p>
              </mat-card-content>
              <mat-card-actions>
                <button mat-raised-button>Editar</button>
                <button mat-raised-button color="warn">Eliminar</button>
              </mat-card-actions>
          </mat-card>
    </div>
</div>
  

Reto 2

import { Component, OnInit } from '@angular/core';
import { Router } from '@angular/router';
import { FormControl, Validators, FormBuilder, FormGroup} from '@angular/forms';
import { finalize } from 'rxjs/operators';

import { CategoriesService } from './../../../../core/services/categories.service';
import { Category } from 'src/app/core/models/category.model';
import { AngularFireStorage } from '@angular/fire/storage';
import { v4 as uuidv4 } from 'uuid';
@Component({
  selector: 'app-category-form',
  templateUrl: './category-form.component.html',
  styleUrls: ['./category-form.component.scss']
})
export class CategoryFormComponent implements OnInit {

  form: FormGroup;

  constructor(
    private formBuilder: FormBuilder,
    private categoriesService: CategoriesService,
    private router: Router,
    private storage: AngularFireStorage
  ) {
    this.buildForm();
   }

  ngOnInit(): void {
  }

  private buildForm() {
    this.form = this.formBuilder.group({
      name: ['', Validators.required],
      image: ['', Validators.required]
    });
  }

  get nameField() {
    return this.form.get('name');
  }

  get imageField() {
    return this.form.get('image');
  }

  save() {
    if (this.form.valid) {
      this.createCategory();
    } else {
      this.form.markAllAsTouched();
    }
  }

  private createCategory() {
    const data = this.form.value;
    this.categoriesService.createCategory(data)
    .subscribe(rta => {
      console.log(rta);
      this.router.navigate(['./admin/categories']);
    });
  }

  uploadFile(event) {
    event.preventDefault();
    const image = event.target.files[0];
    const name = `${uuidv4()}.png`;
    const ref = this.storage.ref(name);
    const task = this.storage.upload(name, image);

    task.snapshotChanges()
    .pipe(
      finalize(() => {
        const urlImage$ = ref.getDownloadURL();
        urlImage$.subscribe(url => {
          console.log(url);
          this.imageField.setValue(url);
        });
      })
    )
    .subscribe();
  }

}

Reto 3

<form [formGroup]="form" (ngSubmit)="save()">
    <mat-card>
        <mat-card-header>
            <mat-card-content>
                <div class="row">
                    <div class="col-xs">
                        <mat-form-field>
                            <mat-label>Nombre</mat-label>
                            <input placeholder="Nombre" formControlName="name" matInput type="text">
                            <div class="messages" *ngIf="nameField.touched && nameField.invalid">
                                <mat-error *ngIf="nameField.hasError('required')">
                                    Este campo es requerido
                                </mat-error>
                            </div>
                        </mat-form-field>
                    </div>
                </div>
                <div class="row">
                    <div class="col-xs">
                        <img *ngIf="imageField.value" [src]="imageField.value" alt=""/>
                        <button (click)="fileInput.click()" mat-mini-fab color="primary">
                            <mat-icon>perm_media</mat-icon>
                        </button>
                        <input #fileInput (change)="uploadFile($event)" placeholder="Image" type="file" style="display: none;">
                        <div class="messages" *ngIf="imageField.touched && imageField.invalid">
                            <mat-error *ngIf="imageField.hasError('required')">
                                Este campo es requerido
                            </mat-error>
                        </div> 
                    </div>
                </div>
            </mat-card-content>
            <mat-card-actions>
                <button mat-raised-button type="submit">Guardar categor铆a</button>
            </mat-card-actions>
        </mat-card-header>
    </mat-card>
</form>

Lo que aprendimos en la clase:

  1. optimizaciones increibles con forms
  2. la palabra randomico

Tercer reto cumplido, me gui茅 del trabajo que hizo el compa帽ero Juan Carlos Pinz贸n, me gust贸 mucho el haber utilizado el mat-progress-bar:

Primer reto:

Segundo reto:

Tercer reto:

Primer reto

Segundo reto

const image = event.target.files[0];
    const name = `${image.name}`;
    const ref = this.storage.ref(name);
    const task = this.storage.upload(name, image);

Tercer reto

HTMl

<button (click)="uploadImage($event)" mat-fab color="primary"><mat-icon>insert_photo</mat-icon></button>
                <input hidden (change)="uploadFile($event)" placeholder="Image" #fileInput type="file" id="file">

TS

uploadImage(event): void {
    event.preventDefault();
    const fileInput = document.getElementById('file');
    fileInput.click();
  }