Creación de una aplicación de lista de tareas pendientes Blazor

Nota

Esta no es la versión más reciente de este artículo. Para la versión actual, consulte la versión .NET 8 de este artículo.

Importante

Esta información hace referencia a un producto en versión preliminar, el cual puede sufrir importantes modificaciones antes de que se publique la versión comercial. Microsoft no proporciona ninguna garantía, expresa o implícita, con respecto a la información proporcionada aquí.

Para la versión actual, consulte la versión .NET 8 de este artículo.

En este tutorial se proporciona una experiencia de trabajo básica para compilar y modificar una aplicación Blazor. Para obtener instrucciones de Blazor más detalladas, consulte la documentación de referencia de Blazor.

Obtenga información sobre cómo:

  • Crear un proyecto de aplicación Blazor de lista de tareas
  • Modificar los componentes de Razor
  • Usar el control de eventos y el enlace de datos en los componentes
  • Uso del enrutamiento en una aplicación Blazor

Al final de este tutorial, tendrá una aplicación de lista de tareas funcional.

Requisitos previos

Descargue e instale .NET si aún no está instalado en el sistema o si el sistema no tiene instalada la versión más reciente.

Creación de una aplicación Blazor

Cree una nueva aplicación web de Blazor denominada TodoList en un shell de comandos:

dotnet new blazor -o TodoList

La opción -o|--output crea una carpeta para el proyecto. Si ha creado una carpeta para el proyecto y el shell de comandos está abierto en esa carpeta, omita la opción -o|--output y el valor para crear la solución.

Use cualquiera de los siguientes modelos de hospedaje para crear una nueva aplicación de Blazor denominada TodoList en un shell de comandos:

  • Para obtener una experiencia con Blazor Server, cree la aplicación con el siguiente comando:

    dotnet new blazorserver -o TodoList
    
  • Para obtener una experiencia con Blazor WebAssembly, cree la aplicación con el siguiente comando:

    dotnet new blazorwasm -o TodoList
    

El comando anterior crea una carpeta denominada TodoList con la opción -o|--output para contener la aplicación. La carpeta TodoList es la carpeta raíz del proyecto. Cambie los directorios a la carpeta TodoList con el siguiente comando:

cd TodoList

Creación de una aplicación de lista de tareas pendientes Blazor

Agregue un nuevo componente Todo de Razor a la aplicación con el siguiente comando:

dotnet new razorcomponent -n Todo -o Components/Pages

La opción -n|--name del comando anterior especifica el nombre del nuevo componente Razor. El nuevo componente se crea en la carpeta Components/Pages del proyecto con la opción -o|--output.

dotnet new razorcomponent -n Todo -o Pages

La opción -n|--name del comando anterior especifica el nombre del nuevo componente Razor. El nuevo componente se crea en la carpeta Pages del proyecto con la opción -o|--output.

Importante

Los nombres de archivo de componente Razor requieren poner en mayúscula la primera letra. Abra la carpeta Pages y confirme que el nombre de archivo del componente Todo empieza con una letra mayúscula T. El nombre de archivo debe ser Todo.razor.

Abra el componente de Todo en cualquier editor de archivos y realice los siguientes cambios en la parte superior del archivo:

  • Agregue una directiva de @pageRazor con una dirección URL relativa de /todo.
  • Habilite la interactividad en la página para que no se represente estáticamente. El modo de representación del Servidor interactivo permite al componente controlar los eventos de la interfaz de usuario desde el servidor.
  • Agregue un título de página con el componente de PageTitle, que permite agregar un elemento <title> HTML a la página.

Abra el componente de Todo en cualquier editor de archivos y realice los siguientes cambios en la parte superior del archivo:

  • Agregue una directiva de @pageRazor con una dirección URL relativa de /todo.
  • Agregue un título de página con el componente de PageTitle, que permite agregar un elemento <title> HTML a la página.

Abra el componente Todo en cualquier editor de archivos y agregue una directiva @pageRazor con una dirección URL relativa de /todo.

Todo.razor:

@page "/todo"
@rendermode InteractiveServer

<PageTitle>Todo</PageTitle>

<h3>Todo</h3>

@code {

}
@page "/todo"

<PageTitle>Todo</PageTitle>

<h3>Todo</h3>

