How to Include an Item in an ICollection

2

I have a Person class that has a ICollection of Phone class. On the Person Maintenance screen I have a dataTable with the Telephones. There is a link to add a new phone, but I can not use @Html.DropDownLIstFor to request the type of phone (commercial, residential, mobile).

I'll try to be succinct.

public partial class PessoaModel
{
        public Guid PessoaID { get; set; }
        public string Nome { get; set; }
        public virtual ICollection<TelefoneModel> Telefone { get; set; }
}
    public partial class TelefoneModel
    {
        public Guid TelefoneID { get; set; }
        public string DDD { get; set; }
        public string Numero { get; set; }
        public string TipoTelefone { get; set; }
        public Guid PessoaID { get; set; }
    }

And my view looks like this:

@model GeoArea.Models.ViewModel.PessoaViewModel

<div class="panel panel-default" id="ITelefones">
    <div class="panel-heading">
        <h3 class="panel-title">Telefones</h3>
    </div>
    <div class="panel-body">
        <table id="tbTelefonePessoa" class="table table-striped table-hover">
            <thead>
                <tr>
                    <th>Tipo</th>
                    <th>Telefone</th>
                    <th>Opções</th>
                    <th></th>
                </tr>
            </thead>
            <tbody></tbody>
        </table>

        <div style="text-align:end">
            <a href="#" onclick="AcrescentarFone()">acrescentar  telefone</a>
        </div>
        <div id="acrescfone" class="hidden">
            @Html.ValidationSummary(true, "", new { @class = "text-danger" })
            <div class="form-group">
                <div class="col-md-6">
                    @Html.Label("Tipo", htmlAttributes: new { @class = "control-label" })
                    <div>
                        @Html.EditorFor(model => model.Telefone.FirstOrDefault().TipoTelefone.Nome, new { htmlAttributes = new { @class = "form-control" } })
                        @Html.ValidationMessageFor(model => model.Telefone, "", new { @class = "text-danger" })
                    </div>
                </div>
                <div class="col-md-6">
                    @Html.Label("Telefone", htmlAttributes: new { @class = "control-label" })
                    <div>
                        @Html.EditorFor(model => model.Telefone.FirstOrDefault().Numero, new { htmlAttributes = new { @class = "form-control" } })
                        @Html.ValidationMessageFor(model => model.Telefone, "", new { @class = "text-danger" })
                    </div>
                </div>
            </div>
        </div>
    </div>
</div>


<script type="text/javascript">
    $(document).ready(function () {
        var ex = document.getElementById('tbTelefonePessoa');
        if ($.fn.DataTable.fnIsDataTable(ex)) {
            $(ex).dataTable().fnClearTable();
            $(ex).dataTable().fnDraw();
        }
        oTelefonePessoa = $('#tbTelefonePessoa').DataTable({
            "bAutoWidth": false,
            "dom": '<"hidden"f><"hidden"l><"hidden"i><"hidden"p>t',
            "bPaginate": false,
            "bProcessing": true,
            "bStateSave": false,
            "bLengthChange": false,
            "sSearch": false,
            "destroy": true,
            "bServerSide": false,
            "bSort": true,
            "iDisplayLength": 10,
            "order": [[0, "asc"]],
            "language": {
                "url": ROOT + "Content/resources/Portuguese-Brasil.json"
            },
            "columnDefs": [
                {
                    'targets': 1,
                    "mData": 0,
                     mRender: function (data, type, row) {
                         var fone = row["Numero"];
                         fone = '(' + row["DDD"] + ') ' + fone.substr(0,(fone.length - 4)) + '-' + fone.substr((fone.length - 4),4);
                        return fone;
                    }
                },
                {
                    'targets': 2,
                    mRender: function(){
                        return '<a class="glyphicon glyphicon-edit">alterar</a>' + '   ' +
                               '<a class="glyphicon glyphicon-remove">excluir</a>';
                    }
                }
            ],
            "columns": [
                { "data": "TipoTelefone.Nome" },
                { "data": "DDD" },
                { "data": "Numero" }
            ]
        });

        var data = @Html.Raw(Newtonsoft.Json.JsonConvert.SerializeObject(Model.Telefone));
        if (data.length > 0) {
            $("#tbTelefonePessoa").dataTable().fnAddData(data);
        }
    });

    function AcrescentarFone(){
        $("#acrescfone").removeClass("hidden");
    };
