Solucionado (ver solução)
Solucionado
(ver solução)
3
respostas

Validação a formulários dinâmicos (Client-side)

Estou com problemas para fazer a validação do lado do cliente de um formulário que está dentro de um Modal que é carregado por uma Partial View.

Esta aqui é a entidade.

public class Cidade : BaseModel
{
    [Required(ErrorMessage = "O campo cidade é obrigatório.")]
    [StringLength(30)]
    [Display(Name = "Cidade")]
    public string Nome { get; set; }

    [Required(ErrorMessage = "O campo UF é obrigatório.")]
    public string UF { get; set; }
}

Este são os métodos envolvidos no controller.

// POST: Cidade/Create
[HttpPost]
[ValidateAntiForgeryToken]
public async Task<IActionResult> Create([Bind("ID,Nome,UF")] Cidade cidade)
{
    if (ModelState.IsValid)
    {
        await _cidadeRepository.Create(cidade);
        return RedirectToAction(nameof(Table));
    }
    return NotFound();
}

// GET /Cidade/New
public IActionResult New()
{
    return PartialView("_NewPartial", new Cidade());
}

Está é a view que faz a chamada do modal.

<!--    ### Content ###    -->
<button id="btnNew" class="btn btn-primary"><i class="fas fa-plus"></i> Novo</button>

 ...

<!--    ### Modal ###    -->

<div class="modal fade" id="cidadeModal" tabindex="-1">
    <div class="modal-dialog">
        <div class="modal-content" id="cidadeContent" >
            <!--    ### Partial View Load Dynamically ###    -->
        </div>
    </div>
</div>

    <script type="text/javascript">
        $(function () {
            $('#btnNew').click(function () {
                var route = '@Url.Action("New", "Cidade")';
                $('#cidadeContent').load(route);
                $('#cidadeModal').modal('show');
            });
    </script>

E essa é a Partial View

@model Sistema.Models.Cidade

<div class="modal-header">
    <h5 class="modal-title">Nova localidade</h5>
</div>
<form id="partialform" asp-controller="Cidade" asp-action="Create" data-ajax-method="post" data-ajax="true" data-ajax-update="#partialform" data-ajax-mode="replace">
    <div class="modal-body">
        <div class="form-group row">
            <label asp-for="Nome" class="col-sm-2 col-form-label" for="nome">Cidade </label>
            <div class="col-sm-10">
                <input type="text" asp-for="Nome" name="nome" class="form-control" id="nome" placeholder="Nome da cidade">
                <span asp-validation-for="Nome" class="text-danger"></span>
            </div>
        </div>
        <div class="form-group row">
            <label asp-for="UF" class="col-sm-2 col-form-label" for="uf">UF</label>
            <div class="col-sm-10">
                <select class="form-control" asp-for="UF" name="uf" id="uf">
                    <option selected disabled>Selecione um estado</option>
                    <option>RS</option>
                    <option>SC</option>
                    <option>PR</option>
                </select>
                <span asp-validation-for="UF" class="text-danger"></span>
            </div>
        </div>
        <div asp-validation-summary="All"></div>
    </div>
    <div class="modal-footer col text-center">
        <button class="btn btn-secondary btn-footer-modal" data-dismiss="modal">Cancelar</button>
        <button class="btn btn-success btn-footer-modal">Salvar</button>
    </div>
</form>

<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery-validation-unobtrusive/3.2.11/jquery.validate.unobtrusive.min.js"></script>

Primeiramente eu não estava tendo nenhuma forma de validação do lado do cliente, ele chamava o método no controller e dava modelo inválido retornando NotFound. Pesquisando eu achei para colocar isso aqui no form da Partial View:

<form id="partialform" asp-controller="Cidade" asp-action="Create" data-ajax-method="post" data-ajax="true" data-ajax-update="#partialform" data-ajax-mode="replace">

Além de incluir o script de validação na Partial View (colocar ali foi o único lugar que fez funcionar)

<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery-validation-unobtrusive/3.2.11/jquery.validate.unobtrusive.min.js"></script>

Com isso ele passou a fazer a validação no lado do cliente, sem nem chamar o método no controller. Só que uma coisa ta estranha ainda, quando tem erro no formulário, o input é atualizado com classe "input-validation-error" e o sumário também está funcionando corretamente listando os erros, mas o span continua como "field-validation-valid" ao invés de "field-validation-error" e tão pouco a mensagem de erro é inserida no span. Ou seja, é isso que estou recebendo agora:

http://prntscr.com/mkntvy

E o que eu queria era:

http://prntscr.com/mknv0m

Desculpa se me estendi. Foi no intuito de deixar bem claro o que está acontecendo. Obrigado, Thiago.

3 respostas

No site da MS (https://docs.microsoft.com/pt-br/aspnet/core/mvc/models/validation?view=aspnetcore-2.2) tem um javascript para validação de formulários dinâmicos que faz com que o retorno da validação seja atualizado na tela, mas eu não entendi como fazer, nem se é exatamente esse meu caso.

solução!

Oi, Thiago, tudo bem?

Faz um teste: remova a declaração dos atributos id e name dos inputs de Nome e UF. A idéia é deixar isso a cargo do próprio TagHelper de cada um (asp-for).

Me dá um feedback aqui.

Funcionou, obrigado pela resposta!

Além do que você falou, removi os seguintes atributos do form, pelo que vi eles não estão fazendo nada.

data-ajax-method="post" data-ajax="true" data-ajax-update="#partialform" data-ajax-mode="replace"

Quanto aos inputs, o conflito estava no atributo name.

Quer mergulhar em tecnologia e aprendizagem?

Receba a newsletter que o nosso CEO escreve pessoalmente, com insights do mercado de trabalho, ciência e desenvolvimento de software