@code {

}
@page "/todo"

<PageTitle>Todo</PageTitle>

<h3>Todo</h3>

@code {

}
@page "/todo"

<h3>Todo</h3>

@code {

}
@page "/todo"

<h3>Todo</h3>

@code {

}

Guarde el archivo Todo.razor.

Agregue el componente Todo a la barra de navegación.

El componente NavMenu se usa en el diseño de la aplicación. Los diseños son componentes que le permiten impedir la duplicación de contenido en una aplicación. El componente NavLink proporciona una indicación en la interfaz de usuario de la aplicación cuando la aplicación carga la dirección URL del componente.

En el contenido del elemento de navegación (<nav>) del componente NavMenu, agregue el siguiente elemento <div> para el componente Todo.

En Components/Layout/NavMenu.razor:

En Shared/NavMenu.razor:

<div class="nav-item px-3">
    <NavLink class="nav-link" href="todo">
        <span class="oi oi-list-rich" aria-hidden="true"></span> Todo
    </NavLink>
</div>

Guarde el archivo NavMenu.razor.

Compile y ejecute la aplicación mediante el comando dotnet watch run en el shell de comandos desde la carpeta TodoList. Cuando la aplicación se ejecute, visite la nueva página de tareas pendientes seleccionando el vínculo Todo en la barra de navegación de la aplicación, que carga la página en /todo.

Deje la aplicación ejecutando el shell de comandos. Cada vez que se guarda un archivo, la aplicación se vuelve a generar automáticamente y la página del explorador se vuelve a cargar automáticamente.

Agregue un archivo TodoItem.cs a la raíz del proyecto (carpeta TodoList) para retener una clase que represente un elemento de la lista de tareas. Use el siguiente C# de código para la clase TodoItem.

TodoItem.cs:

namespace BlazorSample;

public class TodoItem
{
    public string? Title { get; set; }
    public bool IsDone { get; set; }
}
public class TodoItem
{
    public string? Title { get; set; }
    public bool IsDone { get; set; }
}
public class TodoItem
{
    public string? Title { get; set; }
    public bool IsDone { get; set; }
}
public class TodoItem
{
    public string Title { get; set; }
    public bool IsDone { get; set; }
}
public class TodoItem
{
    public string Title { get; set; }
    public bool IsDone { get; set; }
}

Nota

Si usa Visual Studio para crear el archivo TodoItem.cs y la clase TodoItem, use cualquiera de los métodos siguientes:

  • Quite el espacio de nombres que genera Visual Studio para la clase.
  • Use el botón Copiar del bloque de código anterior y reemplace todo el contenido del archivo que genera Visual Studio.

Vuelva al componente Todo y realice las tareas siguientes:

  • Agregue un campo a los elementos de tareas pendientes en un bloque @code. El componente Todo utiliza este campo para mantener el estado de la lista de tareas pendientes.
  • Agregue el marcado de la lista no ordenada y un bucle foreach para que cada elemento de la lista se represente en un elemento de la lista de tareas pendientes (<li>).

Components/Pages/Todo.razor:

@page "/todo"
@rendermode InteractiveServer

<PageTitle>Todo</PageTitle>

<h3>Todo</h3>

<ul>
    @foreach (var todo in todos)
    {
        <li>@todo.Title</li>
    }
</ul>

@code {
    private List<TodoItem> todos = new();
}

Pages/Todo.razor:

@page "/todo"

<PageTitle>Todo</PageTitle>

<h3>Todo</h3>

<ul>
    @foreach (var todo in todos)
    {
        <li>@todo.Title</li>
    }
</ul>

@code {
    private List<TodoItem> todos = new();
}

Pages/Todo.razor:

@page "/todo"

<PageTitle>Todo</PageTitle>

<h3>Todo</h3>

<ul>
    @foreach (var todo in todos)
    {
        <li>@todo.Title</li>
    }
</ul>

@code {
    private List<TodoItem> todos = new();
}

Pages/Todo.razor:

@page "/todo"

<h3>Todo</h3>

<ul>
    @foreach (var todo in todos)
    {
        <li>@todo.Title</li>
    }
</ul>

@code {
    private List<TodoItem> todos = new();
}

Pages/Todo.razor:

@page "/todo"

<h3>Todo</h3>

