1

I have a store of products. Each product has an Id, a price and a name. When a person clicks on the "Buy" button, a form opens so they can fill up their address, their email and their name. When the person clicks on submit, I do an AJAX call to the controller sending the information.

I have tried several solutions but I can't find one that works :/ What I want to do is send the email, address, name and an array of products.

carrinho.js (shoppingcart.js):

function go(nr) {
$('.confirm').toggleClass('comein');
$('#shoppingCart').toggle("fade");

var i = 0;

$("div #cartItems > .itemrow").each(function () {

    var nome = $(this).find("h3").text();
    var preco = $(this).find(".price").text();
    var id = $(this).find(".id").text();

    $("#form").append("" +
        "<input type='hidden' name='[" + i + "].produtos' value='" + nome + "' id='nomeenc' readonly /> " +
        "<input type='hidden' name='[" + i + "].produtos' value='" + id + "' id='idenc' readonly />" +
        "<input type='hidden' name='[" + i + "].produtos' value='" + preco + "' id='precoenc' readonly />");

    $(".messageSuccess button .removeItem").remove();
    $(".messageSuccess img").remove();
    i = i + 1;
});

$("form").on("submit", function (e) {
    e.preventDefault();

    var form = $(this);

    $.ajax({
        type: 'POST',
        url: '/Compra/Encomenda',
        data: form.serialize(),
        success: function () {
            $('.confirm').toggleClass('comein');
            $('#emptyCart').fadeToggle(nr);
            $('.messageSuccess').toggleClass('comein');
        }
    });
});
}

Controller:

public ActionResult Encomenda(SubmitFormModel produtos)
    {
        var model = produtos;

        string path = Server.MapPath("~/files");
        DateTime time = DateTime.Now;
        string date = time.ToString("yyyy-MM-dd-hh-mm-ss");

        XmlSerializer serializer = new XmlSerializer(typeof(SubmitFormModel));
        StreamWriter writer = new StreamWriter(path + "\\" + date + ".xml");
        serializer.Serialize(writer, model);
        writer.Close();

        return PartialView(model);
    }

SubmitFormModel.cs:

namespace Loja.Models
{
[Serializable]
public class SubmitFormModel
{
public List<Produto> Produtos { get; set; } //produto = product
    public string Morada { get; set; } //address
    public string Email { get; set; }
    public string Nome { get; set; } //name
}

}

Produto.cs:

namespace Loja.Models
{
[Serializable]
public class Produto
{
    public int Id { get; set; }
    public string Nome_produto { get; set; } //product_name
    public string Tipo { get; set; } //type
    public string Detalhes { get; set; } //details
    public string Imagem { get; set; } //image
    public int Preco { get; set; } //price
    public string ImgArt { get; set; }
}
}

Form:

<form action="/Compra/Encomenda" method="post" id="form">
    <label class="field a-field a-field_a3 page__field">
        <input class="field__input a-field__input" placeholder="ex. Rodrigo Barradinhas" required name="nome" type="text" id="nome_cliente">
        <span class="a-field__label-wrap">
            <span class="a-field__label">Nome completo</span>
        </span>
    </label>

    <label class="field a-field a-field_a3 page__field">
        <input class="field__input a-field__input" placeholder="ex. [email protected]" required name="email" type="text" id="email">
        <span class="a-field__label-wrap">
            <span class="a-field__label">E-mail</span>
        </span>
    </label>

    <label class="field a-field a-field_a3 page__field">
        <input class="field__input a-field__input" placeholder="ex. Rua x Nºy 1167-004 Lisboa" required name="morada" type="text" id="morada">
        <span class="a-field__label-wrap">
            <span class="a-field__label">Morada</span>
        </span>
    </label>

    <input type='submit' name='confirmar' value='confirmar' class='event' data-main='Compra' />
    <br /><br />
</form>

I wanted to get in my controller something like: https://i.sstatic.net/3nJMv.jpg

