Customer search by Name/Phone/Cpf Javascript/C#

Asked

Viewed 842 times

1

I have a page that lists client, and I need to do a name search, I have the method that does the problem research and how to integrate it with the front-end, I looked for examples on the internet but I think my lack of notion did not let me understand any example.

Here is the method that lists customers in the C#:

      public ActionResult Index(int PaginaAtual){

        ClienteModel clienteModel = new ClienteModel();
        clienteModel.PaginaAtual = PaginaAtual;
        int LojistaId = Convert.ToInt32(User.Identity.Name);
        int[] lojaId = this.LojaServico.GetMany(l => l.LojistaId == LojistaId).Select(l => new int[] { l.LojaId, l.Clientes.Count}).FirstOrDefault();
        int LojaId = lojaId[0];
        if(lojaId != null){
            List<ClienteLoja> clientes = this.ClienteLojaServico.GetMany(x => x.LojaId == LojaId).OrderByDescending(x => x.DataCadastro).Skip(PaginaAtual*10).Take(10).ToList();

            clienteModel.Clientes = clientes;

            clienteModel.qtdeClientes = lojaId[1];  
            //model.LojaId = loja.LojaId;
            return View(clienteModel);
        }else{
          return RedirectToAction("Index", "Home", new { area = "" });
        }
    }

And this here is the method that would make the search :

  public ActionResult AjaxHandler(JQueryDataTableParamModel param, string LojaId)
    {
        int idLoja = Convert.ToInt32(SystemCriptografia.ToDescriptografaQueryString(LojaId));
        //int LojistaId = Convert.ToInt32(User.Identity.Name);
        //var Loja = this.LojaServico.GetMany(l => l.LojaId == idLoja && l.LojistaId == LojistaId).Select(l => new { l.LojaId, l.Clientes }).FirstOrDefault();
        var Loja = this.LojaServico.GetMany(l => l.LojaId == idLoja).Select(l => new { l.LojaId, l.Clientes }).FirstOrDefault();

        IEnumerable<Cliente> totalClientes = new List<Cliente>();
        if (Loja != null)
        {
            totalClientes = Loja.Clientes.Where(c => c.Cliente.Ativo == true && c.Tipo == (byte)enumTipoVinculo.APP).OrderBy(m => m.Cliente.Mensagens.Where(x => x.LojaId == idLoja && x.OrigemId == 0 && x.Visualizada == false).Select(p => p.DataEnvio)).Select(a => a.Cliente);
        }

        IEnumerable<Cliente> filtroCliente;


        if (!string.IsNullOrEmpty(param.sSearch))
        {
            string busca = param.sSearch.ToLower();
            filtroCliente = ClienteServico.GetAll().Where(x => x.Nome.Contains(busca) ||
                           x.Email.Contains(busca) || x.Telefone.Contains(busca));
        }
        else
        {
            filtroCliente = totalClientes;
        }
        var sortColumnIndex = Convert.ToInt32(Request["iSortCol_0"]);
        Func<Cliente, string> orderingFunction;
        switch (sortColumnIndex)
        {
            case 1:
                orderingFunction = (c => c.Email);
                break;
            case 2:
                orderingFunction = (c => c.Telefone);
                break;
            default:
                orderingFunction = (c => c.Nome);
                break;
        }

        var sortDirection = Request["sSortDir_0"]; // asc or desc
        if (sortDirection == "asc")
            filtroCliente = filtroCliente.OrderBy(orderingFunction);
        else
            filtroCliente = filtroCliente.OrderByDescending(orderingFunction);

        var displayedClientes = filtroCliente.Skip(param.iDisplayStart).Take(param.iDisplayLength);
        var result = from c in displayedClientes select new[] { c.Nome, c.Email, c.Telefone, "perfilFbLink" };

        return Json(new
        {
            sEcho = param.sEcho,
            iTotalRecords = totalClientes.Count(),
            iTotalDisplayRecords = totalClientes.Count(),
            aaData = result
        },
                    JsonRequestBehavior.AllowGet);
    }
}

This last method was already ready and was done by someone else who no longer works here, so I’m in a lot of trouble.

Here is my page showing the customers:

