Ir al contenido principal

Creando un DropDownlist en Cascada Genérico para ASP usando JQuery



Inspirado en los tutoriales del gran educador Juan Carlos Zuluaga, me motive a escribir un articulo sobre como crear (o usar) un Dropdownlist en cascada, es decir, que los datos que haya en un lado B (como ciudad) dependa del dato seleccionado en el lado A (como pais).


Si bien es cierto que realizar un Ddl en cascada es algo simple y sencillo, no deja de ser cierto que la duplicidad de código es algo que últimamente preocupa mas de la cuenta a las empresas, quienes escogen a un programador por sus conocimientos técnicos, pero de igual forma prefieren que esos conocimientos técnicos sean óptimos.

Por eso he decidido explicar el modo en el que yo lo he hecho, claro que pueden haber otros modos, pero, este es el mas simple que he visto hasta el momento, ya que cuando lo hice, lo hice realmente con conocimientos muy básicos de c#, así que esto es lo que garantiza que esta hecho por un novato para novatos :D



Iniciemos


Lo primero que vamos a hacer es crear 3 modelos,

Pais=>Ciudad=>Client  


public class Country
{
    public int Id { getset; } 
    public string Name { getset; } 
    public string Denomym { getset; } 
    public ICollection<City> Cities { getset; }
}
public class City
{
    public int Id { getset; } 
    public string Name { getset; } 
    public string Denomym { getset; } 
    public Country Country { getset; } 
    public ICollection<Client> Clients { getset; }
}
public class Client
{
    public int Id { getset; } 
    public string Name { getset; } 
    public string Lastname { getset; } 
    public City City { getset; }
 
}
La idea es que al seleccionar un país debe filtrar y traerme las ciudades del mismo.

Posterior a eso, deberemos de crear un ViewModel que aloje los datos del modelo Client, y al cual le complementaremos los datos que no posee el mismo, en mi caso particular, yo siempre prefiero ponerlo a heredar de la clase base, y completar las que faltan, pero en este ejemplo lo hare lo mas simple posible.


public class ClientViewModel //: Client
{
    public int Id { getset; }
    public string Name { getset; }
    public string Lastname { getset; }
    public City City { getset; }
 
    [Display(Name = "City")]
    [Range(1int.MaxValue, ErrorMessage = "You must select a City.")]
    public int CityId { getset; }
 
    [Display(Name = "Country")]
    [Range(1int.MaxValue, ErrorMessage = "You must select a Country.")]
    public int CountryId { getset; }
    //This is added because I dont want to save country on client, but I need on the ViewModel
    public ICollection<Country> Country { getset; }
    //This is added to receive the Listed items
    public IEnumerable<SelectListItem> Cities { getset; }
    public IEnumerable<SelectListItem> Countries { getset; }
 
}

Creamos un Helper para convertir cualquier entidad a un SelectListItem, esto no es necesario, pero es una forma de evitar la duplicidad de código y mas cuando esto es algo que normalmente no varia.


public class GenericSelectList
{
    public IEnumerable<SelectListItem> CreateSelectList<T>(IList<T> entities, Func<Tobject> funcToGetValue, Func<Tobject> funcToGetText)
    {
        return entities
            .Select(x => new SelectListItem
            {
                Value = funcToGetValue(x).ToString(),
                Text = funcToGetText(x).ToString()
            });
    }
}

Ahora es el momento de Crear nuestro método que se va a encargar de traer nuestros datos, yo personalmente lo pongo en el controlador que se va a encargar de manipular nuestra información, pero, perfectamente puede ser puesto en un Helper.


public JsonResult GetCitiesFromCountry(int id)
 {
     var dbList = _context.Cities.Where(m => m.Country.Id == id)
         .Select(c => new
         {
             Id = c.Id,
             Name = c.Name
         });
 
     return Json(dbList);
 }

Después creamos el control que se encargara de traer nuestros datos para mandarlo a la vista y tras eso obtener los datos, convertirlo para mandarlo a la base de datos.

Por obvias razones acá no voy a usar patrones ni nada por el estilo, pues el único interés es explicar el archivo Js genérico para llenar un ddl en cascada.


