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

Convierte tus certificados en títulos universitarios en USA

Antes: $249

Currency
$209

Paga en 4 cuotas sin intereses

Paga en 4 cuotas sin intereses
Suscríbete

Termina en:

19 Días
6 Hrs
45 Min
41 Seg

Proyecto: mejorando nuestro formulario de productos

29/37
Recursos

Aportes 10

Preguntas 0

Ordenar por:

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

muchas gracias por el video, los mensajes de errores siempre han sido una agonía para mí, y en literal 5 segundos me han quedado claro!

Febrero 10 de 2023 el api no funciona

18 de Septiembre del 2022 las endpoints no funcionan

febrero 24, 2022 las endpoints no funcionan.

Saludos.

No funciona:

https://store.nicobytes.site/api

Enero 27 - 2023 la API sigue sin funcionar…

El api ahora te pide que la imagen sea un array asi que lo solucione asi: primero en el formGroup ponerlo como nulo, images: [null, [Validators.required]], en el input html poner el atributo multiple y luego en el metodo uploadFile modificar el codigo del task por esto task
.snapshotChanges()
.pipe(
finalize(() => {
this.image$ = fileRef.getDownloadURL();
this.image$.subscribe((url) => {
const currentValue = this.form.get(‘images’).value || [];
const newValue = […currentValue, url];
this.form.patchValue({ images: newValue });
});
})
)
.subscribe();

Si estas viendo el video en 2023 recuerda usar la nueva version de la API:

https://api.escuelajs.co/api/v1

. Para esta clase es necesario en el HTML de products modificar los siguientes datos:
.
anterior -> nuevo

{{product._id}}  -> {{product.id}}, 
{{product.name}}  -> {{product.title}}, 
[routerLink]="['edit', product._id] -> [routerLink]="['edit', product.id]

Logre seguir la clase pero haciendo unas modificaciones por lo que cambio la API, comparto resultado y el codigo

codigo .html

<form [formGroup]="form" (ngSubmit)="saveProduct($event)">
  <mat-card>
    <mat-card-header>
      <mat-card-title>Producto</mat-card-title>
    </mat-card-header>
    <mat-card-content>
      <div class="row">
        <div class="col-xs">
          <mat-form-field>
            <input placeholder="Title" formControlName="title" matInput type="text">
            <div class="messages" *ngIf="titleField.touched && titleField.invalid">
              <mat-error *ngIf="titleField.hasError('required')">Este campo es rerquerido</mat-error>
              <mat-error *ngIf="titleField.hasError('minlength')">Debe tener mas de 4 caracteres</mat-error>
            </div>
          </mat-form-field>
        </div>
      </div>
      <div class="row">
        <div class="col-xs">
          <mat-form-field>
            <input placeholder="Price" formControlName="price" matInput type="number">
          </mat-form-field>
          <div class="messages" *ngIf="priceField.errors && priceField.dirty">
            <mat-error *ngIf="priceField.hasError('price_invalid')">No te debes pasar de 10000</mat-error>
            <mat-error *ngIf="priceField.hasError('required')">El campo es requerido</mat-error>
          </div>
        </div>
      </div>
      <div class="row">
        <div class="col-xs">
          <mat-form-field>
            <textarea placeholder="Text" formControlName="description" matInput></textarea>
          </mat-form-field>
        </div>
      </div>
      <div class="row">
        <div class="col-xs">
          <div *ngFor="let imageField of imagesField.value">
            <img *ngIf="imageField" [src]="imageField" style="width: 200px;">
          </div>
          <input type="file" (change)="uploadFile($event)" multiple="multiple">
        </div>
      </div>
      <div class="row">
        <div class="col-xs">
          <mat-form-field>
            <input placeholder="Category" formControlName="categoryId" type="number" matInput/>
          </mat-form-field>
        </div>
      </div>
    </mat-card-content>
    <mat-card-actions>
      <button [disabled]="form.invalid" mat-raised-button type="submit">Guardar</button>
    </mat-card-actions>
  </mat-card>
  
</form>

Codigo .ts

import { Component, OnInit } from '@angular/core';
import { FormBuilder, FormGroup, Validators } from '@angular/forms';
import { Router } from '@angular/router';
import { AngularFireStorage } from '@angular/fire/storage';

import { finalize } from 'rxjs/operators';

import { MyValidators } from './../../../../utils/validators';
import { ProductsService } from './../../../../core/services/products/products.service';
import { FileModel } from './../../../../core/models/file.model'
import { Observable } from 'rxjs';

@Component({
  selector: 'app-product-create',
  templateUrl: './product-create.component.html',
  styleUrls: ['./product-create.component.scss']
})
export class ProductCreateComponent implements OnInit {

  form: FormGroup;
  image$: Observable<any>;

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

  ngOnInit() {
  }

  saveProduct(event: Event) {
    event.preventDefault();
    if (this.form.valid) {
      const product = this.form.value;
      this.productsService.createProduct(product)
      .subscribe((newProduct) => {
        this.router.navigate(['./admin/products']);
      });
    }
  }

  uploadFile(event) {
    const files = [...event.target.files] as FileModel[];
    files.forEach(item => {
      const name = `${item.name}`;
      const fileRef = this.storage.ref(name);
      const task = this.storage.upload(name, item);
      task.snapshotChanges()
      .pipe(
        finalize(() => {
          this.image$ = fileRef.getDownloadURL();
          this.image$.subscribe(url => {
            const fileList = this.imagesField.value as string[]
            this.imagesField.setValue([...fileList, url ])
          });
        })
      )
      .subscribe();
    })

    if (files) {
      this.imagesField.setValue([] as string[])
    }

  }

  private buildForm() {
    this.form = this.formBuilder.group({
      title: ['', [Validators.required, Validators.minLength(4)]],
      price: ['', [Validators.required, MyValidators.isPriceValid]],
      images: [Array<string>(), Validators.required],
      categoryId: ['', Validators.required],
      description: ['', [Validators.required, Validators.minLength(10)]],
    });
  }
  
  get titleField() {
    return this.form.get('title')
  }
  get priceField() {
    return this.form.get('price');
  }
  get imagesField() {
    return this.form.get('images');
  }
  get descriptionField() {
    return this.form.get('description');
  }

}

Utilizando la nueva API (https://api.escuelajs.co/api/v1) me muesta los siguiente mensajes