<div class="row">
<div class="col-xs-12">
    <div class="box">
        <!-- /.box-header -->
        <div class="box-body">
            <div class="row">
                <div class="col-sm-5">

                </div>
                <div class="mailbox-controls" style="margin-right:20px;margin-bottom:10px">


                    <div class="pull-right" >
                        @QntdeInicial.ToString() - @QntdeFinal.ToString()
                        <div class="btn-group">
                            <a id="previousPage" href="@Url.Action("Index", "Cliente", new {PaginaAtual = @Model.PaginaAtual -1 , Area="Lojista"})">
                                <i class="btn btn-default btn-sm  fa fa-chevron-left"></i>
                            </a>
                            <a id="nextPage" href="@Url.Action("Index", "Cliente", new {PaginaAtual = @Model.PaginaAtual +1 , Area="Lojista"}) ">
                                <i class="btn btn-default btn-sm  fa fa-chevron-right">
                                </i>
                            </a>
                        </div>
                    </div>
                    <!-- /.pull-right -->
                </div>
            </div>
            <div class="dataTables_wrapper form-inline dt-bootstrap" id="example2_wrapper">

                <div class="col-sm-12">
                    <table aria-describedby="example2_info" role="grid" id="example2" class="table table-bordered table-hover dataTable">
                        <thead>
                            <tr role="row">
                                <th aria-label="Rendering engine: activate to sort column descending" aria-sort="ascending" colspan="1" rowspan="1" aria-controls="example2" tabindex="0" class="sorting_asc">
                                </th>
                                <th aria-label="" aria-sort="ascending" colspan="1" rowspan="1" aria-controls="example2" tabindex="0" class="sorting_asc">Nome</th>
                                <th aria-label="" colspan="1" rowspan="1" aria-controls="example2" tabindex="0" class="sorting">Email</th>
                                <th aria-label="" colspan="1" rowspan="1" aria-controls="example2" tabindex="0" class="sorting">Cidade</th>
                                <th aria-label="" colspan="1" rowspan="1" aria-controls="example2" tabindex="0" class="sorting">Telefone</th>                 
                                <th aria-label="" colspan="1" rowspan="1" aria-controls="example2" tabindex="0" class="sorting">Avaliacão</th>
                                <th aria-label="" colspan="1" rowspan="1" aria-controls="example2" tabindex="0" class="sorting">Ações</th>

                            </tr>
                        </thead>
                        <tbody id="tabela-clientes">
                            @foreach (ClienteLoja cli in Model.Clientes)
                            {
                                <tr class="odd" role="row">
                                    <td align="center" class="sorting_1">
                                        <img src="/Content/imagens/principais/no-user.png" alt="Product Image" style="height:40px">
                                    </td>
                                    <td>@(!String.IsNullOrEmpty(cli.Cliente.Nome) ? cli.Cliente.Nome : "Usuario nao cadastrado")</td>
                                    <td>@(!String.IsNullOrEmpty(cli.Cliente.Email) ? cli.Cliente.Email : "Email nao cadastrado")</td>
                                    <td>@if (cli.Cliente.EnderecoResidencial != null) { cli.Cliente.EnderecoResidencial.Cidade.Nome.ToString(); } else { Write("--"); } </td>
                                    <td>@(!String.IsNullOrEmpty(cli.Cliente.Telefone) ? cli.Cliente.Telefone : "Telefone nao cadastrado")</td>
                                    <td>@cli.Avaliacao.ToString()</td>
                                    <td align="left">
                                        <a class="openMyModal btn btn-info" data-id='{"nome": "@cli.Cliente.Nome","email": "@cli.Cliente.Email","pessoaId": "@cli.Cliente.PessoaId", "telefone": "@cli.Cliente.Telefone","perfilFace":"@cli.Cliente.PerfilFace" }' title="Ver informacoes do usuario" href="#myModal" data-toggle="modal" data-parametro="" data-target="#modalCliente"><i class="fa fa-user openMyModal" data-widget=""></i></a>

                                        <a class="btn btn-warning" href="@Url.Action("Conversa", "Mensagem", new {ClienteId = cli.ClienteId, Area="Lojista"})">
                                            <i class=" fa fa-envelope" title="Ver conversa com este usuario"></i>
                                        </a>

                                        @if (!String.IsNullOrEmpty(cli.Cliente.PerfilFace))
                                        {
                                            if (cli.Cliente.PerfilFace != "Nulo")
                                            {
                                                <a target="_blank" [email protected] class="btn btn-social-icon btn-facebook">
                                                    <i class="fa fa-facebook">
                                                    </i>
                                                </a>
                                            }
                                        }
                                    </td>
                                </tr>
                            }
                        </tbody>
                    </table>
                </div>
            </div>

