No tienes acceso a esta clase

¬°Contin√ļa aprendiendo! √önete y comienza a potenciar tu carrera

Creando funcionalidad de eliminar usando JavaScript

17/19
Recursos

Aportes 8

Preguntas 4

Ordenar por:

¬ŅQuieres ver m√°s aportes, preguntas y respuestas de la comunidad?

Reto de editar producto

Agrego un botón para editar producto en Products.razor

<div class="card">
                <img class="card-img-top" src="@product.Images[0]" alt="@product.Title" loading="lazy" width="270" height="210"/>
                <div class="card-body">
                    <h4><b>@product.Title</b></h4>
                    <p>@product.Price?.ToString("C")</p>
                    <button class="btn btn-danger btn-delete" title="Delete" @onclick="@(() => DeleteProduct(product))">
                        <span class="oi oi-trash"></span>
                    </button>
                    <button class="btn btn-success" title="Delete" @onclick="@(() => GoToEditProduct(product.Id))">
                        <span class="oi oi-pencil"></span>
                    </button>
                </div>
            </div>

Capturo el id del producto y lo mando por par√°metro a la vista para editarlo

private void GoToEditProduct(int productId)
    {
        NavigationManager.NavigateTo($"/editproduct/{productId}");
    }

ProductEditForm.razor

@page "/editproduct/{productIdParameter}"
@inject IProductService productService
@inject ICategoryService categoryService
@inject NavigationManager NavigationManager

<PageTitle>Edit Product</PageTitle>

<Title TitleProp="Edit Product"/>

<button class="btn btn-dark" @onclick="GoToProducts">Go to back products</button>

<EditForm Model="@product" OnSubmit="@Save">
    <div class="row">
        <div class="col-8 form-group">
            <label for="title" class="col-form-label">Title</label>
            <InputText class="form-control" id="title" @bind-Value="product.Title" required/>
        </div>
        <div class="col form-group">
            <label for="price" class="col-form-label">Price</label>
            <InputNumber class="form-control" id="price" @bind-Value="product.Price" min="0" required/>
        </div>
    </div>
    <div class="row">
        <div class="col form-group">
            <label for="category" class="col-form-label">Category</label>
            <InputSelect class="form-control" id="category" @bind-Value="product.CategoryId" required>
                <option>Select Category...</option>
                @foreach (var category in categories)
                {
                    <option value="@category.Id">@category.Name</option>
                }
            </InputSelect>
        </div>
        <div class="col form-group">
            <label for="image" class="col-form-label">Image (URL)</label>
            <InputText class="form-control" id="image" @bind-Value="product.Image" required />
        </div>
    </div>
    <div class="form-group">
        <label for="description" class="col-form-label">Description</label>
        <InputTextArea class="form-control" id="description" @bind-Value="product.Description" required />
    </div>
    <hr />
    <button class="btn btn-primary" type="submit">Save</button>
</EditForm>

@code {
    private Product product = new();
    private List<Category> categories { get; set; } = new List<Category>();
    [Parameter]
    public string productIdParameter { get; set; } = "";

    protected override async Task OnInitializedAsync()
    {
         await GetCategories();
         await GetProduct(int.Parse(productIdParameter));
    }

    public override async Task SetParametersAsync(ParameterView parameters)
    {
        if (parameters.TryGetValue<string>(nameof(productIdParameter), out var value))
        {
            productIdParameter = value ?? productIdParameter;
        }
        await base.SetParametersAsync(parameters);
    }

    private void GoToProducts()
    {
        NavigationManager.NavigateTo("/products");
    }

    private async Task GetCategories()
    {
        categories = await categoryService.Get() ?? categories;
    }

    private async Task GetProduct(int productId)
    {
        product = await productService.Get(productId) ?? product;
        product.Image = product.Images[0] ?? "";
    }

    private async Task Save()
    {
        product.Images = new string[1] { product.Image };
        await productService.Update(product);
        GoToProducts();
    }
}

En ProductService.cs agrego 2 funciones para obtener un producto por id y editar un producto

public async Task<Product?> Get(int productId)
    {
        var response = await _client.GetAsync($"v1/products/{productId}");
        var content = await response.Content.ReadAsStringAsync();
        if (!response.IsSuccessStatusCode) throw new ApplicationException(content);
        return JsonSerializer.Deserialize<Product>(content, _serializer);
    }

public async Task Update(Product product)
    {
        var response = await _client.PutAsync($"v1/products/{product.Id}", JsonContent.Create(product));
        var content = await response.Content.ReadAsStringAsync();
        if (!response.IsSuccessStatusCode) throw new ApplicationException(content);
    }

También modifico la interfaz del servicio

public interface IProductService
{
    Task<List<Product>?> Get();
    Task<Product?> Get(int productId);
    Task Add(Product product);
    Task Update(Product product);
    Task Delete(int productId);
}
Por acá les dejo la línea de código. \<button title="Delete" class="btn btn-danger btn-delete" @onclick="@(() => DeleteProduct(product))">\\\</button>
Link del Repositorio <https://github.com/platzi/curso-aplicaciones-web-blazor/blob/12-agregandolibreria/Pages/Products/Products.razor>
Deber√≠an dejar los recursos ūüėĒ

Para el reto basicamente es lo mismo, solo hay que agregar la propiedad Category dentro del modelo Product.

Hacer el ajuste para asignar el dato al formulario:

 product.Image = product.Images[0];
 product.CategoryId = product.Category.Id;

Y para poder pasar el parametro yo opte por usar el QueryString:

[Parameter]
[SupplyParameterFromQuery]
public string Id {get;set;}

Recuerda que puedes utilizar el comando dotnet watch para ver los cambios de la app en tiempo real.

products.razor


@page "/product"

@inject ILogger<Products> logger;
@inject  IProductService productService;
@inject  NavigationManager NavigationManager;
@inject  IJSRuntime IJSRuntime;

<PageTitle>Products</PageTitle>

<ModuleTitle Title="Products"/>
<button class="btn btn-dark" @onclick="@(()=> NavigationManager.NavigateTo("/addproduct"))">  Add Product</button>
@if (products?.Count > 0){
    <div class= "products-container">
            @foreach (var product in products)
            {
                <div class="card">
                    <img class="card-img-top" src="@product.Images[0]" alt="Product" loading="lazy" width ="270" height="210">
                    <div class="card-body">
                        <h4><b>@product.Title</b></h4>
                        <p>@product.Price?.ToString("C")</p>
                        <button title="Delete" class="btn btn-danger btn-delete" @onclick="@(() => DeleteProduct(product))"><span class="oi oi-trash"></span></button>

                    </div>
                </div>
            }
    </div>

 
 }
else{
 <p>
    No hay productos para mostrar.
 </p> 
 
 }

@code{
    private List<Product>? products;

protected override async Task OnInitializedAsync()
{
    await GetProducts();
}
    private async Task GetProducts(){
           products= await productService.Get();
    }
    private async Task DeleteProduct(Product product){
     bool confirmed = await IJSRuntime.InvokeAsync<bool>("confirm", $"Are you sure? { product.Title}");   
        if(!confirmed)
            return; 
        await productService.Delete(product.Id);
        await GetProducts();
    }

 }

En vez de llamar de nuevo al apícola se puede simplemente remover de la lista

products.Remove(product);