ASP.NET MVC Calculate value in a table

1

I am developing a register where I will have a table with some additional details that must be inserted together with the main register.

But one of the columns of this table is calculated, which is where I'm having difficulty performing this calculation.

Basically, I need to calculate the ValorCalculado field based on Percentual applied to ValorPrincipal

  

And this value should appear as the user enters the MainValue field or Percentage

Yes, I did a very simple example, think of an input system of products in stock, where the user has read an XML and this note has at least 10 products, and is launching the percentage of product profit per product and wanting to see what the sales value as you change these items. Imagine having to be making a request to the server every time it has an altered percentage in the View, so it would be good to do the calculation both in View and not only in the server.

In summary, I need the CalculatedValue to display the PrimaryValue * Percent every time I have a change in PrimaryValue or Percentage

Follow the example code

    public class CadastroController : Controller
    {
        // GET: Cadastro
        public ActionResult Index()
        {
            CadastroViewModel model = new CadastroViewModel();

            model.Detalhes.Add(new CadastroDetalhesViewModel());
            model.Detalhes.Add(new CadastroDetalhesViewModel());
            model.Detalhes.Add(new CadastroDetalhesViewModel());
            model.Detalhes.Add(new CadastroDetalhesViewModel());

            return View(model);
        }

        [HttpPost]
        public ActionResult Index(CadastroViewModel model)
        {
            return View(model);
        }
    }

Model

    public class CadastroViewModel
    {
        public CadastroViewModel()
        {
            Detalhes = new List<CadastroDetalhesViewModel>();
        }

        public int CadastroId { get; set; }

        public DateTime DataInicio { get; set; }

        public DateTime DataFim { get; set; }

        public decimal ValorPrincipal { get; set; }

        public decimal Percentual { get; set; }

        public decimal ValorCalculado { get; set; }

        public List<CadastroDetalhesViewModel> Detalhes { get; set; }
    }

    public class CadastroDetalhesViewModel
    {
        public int CadastroId { get; set; }

        public decimal ValorPrincipal { get; set; }

        public decimal Percentual { get; set; }

        public decimal ValorCalculado { get; set; }

    }

View

@model AspNetMvcCalcularValoresTabela.Models.CadastroViewModel

@{
    ViewBag.Title = "View";
}

<h2>View</h2>

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

    <div class="form-horizontal">
        <h4>CadastroViewModel</h4>
        <hr />
        @Html.ValidationSummary(true, "", new { @class = "text-danger" })
        <div class="form-group">
            @Html.LabelFor(model => model.CadastroId, htmlAttributes: new { @class = "control-label col-md-2" })
            <div class="col-md-10">
                @Html.EditorFor(model => model.CadastroId, new { htmlAttributes = new { @class = "form-control" } })
                @Html.ValidationMessageFor(model => model.CadastroId, "", new { @class = "text-danger" })
            </div>
        </div>

        <div class="form-group">
            @Html.LabelFor(model => model.DataInicio, htmlAttributes: new { @class = "control-label col-md-2" })
            <div class="col-md-10">
                @Html.EditorFor(model => model.DataInicio, new { htmlAttributes = new { @class = "form-control" } })
                @Html.ValidationMessageFor(model => model.DataInicio, "", new { @class = "text-danger" })
            </div>
        </div>

        <div class="form-group">
            @Html.LabelFor(model => model.DataFim, htmlAttributes: new { @class = "control-label col-md-2" })
            <div class="col-md-10">
                @Html.EditorFor(model => model.DataFim, new { htmlAttributes = new { @class = "form-control" } })
                @Html.ValidationMessageFor(model => model.DataFim, "", new { @class = "text-danger" })
            </div>
        </div>

        <div class="form-group">
            @Html.LabelFor(model => model.ValorPrincipal, htmlAttributes: new { @class = "control-label col-md-2" })
            <div class="col-md-10">
                @Html.EditorFor(model => model.ValorPrincipal, new { htmlAttributes = new { @class = "form-control" } })
                @Html.ValidationMessageFor(model => model.ValorPrincipal, "", new { @class = "text-danger" })
            </div>
        </div>

        <div class="form-group">
            @Html.LabelFor(model => model.Percentual, htmlAttributes: new { @class = "control-label col-md-2" })
            <div class="col-md-10">
                @Html.EditorFor(model => model.Percentual, new { htmlAttributes = new { @class = "form-control" } })
                @Html.ValidationMessageFor(model => model.Percentual, "", new { @class = "text-danger" })
            </div>
        </div>

        <div class="form-group">
            @Html.LabelFor(model => model.ValorCalculado, htmlAttributes: new { @class = "control-label col-md-2" })
            <div class="col-md-10">
                @Html.EditorFor(model => model.ValorCalculado, new { htmlAttributes = new { @class = "form-control" } })
                @Html.ValidationMessageFor(model => model.ValorCalculado, "", new { @class = "text-danger" })
            </div>
        </div>

        <table>
            <thead>
                <tr>
                    <th></th>
                    <th></th>
                    <th></th>
                </tr>
            </thead>
            <tbody>
                @for (int i = 0; i < Model.Detalhes.Count; i++)
                {
                    <tr>
                        <td>@Html.EditorFor(a => a.Detalhes[i].ValorPrincipal, new { htmlAttributes = new { @class = "form-control" } })</td>
                        <td>@Html.EditorFor(a => a.Detalhes[i].Percentual, new { htmlAttributes = new { @class = "form-control" } })</td>
                        <td>@Html.EditorFor(a => a.Detalhes[i].ValorCalculado, new { htmlAttributes = new { @class = "form-control" } })</td>
                    </tr>
                }
            </tbody>
        </table>

        <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>
    