<ul>
    @foreach (var todo in todos)
    {
        <li>@todo.Title</li>
    }
</ul>

@code {
    private IList<TodoItem> todos = new List<TodoItem>();
}

Para agregar elementos de tareas pendientes a la lista, la aplicación requiere elementos de la interfaz de usuario. Agregue una entrada de texto (<input>) y un botón (<button>) debajo de la lista no ordenada (<ul>...</ul>):

@page "/todo"
@rendermode InteractiveServer

<PageTitle>Todo</PageTitle>

<h3>Todo</h3>

<ul>
    @foreach (var todo in todos)
    {
        <li>@todo.Title</li>
    }
</ul>

<input placeholder="Something todo" />
<button>Add todo</button>

@code {
    private List<TodoItem> todos = new();
}
@page "/todo"

<PageTitle>Todo</PageTitle>

<h3>Todo</h3>

<ul>
    @foreach (var todo in todos)
    {
        <li>@todo.Title</li>
    }
</ul>

<input placeholder="Something todo" />
<button>Add todo</button>

@code {
    private List<TodoItem> todos = new();
}
@page "/todo"

<PageTitle>Todo</PageTitle>

<h3>Todo</h3>

<ul>
    @foreach (var todo in todos)
    {
        <li>@todo.Title</li>
    }
</ul>

<input placeholder="Something todo" />
<button>Add todo</button>

@code {
    private List<TodoItem> todos = new();
}
@page "/todo"

<h3>Todo</h3>

<ul>
    @foreach (var todo in todos)
    {
        <li>@todo.Title</li>
    }
</ul>

<input placeholder="Something todo" />
<button>Add todo</button>

@code {
    private List<TodoItem> todos = new();
}
@page "/todo"

<h3>Todo</h3>

<ul>
    @foreach (var todo in todos)
    {
        <li>@todo.Title</li>
    }
</ul>

<input placeholder="Something todo" />
<button>Add todo</button>

@code {
    private IList<TodoItem> todos = new List<TodoItem>();
}

Guarde el archivo TodoItem.cs y el archivo Todo.razor actualizado. En el shell de comandos, la aplicación se vuelve a compilar automáticamente cuando se guardan los archivos. El explorador vuelve a cargar la página.

Al seleccionar el botón Add todo , no ocurre nada porque no hay ningún controlador de eventos conectado al botón.

Agregue un método AddTodo al componente Todo y registre el método para el botón mediante el atributo @onclick. El método AddTodo de C# se llama cuando se selecciona el botón:

<input placeholder="Something todo" />
<button @onclick="AddTodo">Add todo</button>

@code {
    private List<TodoItem> todos = new();

    private void AddTodo()
    {
        // Todo: Add the todo
    }
}
<input placeholder="Something todo" />
<button @onclick="AddTodo">Add todo</button>

@code {
    private List<TodoItem> todos = new();

    private void AddTodo()
    {
        // Todo: Add the todo
    }
}
<input placeholder="Something todo" />
<button @onclick="AddTodo">Add todo</button>

@code {
    private List<TodoItem> todos = new();

    private void AddTodo()
    {
        // Todo: Add the todo
    }
}
<input placeholder="Something todo" />
<button @onclick="AddTodo">Add todo</button>

@code {
    private List<TodoItem> todos = new();

    private void AddTodo()
    {
        // Todo: Add the todo
    }
}
<input placeholder="Something todo" />
<button @onclick="AddTodo">Add todo</button>

@code {
    private IList<TodoItem> todos = new List<TodoItem>();

    private void AddTodo()
    {
        // Todo: Add the todo
    }
}

Para obtener el título del nuevo elemento de la lista de tareas pendientes, agregue un campo de cadena newTodo en la parte superior del bloque @code:

private string? newTodo;
private string newTodo;

Modifique el elemento <input> de texto para enlazar newTodo con el atributo @bind:

<input placeholder="Something todo" @bind="newTodo" />

Actualice el método AddTodo para agregar el TodoItem con el título especificado a la lista. Borre el valor de la entrada de texto mediante el establecimiento de newTodo en una cadena vacía:

@page "/todo"
@rendermode InteractiveServer

<PageTitle>Todo</PageTitle>

<h3>Todo</h3>