I find it hard for anyone to be able to answer exactly what I want because I’m very specific, but if someone can shed some light on it, or an explanation of how these searches can be done, it would help me a lot, because I can’t even research the subject I’m getting.

Thank you very much!

  • You are using the plugin Datatable?

  • I realized that in the old method Datatable was used, so the method is that way, but in the old method it brought ALL clients at once, now this paginated straight. So I had the idea to do a search by name memso, with another method in the C# controller that brings this same page only that only the filter clients, would not have any update in real time, but would be more usable.

  • Look this article. It explains how to do what you want and has the download code. However, the evening I work out a complete answer.

  • I’m taking a look at the article but will already give time to finish, if you can post an answer I thank you, tomorrow I will try to implement according to the article or your reply, anyway thank you very much for your help .

1 answer

1


Come on.

The first thing will be "type" the attributes of Datatables. For this, we will create the Viewmodel DatatablesViewModel.

Datatablesviewmodel.Cs

using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;

///This view model class has been referred from example created by Marien Monnier at Soft.it. All credits to Marien for this class
namespace MVCDatatableApp.Models
{
    /// <summary>
    /// A full result, as understood by jQuery DataTables.
    /// </summary>
    /// <typeparam name="T">The data type of each row.</typeparam>
    public class DTResult<T>
    {
        /// <summary>
        /// The draw counter that this object is a response to - from the draw parameter sent as part of the data request.
        /// Note that it is strongly recommended for security reasons that you cast this parameter to an integer, rather than simply echoing back to the client what it sent in the draw parameter, in order to prevent Cross Site Scripting (XSS) attacks.
        /// </summary>
        public int draw { get; set; }

        /// <summary>
        /// Total records, before filtering (i.e. the total number of records in the database)
        /// </summary>
        public int recordsTotal { get; set; }

        /// <summary>
        /// Total records, after filtering (i.e. the total number of records after filtering has been applied - not just the number of records being returned for this page of data).
        /// </summary>
        public int recordsFiltered { get; set; }

        /// <summary>
        /// The data to be displayed in the table.
        /// This is an array of data source objects, one for each row, which will be used by DataTables.
        /// Note that this parameter's name can be changed using the ajaxDT option's dataSrc property.
        /// </summary>
        public List<T> data { get; set; }
    }

    /// <summary>
    /// The additional columns that you can send to jQuery DataTables for automatic processing.
    /// </summary>
    public abstract class DTRow
    {
        /// <summary>
        /// Set the ID property of the dt-tag tr node to this value
        /// </summary>
        public virtual string DT_RowId
        {
            get { return null; }
        }

        /// <summary>
        /// Add this class to the dt-tag tr node
        /// </summary>
        public virtual string DT_RowClass
        {
            get { return null; }
        }

        /// <summary>
        /// Add this data property to the row's dt-tag tr node allowing abstract data to be added to the node, using the HTML5 data-* attributes.
        /// This uses the jQuery data() method to set the data, which can also then be used for later retrieval (for example on a click event).
        /// </summary>
        public virtual object DT_RowData
        {
            get { return null; }
        }
    }

    /// <summary>
    /// The parameters sent by jQuery DataTables in AJAX queries.
    /// </summary>
    public class DTParameters
    {
        /// <summary>
        /// Draw counter.
        /// This is used by DataTables to ensure that the Ajax returns from server-side processing requests are drawn in sequence by DataTables (Ajax requests are asynchronous and thus can return out of sequence).
        /// This is used as part of the draw return parameter (see below).
        /// </summary>
        public int Draw { get; set; }