and an array of products

9
  • 1
    Shouldn't it be name='produtos[" + i + "].name' instead of name='[" + i + "].produtos'? With one input per property like you do but with name equals to produtos[" + i + "].**propertyName**. Commented May 22, 2019 at 12:06
  • Also in the each method you're setting the same id to several input which is not a good idea as ids should be unique. I'd suggest you remove then if you don't need them. Commented May 22, 2019 at 12:13
  • @colinD About the ids, I have already remove them, that is from before, when I didn't had a foreach() and it was a single product Commented May 22, 2019 at 12:55
  • @colinD I tried what you suggested and this is what I get: imgur.com/a/WRwmgwP Commented May 22, 2019 at 12:58
  • It should be produtos[" + i + "].nome_produto instead of nome to match the Produto model but other than that it's strange that the other properties aren't set anymore. Commented May 22, 2019 at 13:03

2 Answers 2

1

Another way of doing this. I always find dealing with JSON simpler than with multiple input attributes.

  1. First of all I will recommend is instead of taking values from text of HTML, you should attach **data-*** attributes. Let's say, your HTML is something similar to
<div id="cartItems">
    <div class="itemrow">
        ...
        <h3>Samsung Mobile S10</h3>
        <span class="price">350</span>
        <input type="hidden" class="id" value="34">
        ...
    </div>
    <div class="itemrow">
        ...
        <h3>IPhone 7s</h3>
        <span class="price">650</span>
        <input type="hidden" class="id" value="38">
        ...
    </div>
</div>

Instead of this, you should create an HTML similar to this

<div id="cartItems">
    <div class="itemrow" data-pid="34" data-price="350" data-name="Samsung Mobile S10">
        ...
        <h3>Samsung Mobile S10</h3>
        <span class="price">350</span>
        <input type="hidden" class="id" value="34">
        ...
    </div>
    <div class="itemrow" data-pid="38" data-price="650" data-name="IPhone 7s">
        ...
        <h3>IPhone 7s</h3>
        <span class="price">650</span>
        <input type="hidden" class="id" value="38">
        ...
    </div>
</div>
  1. You should look to create a JSON array string of all the products in the cart. Create ONE hidden control and place your products JSON there.
<input type="hidden" id="allproductsjson" value="">

Your function can be similar to

$("form").on("submit", function (e) {
    e.preventDefault();
    createProductsJSON();
    var form = $(this);
    $.ajax({
        type: 'POST',
        url: '/Compra/Encomenda',
        data: form.serialize(),
        success: function () {
            $('.confirm').toggleClass('comein');
            $('#emptyCart').fadeToggle(nr);
            $('.messageSuccess').toggleClass('comein');
        }
    });
});

function createProductsJSON() {
    var jsonObj = [];
    $("#cartItems > .itemrow").each(function() {
        var pId = $(this).attr("data-pid");
        var pName = $(this).attr("data-name);
        var pPrice = $(this).attr("data-price);

        var item = {}
        item ["id"] = pId;
        item ["name"] = pName;
        item ["price"] = pPrice;

        jsonObj.push(item);
    });

    console.log(jsonObj);
    $("#allproductsjson").val(JSON.stringify(jsonObj));
}
  1. In the controller, you will get just one field and you can simply do a parsejson to get the output.

Let me know if this works for you.

Sign up to request clarification or add additional context in comments.

1 Comment

Hello @Jay Pagnis, I apreciate your comment, thank you so much. I will try this in a future project, but again, thank you very much! I just finished 12 grade and im doing an internship in a company and I'm still learning :) Hope to be a good programmer one day
0

It was a problem with var names :/

Looks like it's a variable name problem that occurs during binding. Could you change the variable name in the method public ActionResult Encomenda(SubmitFormModel produtos) and see it if work? For example Encomenda(SubmitFormModel formModel). – colinD

It worked. Thank you

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.