Retrieve the value of a dynamically generated field

Asked

Viewed 286 times

1

Good morning. Staff would like to know how do I recover the value of the control that is generated dynamically in my form at runtime? Type below in the image I have a class that brings all the properties of the controls to be shown in the Client View. In it I bring the type of HTML control, the CSS class that will be used, the order that will appear this control on the page, etc., everything already pre-configured in the database: Configurações do Controle

At the time I perform Submit and the model is not valid, I am not able to recover the value typed in the field as shown in the page below: Tela Cadastro de Cliente Formulário não está recuperando o valor Digitado

I’m trying to make this kind of dynamic control generation work, because I think of a registration system where I can have several clients with different registration screens, with different fields, different display names, the order that each label or input appears, etc. Thinking about this scenario it is easy to assemble all screens according to the requirements of screens with say 10 clients with different screens, without having to touch my Views. I tried to do it this way, but if anyone has a better idea that can help me generate these controls dynamically without having to create multiple views in the project thank you or help me by following this logic that I did.

using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.ComponentModel.DataAnnotations;

namespace ProjetoModeloDDD.MVC.ViewModels
{
    public class ClienteViewModel
    {
        [Key]
        public int ClienteId { get; set; }

        [Required(ErrorMessage = "Preencha o campo Nome")]
        [MaxLength(150, ErrorMessage = "Máximo {0} caracteres")]
        [MinLength(2, ErrorMessage = "Minimo {0} caracteres")]
        public string Nome { get; set; }

        [Required(ErrorMessage = "Preencha o campo Sobrenome")]
        [MaxLength(150, ErrorMessage = "Máximo {0} caracteres")]
        [MinLength(2, ErrorMessage = "Mínimo {0} caracteres")]
        public string Sobrenome { get; set; }

        [Required(ErrorMessage = "Preencha o campo Endereço")]
        [MaxLength(150, ErrorMessage = "Máximo {0} caracteres")]
        [MinLength(2, ErrorMessage = "Mínimo {0} caracteres")]
        [Display(Name = "Endereço")]
        public string Endereco { get; set; }

        [Display(Name = "Ponto de Ref.")]
        public string PontoReferencia { get; set; }
        public string Telefone { get; set; }

        [Display(Name = "Data de Nascimento")]
        public DateTime DataNascimento { get; set; }

        [Required(ErrorMessage = "Preencha o campo E-mail")]
        [MaxLength(100, ErrorMessage = "Máximo {0} caracteres")]
        [EmailAddress(ErrorMessage = "Preencha um E-mail válido")]
        [DisplayName("E-mail")]
        public string Email { get; set; }

        [ScaffoldColumn(false)]
        public DateTime DataCadastro { get; set; }

        public bool Ativo { get; set; }
        public virtual IEnumerable<ProdutoViewModel> Produtos { get; set; }

        public IEnumerable<MenuConfigViewModel> MenuConfigViewModels { get; set; }
    }
}

View Create Client Code

@using ProjetoModeloDDD.MVC.Helpers
@model  ProjetoModeloDDD.MVC.ViewModels.ClienteViewModel


@{
    ViewBag.Title = "Create";


}

<h2>Create</h2>


@using (Html.BeginForm()) 
{
    @Html.AntiForgeryToken()

    <div class="form-horizontal">
        <h4>ClienteViewModel</h4>
        <hr />fma

        @if (Model.MenuConfigViewModels != null)
        {
            foreach (var item in Model.MenuConfigViewModels)
            {
                if (item.TagHtml.Equals("input"))
                {
                    @Html.ValidationSummary(true, "", new { @class = "text-danger" })
                    <div class="form-group">
                        @HtmlHelpers.MyInputHelper(item.Name, item.Name, "", htmlAttributes: new { @class = "form-control text-box single-line input-validation-error" })
                        @*@Html.ValidationMessageFor(model => model.Nome, "", new { @class = "text-danger" })*@
                    </div>
                }

            }

        } 

        <div class="form-group">
            <div class="col-md-offset-2 col-md-10">
                <input type="submit" value="Create" class="btn btn-default" />
            </div>
        </div>
    </div>
}

<div>
    @Html.ActionLink("Back to List", "Index")
</div>

@section Scripts {
    @Scripts.Render("~/bundles/jqueryval")
}
  • Please provide the class ClienteViewModel?

  • You’d better take the pictures and put the code in. It’s easier to help.

  • Ready changed and included the Viewsmodels codes

  • I could not understand what you want. How so dynamic? By your images, you are filling only one field. Could explain better what you want?

  • For example, let’s say you had 10 clients with different sign-up screens. Creating 10 views would not be feasible, so I would like to create only 1 view where I mount all the HTML fields by a foreach stating when is the type of control whether it is input, label, table, etc, according to the requirements of the client, so I can specify to which CSS class that field will use etc.

  • I think I get it, your application is customized for each customer who will use it, and for each one the form fields are different, is that it ? If so, this is one of the reasons why you should research SOLID.

Show 1 more comment

1 answer

1


What you want is one (or all) of the principles by which you exist SOLID

Create an interface, put all the fields that will exist mandatory for all 10, 100, N clients

public interface IClienteDaAplicacaoModel
{
    Int32 ClienteId {get;set;}
    String CPF {get;set;}
    String Email {get;set;}
}

Now for each customer, create a concrete model that inherits the interface

public sealed class ClienteXModel : IClienteDaAplicacaoModel
{
    public String CampoEspecificoDoClienteX {get;set;}
    public String CNPJ {get;set;}
}

public sealed class ClienteYModel : IClienteDaAplicacaoModel
{
    public Int64 TelefoneContato {get;set;}
}

public sealed class...outros clientes

From there you work with the Interface and not with its implementations, and use Reflection to pick up the fields of each implementation according to use

In addition to the links above, here are a few more about SOLID and Reflection

*I used Sealed in the concrete examples, but they can be Abstract or not Sealed if you want them to be inherited by other customers (let’s assume that the Z client has everything from the X client and the interface, then in this case it would be enough to inherit X in Z instead of having the same X fields in Z again)

Browser other questions tagged

You are not signed in. Login or sign up in order to post.