        /// <summary>
        /// An array defining all columns in the table.
        /// </summary>
        public DTColumn[] Columns { get; set; }

        /// <summary>
        /// An array defining how many columns are being ordering upon - i.e. if the array length is 1, then a single column sort is being performed, otherwise a multi-column sort is being performed.
        /// </summary>
        public DTOrder[] Order { get; set; }

        /// <summary>
        /// Paging first record indicator.
        /// This is the start point in the current data set (0 index based - i.e. 0 is the first record).
        /// </summary>
        public int Start { get; set; }

        /// <summary>
        /// Number of records that the table can display in the current draw.
        /// It is expected that the number of records returned will be equal to this number, unless the server has fewer records to return.
        /// Note that this can be -1 to indicate that all records should be returned (although that negates any benefits of server-side processing!)
        /// </summary>
        public int Length { get; set; }

        /// <summary>
        /// Global search value. To be applied to all columns which have searchable as true.
        /// </summary>
        public DTSearch Search { get; set; }

        /// <summary>
        /// Custom column that is used to further sort on the first Order column.
        /// </summary>
        public string SortOrder
        {
            get
            {
                return Columns != null && Order != null && Order.Length > 0
                    ? (Columns[Order[0].Column].Data + (Order[0].Dir == DTOrderDir.DESC ? " " + Order[0].Dir : string.Empty))
                    : null;
            }
        }

    }

    /// <summary>
    /// A jQuery DataTables column.
    /// </summary>
    public class DTColumn
    {
        /// <summary>
        /// Column's data source, as defined by columns.data.
        /// </summary>
        public string Data { get; set; }

        /// <summary>
        /// Column's name, as defined by columns.name.
        /// </summary>
        public string Name { get; set; }

        /// <summary>
        /// Flag to indicate if this column is searchable (true) or not (false). This is controlled by columns.searchable.
        /// </summary>
        public bool Searchable { get; set; }

        /// <summary>
        /// Flag to indicate if this column is orderable (true) or not (false). This is controlled by columns.orderable.
        /// </summary>
        public bool Orderable { get; set; }

        /// <summary>
        /// Specific search value.
        /// </summary>
        public DTSearch Search { get; set; }
    }

    /// <summary>
    /// An order, as sent by jQuery DataTables when doing AJAX queries.
    /// </summary>
    public class DTOrder
    {
        /// <summary>
        /// Column to which ordering should be applied.
        /// This is an index reference to the columns array of information that is also submitted to the server.
        /// </summary>
        public int Column { get; set; }

        /// <summary>
        /// Ordering direction for this column.
        /// It will be dt-string asc or dt-string desc to indicate ascending ordering or descending ordering, respectively.
        /// </summary>
        public DTOrderDir Dir { get; set; }
    }

    /// <summary>
    /// Sort orders of jQuery DataTables.
    /// </summary>
    public enum DTOrderDir
    {
        ASC,
        DESC
    }

    /// <summary>
    /// A search, as sent by jQuery DataTables when doing AJAX queries.
    /// </summary>
    public class DTSearch
    {
        /// <summary>
        /// Global search value. To be applied to all columns which have searchable as true.
        /// </summary>
        public string Value { get; set; }

        /// <summary>
        /// true if the global filter should be treated as a regular expression for advanced searching, false otherwise.
        /// Note that normally server-side processing scripts will not perform regular expression searching for performance reasons on large data sets, but it is technically possible and at the discretion of your script.
        /// </summary>
        public bool Regex { get; set; }
    }
}

After that, we will create the class responsible for filtering the values according to the column. Let’s call this class ResultSet.cs.