public class ClientsController : Controller
  {
      private readonly AppContext _context;
      private readonly GenericSelectList _genericSelectList;
      
      public ClientsController(AppContext context)
      {
          _context = context;
          _genericSelectList = new GenericSelectList();
      }
     
       public async Task<IActionResult> Create()
      {
          var countries = new List<Country>
          {
              new Country
              {
                  Id = 0,
                  Name = "Choose one Country"
              }
          };
       
          countries.AddRange(await _context.Countries.ToListAsync());       
          var model = new ClientViewModel
          {
              Countries = _genericSelectList.CreateSelectList(countries, x => x.Id, x => x.Name),
          }; 
          return View(model);
      }
 
      [HttpPost]
      [ValidateAntiForgeryToken]
      public async Task<IActionResult> Create(ClientViewModel model)
      {
          if (ModelState.IsValid)
          {
              var city = await _context.Cities.FindAsync(model.CityId); 
              var client = new Client
              {
                  Name = model.Name,
                  Lastname = model.Lastname,
                  City = city
              }; 
              _context.Add(client);
              await _context.SaveChangesAsync();
              return RedirectToAction(nameof(Index));
          }
          return View(model);
      }
  }

Creamos la vista y referenciamos el script en nuestra pagina, y creamos una variable mediante javascript que se llame "gUrlDdl" a la cual le debemos asignar la url donde esta el método que trae los datos., no olvides asignarle al select Maestro la clase "MasterDdl" y al detalle "DetailDdl"


@model GenDdlSampleCoreMvc.Models.ClientViewModel
 
<div class="row">
    <div class="col-md-4">
        <form asp-action="Create">
            <div asp-validation-summary="ModelOnly" class="text-danger"></div>
 
            <div class="form-group">
                <label asp-for="Country" class="control-label"></label>
                <select asp-for="CountryId" 
                        asp-items="Model.Countries"
                        class="form-control MasterDdl">
                </select>
                <span asp-validation-for="Country" class="text-danger"></span>
            </div>
            <div class="form-group">
                <label asp-for="City" class="control-label"></label>
                <select asp-for="CityId" 
                        asp-items="Model.Cities" 
                        class="form-control DetailDdl">                
                </select>
                <span asp-validation-for="City" class="text-danger"></span>
            </div>
            <div class="form-group">
                <label asp-for="Name" class="control-label"></label>
                <input asp-for="Name" class="form-control" />
                <span asp-validation-for="Name" class="text-danger"></span>
            </div>
            <div class="form-group">
                <label asp-for="Lastname" class="control-label"></label>
                <input asp-for="Lastname" class="form-control" />
                <span asp-validation-for="Lastname" class="text-danger"></span>
            </div>
            <div class="form-group">
                <input type="submit" value="Create" class="btn btn-primary" />
            </div>
        </form>
    </div>
</div>
<script src="~/lib/sGenCascadeDdl/dist/sgencascadeddl.js"></script>
 
<script>
         var gUrlDdl = '@Url.Action("GetCitiesFromCountry""Clients")';
</script>






Y listo, ya tenemos todo lo que necesitamos para nuestro Dropdown List en Cascada


Puedes ver el código de ejemplo, así como el script necesario en mi repositorio.

https://github.com/sgermosen/GenericCascadeDropDownList

Comentarios

Entradas populares de este blog

MANTENER UNA PÁGINA WEB SEGURA, CLAVE PARA LOGRAR VISIBILIDAD Y AUMENTAR LA CONFIANZA DE LOS VISITANTES

El comercio global y los modelos de negocio se encuentran en pleno proceso de adaptación al mundo digital, que es ya toda una realidad. En este sentido, el 62.6% de los españoles realizó compras a través de Internet en 2020, frente al 58% que lo hicieron en el año anterior, según la Encuesta sobre Equipamiento y Uso de Tecnologías de Información y Comunicación en los Hogares, elaborada por el Instituto Nacional de Estadística. Estamos, por tanto, ante una tendencia al alza en la que las tiendas online están cobrando un peso cada vez más importante para los consumidores.

Crea apps sin programar

Ahora más que nunca, son diversos los medios que permiten tener conocimiento en áreas como la tecnología junto a los sitios web y apps móviles.

7 Mitos de Programación que te Hacen Perder el Tiempo

En el mundo del desarrollo de software, existen numerosos "mantras" y "mejores prácticas" que seguimos religiosamente. Sin embargo, muchas de estas ideas aparentemente brillantes pueden convertirse en verdaderas trampas que nos hacen desperdiciar tiempo valioso. Este análisis examina varios mitos de programación que, si bien pueden parecer sensatos a primera vista, podrían estar obstaculizando tu productividad real. Mito 1: Necesitas dominar las tecnologías más recientes para ser relevante La trampa: El miedo a quedarse atrás (FOMO) nos empuja a invertir continuamente tiempo en aprender cada nuevo framework, lenguaje o herramienta que aparece en el horizonte tecnológico. La realidad: Las tecnologías "dinosaurio" siguen dominando el mundo real: WordPress y PHP continúan ejecutando la mayoría de las aplicaciones web Java sigue siendo el estándar en el mundo empresarial La mayoría de las bases de datos siguen siendo SQL C++ continúa siendo fundamen...