</script>

I do not necessarily need to use dataTable but I found it easiest. Do you have any suggestions?

    
asked by anonymous 17.02.2016 / 22:07

2 answers

4

You can use BeginCollectionItem to accomplish this. I answer this a few times here .

To use it you should install the package via Nuget with the following command:

  

Install-Package BeginCollectionItem

After that, we'll add a Action to your controller to add a new phone to the Person, like this:

public ActionResult GetNewTelefone()
    {
        var telefone = new Telefone
        {
            TelefoneId = Guid.NewGuid()
        };

        return PartialView("_Telefone", telefone);
    }

In this way we are creating a new phone and returning it in a PartialView , which you can do as follows:

@model WebApplication1.Models.Telefone


@using (Html.BeginCollectionItem("Telefones"))
{
    <div class="form-group">
        @Html.HiddenFor(model => model.TelefoneId)
        @Html.LabelFor(model => model.DDD, htmlAttributes: new { @class = "control-label col-md-2" })
        <div class="col-md-4">
            @Html.EditorFor(model => model.DDD, new { htmlAttributes = new { @class = "form-control" } })
            @Html.ValidationMessageFor(model => model.DDD, "", new { @class = "text-danger" })
        </div>
        @Html.LabelFor(model => model.Numero, htmlAttributes: new { @class = "control-label col-md-2" })
        <div class="col-md-4">
            @Html.EditorFor(model => model.Numero, new { htmlAttributes = new { @class = "form-control" } })
            @Html.ValidationMessageFor(model => model.Numero, "", new { @class = "text-danger" })
        </div>
    </div>

}

Within @using (Html.BeginCollectionItem("Telefones")) you put the name of soa ICollection , which in your case would be Phone .

Once this is done, we only need to make a Ajax request and return PartialView to the desired location, like this:

<script>
        $('#add-telefone').click(function () {
            $.ajax({
                url: '@Url.Action("GetNewTelefone","Pessoa")',
                type: 'POST',
                success: function (data) {
                    $('#new-telefone').append(data);
                }
            });
            return false;
        });
</script>

Script is making a request by clicking the button with id=add-telefone and returning PartialView to div that has id=new-telefone .

Once you've done this, simply click on save normally the list will be sent to your controller.

And in your controller you save the phone normally, like this:

[HttpPost]
    [ValidateAntiForgeryToken]
    public ActionResult Edit([Bind(Include = "PessoaId,Nome,Telefones")] Pessoa pessoa)
    {
        if (ModelState.IsValid)
        {

            if (pessoa.Telefones != null && pessoa.Telefones.Any())
            {
                foreach (var telefone in pessoa.Telefones)
                {
                    telefone.PessoaId = pessoa.PessoaId;
                    db.Telefone.Add(telefone);
                }
            }

            db.Entry(pessoa).State = EntityState.Modified;
            db.SaveChanges();
            return RedirectToAction("Index");
        }
        return View(pessoa);
    }
  

If you are using [Bind (Include)], do not forget to add ICollection<Telefone> Telefone to it, otherwise the value will null.

Any questions, I've done a sample project using this package. You can download to understand better if you want. It is in my GitHub .

    
19.02.2016 / 13:15
0

An ICollection type is just the sampling of a collection (readonly), being List, an IList implementation, that comes from ICollection, along with list manipulation (eg, Add, Remove, Clear) methods.

Use as follows:

public virtual List<TelefoneModel> Telefone { get; set; }
    
18.02.2016 / 23:07