Resultset.Cs

  public class ResultSet
    {
        public List<Customer> GetResult(string search, string sortOrder, int start, int length, List<Customer> dtResult, List<string> columnFilters)
        {
            return FilterResult(search, dtResult,columnFilters).SortBy(sortOrder).Skip(start).Take(length).ToList();
        }

        public int Count(string search, List<Customer> dtResult, List<string> columnFilters)
        {
            return FilterResult(search, dtResult, columnFilters).Count();
        }

        private IQueryable<Customer> FilterResult(string search, List<Customer> dtResult, List<string> columnFilters)
        {
            IQueryable<Customer> results = dtResult.AsQueryable();

            results = results.Where(p => (search == null || (p.Name != null && p.Name.ToLower().Contains(search.ToLower()) || p.City != null && p.City.ToLower().Contains(search.ToLower())
                || p.Postal != null && p.Postal.ToLower().Contains(search.ToLower()) || p.Email != null && p.Email.ToLower().Contains(search.ToLower()) || p.Company != null && p.Company.ToLower().Contains(search.ToLower()) || p.Account != null && p.Account.ToLower().Contains(search.ToLower())
                || p.CreditCard != null && p.CreditCard.ToLower().Contains(search.ToLower()))) 
                && (columnFilters[0] == null || (p.Name != null && p.Name.ToLower().Contains(columnFilters[0].ToLower())))
                && (columnFilters[1] == null || (p.City != null && p.City.ToLower().Contains(columnFilters[1].ToLower())))
                && (columnFilters[2] == null || (p.Postal != null && p.Postal.ToLower().Contains(columnFilters[2].ToLower())))
                && (columnFilters[3] == null || (p.Email != null && p.Email.ToLower().Contains(columnFilters[3].ToLower())))
                && (columnFilters[4] == null || (p.Company != null && p.Company.ToLower().Contains(columnFilters[4].ToLower())))
                && (columnFilters[5] == null || (p.Account != null && p.Account.ToLower().Contains(columnFilters[5].ToLower())))
                && (columnFilters[6] == null || (p.CreditCard != null && p.CreditCard.ToLower().Contains(columnFilters[6].ToLower())))
                );

            return results;
        }
    }

Now we have almost everything prepared, so let’s go to our controller.

Homecontroller

 public JsonResult DataHandler(DTParameters param)
    {
        try
        {
            var dtsource = new List<Customer>();
            using (dataSetEntities dc = new dataSetEntities())
            {
                dtsource = dc.Customers.ToList();
            }

            List<String> columnSearch = new List<string>();

            foreach (var col in param.Columns)
            {
                columnSearch.Add(col.Search.Value);
            }

            List<Customer> data = new ResultSet().GetResult(param.Search.Value, param.SortOrder, param.Start, param.Length, dtsource, columnSearch);
            int count = new ResultSet().Count(param.Search.Value, dtsource, columnSearch);
            DTResult<Customer> result = new DTResult<Customer>
            {
                draw = param.Draw,
                data = data,
                recordsFiltered = count,
                recordsTotal = count
            };
            return Json(result);
        }
        catch (Exception ex)
        {
            return Json(new { error = ex.Message });
        }
    }

You can change the search to the way you want, but the important thing is to return the requested data on the server-side, as per the Datatables DOC.

In our View, just use the Datatables with server-side, in this way:

$(document).ready(function () {

    $('#datatab tfoot th').each(function () {
        $(this).html('<input type="text" />');
    });

    var oTable = $('#datatab').DataTable({
        "serverSide": true,
        "ajax": {
            "type": "POST",
            "url": '/Home/DataHandler',
            "contentType": 'application/json; charset=utf-8',
            'data': function (data) { return data = JSON.stringify(data); }
        },
        "dom": 'frtiS',
        "scrollY": 500,
        "scrollX": true,
        "scrollCollapse": true,
        "scroller": {
            loadingIndicator: false
        },
        "processing": true,
        "paging": true,
        "deferRender": true,
        "columns": [
       { "data": "Name" },
       { "data": "City" },
       { "data": "Postal" },
       { "data": "Email" },
       { "data": "Company" },
       { "data": "Account" },
       { "data": "CreditCard" }
        ],
        "order": [0, "asc"]

    });

    oTable.columns().every(function () {
        var that = this;

        $('input', this.footer()).on('keyup change', function () {
            that
                .search(this.value)
                .draw();
        });
    });

});

If you want to understand better, there is that question and this one here who speak of the same subject.

If you want the full code, you can see the repository on Github here.

And a more detailed explanation, you can see the article from where I sought this code.

Browser other questions tagged

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