<ul>
    @foreach (var todo in todos)
    {
        <li>@todo.Title</li>
    }
</ul>

<input placeholder="Something todo" @bind="newTodo" />
<button @onclick="AddTodo">Add todo</button>

@code {
    private List<TodoItem> todos = new();
    private string? newTodo;

    private void AddTodo()
    {
        if (!string.IsNullOrWhiteSpace(newTodo))
        {
            todos.Add(new TodoItem { Title = newTodo });
            newTodo = string.Empty;
        }
    }
}
@page "/todo"

<PageTitle>Todo</PageTitle>

<h3>Todo</h3>

<ul>
    @foreach (var todo in todos)
    {
        <li>@todo.Title</li>
    }
</ul>

<input placeholder="Something todo" @bind="newTodo" />
<button @onclick="AddTodo">Add todo</button>

@code {
    private List<TodoItem> todos = new();
    private string? newTodo;

    private void AddTodo()
    {
        if (!string.IsNullOrWhiteSpace(newTodo))
        {
            todos.Add(new TodoItem { Title = newTodo });
            newTodo = string.Empty;
        }
    }
}
@page "/todo"

<PageTitle>Todo</PageTitle>

<h3>Todo</h3>

<ul>
    @foreach (var todo in todos)
    {
        <li>@todo.Title</li>
    }
</ul>

<input placeholder="Something todo" @bind="newTodo" />
<button @onclick="AddTodo">Add todo</button>

@code {
    private List<TodoItem> todos = new();
    private string? newTodo;

    private void AddTodo()
    {
        if (!string.IsNullOrWhiteSpace(newTodo))
        {
            todos.Add(new TodoItem { Title = newTodo });
            newTodo = string.Empty;
        }
    }
}
@page "/todo"

<h3>Todo</h3>

<ul>
    @foreach (var todo in todos)
    {
        <li>@todo.Title</li>
    }
</ul>

<input placeholder="Something todo" @bind="newTodo" />
<button @onclick="AddTodo">Add todo</button>

@code {
    private List<TodoItem> todos = new();
    private string newTodo;

    private void AddTodo()
    {
        if (!string.IsNullOrWhiteSpace(newTodo))
        {
            todos.Add(new TodoItem { Title = newTodo });
            newTodo = string.Empty;
        }
    }
}
@page "/todo"

<h3>Todo</h3>

<ul>
    @foreach (var todo in todos)
    {
        <li>@todo.Title</li>
    }
</ul>

<input placeholder="Something todo" @bind="newTodo" />
<button @onclick="AddTodo">Add todo</button>

@code {
    private IList<TodoItem> todos = new List<TodoItem>();
    private string newTodo;

    private void AddTodo()
    {
        if (!string.IsNullOrWhiteSpace(newTodo))
        {
            todos.Add(new TodoItem { Title = newTodo });
            newTodo = string.Empty;
        }
    }
}

Guarde el archivo Todo.razor. La aplicación se vuelve a generar automáticamente en el shell de comandos y la página se vuelve a cargar en el explorador.

Se puede hacer que el texto de título de cada elemento de tarea pendiente sea editable y una casilla puede ayudar al usuario a realizar el seguimiento de los elementos completados. Agregue una entrada de casilla a cada elemento de tarea pendiente y enlace su valor a la propiedad IsDone. Cambie @todo.Title a un elemento <input> enlazado a todo.Title con @bind:

<ul>
      @foreach (var todo in todos)
      {
         <li>
            <input type="checkbox" @bind="todo.IsDone" />
            <input @bind="todo.Title" />
         </li>
      }
</ul>

Actualice el encabezado <h3> para mostrar un recuento del número de elementos de la lista de tareas que no se han completado (IsDone es false). La expresión Razor del encabezado siguiente se evalúa cada vez que Blazor vuelve a representar el componente.

<h3>Todo (@todos.Count(todo => !todo.IsDone))</h3>

Componente completado Todo :

@page "/todo"
@rendermode InteractiveServer

<PageTitle>Todo</PageTitle>

<h1>Todo (@todos.Count(todo => !todo.IsDone))</h1>

<ul>
    @foreach (var todo in todos)
    {
        <li>
            <input type="checkbox" @bind="todo.IsDone" />
            <input @bind="todo.Title" />
        </li>
    }