asked by anonymous 28.04.2016 / 02:05

1 answer

4
  

If I may, I'll use foreach for the answer.

Just do the same loop calculation, example:

 <tbody>
  @foreach(var item in Model.Detalhes)
  {
    //Não sei qual a regra que você precisa, então farei uma multiplicação, mas altere para sua encessidade.
    item.ValorCalculado = item.ValorPrincipal * item.ValorCalculado; 

      <tr>
          <td>@Html.EditorFor(a => item.ValorPrincipal, new { htmlAttributes = new { @class = "form-control" } })</td>
          <td>@Html.EditorFor(a => item.Percentual, new { htmlAttributes = new { @class = "form-control" } })</td>
          <td>@Html.EditorFor(a => item.ValorCalculado, new { htmlAttributes = new { @class = "form-control" } })</td>
      </tr>
  }
</tbody>

And from what I see, you're sending those values to a controller, I'd advise using BeginCollectionItem .

Now, if you want to continue using for , just follow the same logic:

<tbody>
    @for (int i = 0; i < Model.Detalhes.Count; i++)
    {
        Model.Detalhes[i].ValorCalculado = Model.Detalhes[i].ValorPrincipal * Model.Detalhes[i].Percentual;
        <tr>
            <td>@Html.EditorFor(a => a.Detalhes[i].ValorPrincipal, new { htmlAttributes = new { @class = "form-control" } })</td>
            <td>@Html.EditorFor(a => a.Detalhes[i].Percentual, new { htmlAttributes = new { @class = "form-control" } })</td>
            <td>@Html.EditorFor(a => a.Detalhes[i].ValorCalculado, new { htmlAttributes = new { @class = "form-control" } })</td>
        </tr>
    }
</tbody>
  

I did not understand the reason for you to do the calculation by means of a value typed in View . If the system should generate, it would be better to do this in server , the calculation would be safer.

Editing

  

Based on AP comments, I'll add an alternative response in jQuery.

To do what you want, let's use the .blur () event of jQuery to change the value of ValorCalculado whenever the value of a input is changed, this way:

$('input').blur(function(){

	var valorPrincipal = $(this).parent().parent().find('input[id*="ValorPrincipal"]').first().val();
	var percentual = $(this).parent().parent().find('input[id*="Percentual"]').first().val();
  var valorCalculado = valorPrincipal * percentual;
  
  if(valorCalculado != 0){
    $(this).parent().parent().find('input[id*="ValorCalculado"]').first().val(valorCalculado);
  }else{
  	$(this).parent().parent().find('input[id*="ValorCalculado"]').first().val('');
  }
});
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script><table><tr>ValorPrincipal</tr><tr>Percentual</tr><tr>ValorCalculado</tr><tbody><tr><td><inputid="ValorPrincipal1"/></td>
        <td><input id="Percentual1"/></td>
        <td><input id="ValorCalculado1"/></td>
    </tr>
       <tr>
        <td><input id="ValorPrincipal2"/></td>
        <td><input id="Percentual2"/></td>
        <td><input id="ValorCalculado2"/></td>
    </tr>
       <tr>
        <td><input id="ValorPrincipal3"/></td>
        <td><input id="Percentual3"/></td>
        <td><input id="ValorCalculado3"/></td>
    </tr>
  </tbody>
</table>

Example in JSFiddle.

Explaining what was done:

The explanation is quite simple. Whenever a input is changed and focus exits it, ie exiting input , the new value of ValorCalculado for the row in the table is calculated. To do this, you need to get the Primary and Percentage values of the same row. This line of code does this job:

var valorPrincipal = $(this).parent().parent().find('input[id*="ValorPrincipal"]').first().val();

Where $(this) is the element that input that the user edited, .parent().parent() is responsible for getting the tr of each line, .find('input[id*="ValorPrincipal"]').first().val() is responsible for fetching the element that contains ValorPrincipal strong> id (make sure you have this in the id, or change to what you think is best) and get its value. After doing this, simply replicate to the percentage, make the calculation of returning the value to the corresponding input , as shown in the example.

    
28.04.2016 / 04:07