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

No tienes acceso a esta clase

¡Continúa aprendiendo! Únete y comienza a potenciar tu carrera

No se trata de lo que quieres comprar, sino de quién quieres ser. Aprovecha el precio especial.

Antes: $249

Currency
$209

Paga en 4 cuotas sin intereses

Paga en 4 cuotas sin intereses
Suscríbete

Termina en:

13 Días
20 Hrs
54 Min
5 Seg

Proyecto: subir imágenes a Firebase Storage

23/37
Recursos

Aportes 9

Preguntas 4

Ordenar por:

¿Quieres ver más aportes, preguntas y respuestas de la comunidad?

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>

En la actualidad tuve que modificar la forma en que se suben los archivos, porque de la manera que la explican ya no me funciono:
Aqui está el código.

import { Storage, ref, uploadBytes, listAll, getDownloadURL, StorageReference } from '@angular/fire/storage';


  constructor(
    private storage: Storage
  ) {  }
  
uploadFile(event: any) {
    const image = event.target.files[0];
    const name = image.name;

    const imgRef = ref(this.storage,`imagenes/${name}`);
    const task = uploadBytes(imgRef,image);

    task
      .then(response => {
        console.log(response);
        this.getImage(name)
      })
      .catch(error => console.log(error))
  }

  getImage(nameImage:string) {
    const imgRef = ref(this.storage, 'imagenes')
    listAll(imgRef)
      .then( async rta => {

        const itemActual: StorageReference|undefined = rta.items.find(item => item.name === nameImage);

        if(itemActual){
          const url = await getDownloadURL(itemActual)
          this.imageField?.setValue(url);
          console.log(url);
        }

      })
  }

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();
  }