</ul>

<input placeholder="Something todo" @bind="newTodo" />
<button @onclick="AddTodo">Add todo</button>

@code {
    private List<TodoItem> todos = new();
    private string? newTodo;

    private void AddTodo()
    {
        if (!string.IsNullOrWhiteSpace(newTodo))
        {
            todos.Add(new TodoItem { Title = newTodo });
            newTodo = string.Empty;
        }
    }
}
@page "/todo"

<PageTitle>Todo</PageTitle>

<h1>Todo (@todos.Count(todo => !todo.IsDone))</h1>

<ul>
    @foreach (var todo in todos)
    {
        <li>
            <input type="checkbox" @bind="todo.IsDone" />
            <input @bind="todo.Title" />
        </li>
    }
</ul>

<input placeholder="Something todo" @bind="newTodo" />
<button @onclick="AddTodo">Add todo</button>

@code {
    private List<TodoItem> todos = new();
    private string? newTodo;

    private void AddTodo()
    {
        if (!string.IsNullOrWhiteSpace(newTodo))
        {
            todos.Add(new TodoItem { Title = newTodo });
            newTodo = string.Empty;
        }
    }
}
@page "/todo"

<PageTitle>Todo</PageTitle>

<h1>Todo (@todos.Count(todo => !todo.IsDone))</h1>

<ul>
    @foreach (var todo in todos)
    {
        <li>
            <input type="checkbox" @bind="todo.IsDone" />
            <input @bind="todo.Title" />
        </li>
    }
</ul>

<input placeholder="Something todo" @bind="newTodo" />
<button @onclick="AddTodo">Add todo</button>

@code {
    private List<TodoItem> todos = new();
    private string? newTodo;

    private void AddTodo()
    {
        if (!string.IsNullOrWhiteSpace(newTodo))
        {
            todos.Add(new TodoItem { Title = newTodo });
            newTodo = string.Empty;
        }
    }
}
@page "/todo"

<h1>Todo (@todos.Count(todo => !todo.IsDone))</h1>

<ul>
    @foreach (var todo in todos)
    {
        <li>
            <input type="checkbox" @bind="todo.IsDone" />
            <input @bind="todo.Title" />
        </li>
    }
</ul>

<input placeholder="Something todo" @bind="newTodo" />
<button @onclick="AddTodo">Add todo</button>

@code {
    private List<TodoItem> todos = new();
    private string? newTodo;

    private void AddTodo()
    {
        if (!string.IsNullOrWhiteSpace(newTodo))
        {
            todos.Add(new TodoItem { Title = newTodo });
            newTodo = string.Empty;
        }
    }
}
@page "/todo"

<h1>Todo (@todos.Count(todo => !todo.IsDone))</h1>

<ul>
    @foreach (var todo in todos)
    {
        <li>
            <input type="checkbox" @bind="todo.IsDone" />
            <input @bind="todo.Title" />
        </li>
    }
</ul>

<input placeholder="Something todo" @bind="newTodo" />
<button @onclick="AddTodo">Add todo</button>

@code {
    private List<TodoItem> todos = new();
    private string? newTodo;

    private void AddTodo()
    {
        if (!string.IsNullOrWhiteSpace(newTodo))
        {
            todos.Add(new TodoItem { Title = newTodo });
            newTodo = string.Empty;
        }
    }
}

Guarde el archivo Todo.razor. La aplicación se vuelve a generar automáticamente en el shell de comandos y la página se vuelve a cargar en el explorador.

Agregue los elementos, edite los elementos y marque los elementos de la lista de tareas realizados para probar el componente.

Cuando termine, cierre la aplicación en el shell de comandos. Muchos shells de comandos aceptan el comando de teclado Ctrl+C (Windows) o +C (macOS) para detener una aplicación.

Publicar en Azure

Para obtener más información sobre la implementación en Azure, consulte Inicio rápido: Implementación de una aplicación web de ASP.NET.

Pasos siguientes

En este tutorial ha aprendido a:

  • Crear un proyecto de aplicación Blazor de lista de tareas
  • Modificar los componentes de Razor
  • Usar el control de eventos y el enlace de datos en los componentes
  • Uso del enrutamiento en una aplicación Blazor

Más información sobre las herramientas de ASP.NET Core Blazor: