Home > Back-end >  When using Datatable.js, How do I send the number of the page I clicked back to my back-end? (with s
When using Datatable.js, How do I send the number of the page I clicked back to my back-end? (with s

Time:11-17

So long story short, I'm trying to show a table with MVC structure and show it with Datatable.js. Since the DB here can be quite huge, I thus want to make the most of data processing stay in my back-end, which means the only time it actually response is when users click the supposed page. My current code looks like this:

My controller:

public ActionResult Index() {
      //To send data to my drop-down list. Currently work as intended
      M_BussinessLogics Builder = new M_BussinessLogics();
      List<VM_PublicatorInfo> Dlist = Builder.GetPublicationList();
      SelectList P_List = new SelectList(Dlist, "PublicationID", "DataDesc");
      ViewBag.TheList = P_List;

      return View();
    }
    
    //Response after user selected a certain option from the drop-down list 
    [HttpPost]
    public ActionResult index(string PubID, int? draw, int? start, int? pageNumber, int length=10) {

      try {

        if (pageNumber == null) {
           pageNumber = 0;
        }
      
      //Model for data digging (with SQL), should be irrelevant to my problem here 
      M_BussinessLogics FormBuilder = new M_BussinessLogics();
      List<VM_Column> Form_Col_List = FormBuilder.GetTablesInfo(PubID, pageNumber);
      
      //Model to get the whole counts of data so Datatable.js knows how many pages are there, should be irrelevant to my problem here 
      int CountTest = FormBuilder.GetDataCount(PubID);

      List<VM_PublicatorInfo> Dlist = FormBuilder.GetPublicationList();
      SelectList P_List = new SelectList(Dlist, "PublicationID", "DataDesc");
      ViewBag.TheList = P_List;



      return Json(new {
        draw = draw,
        
        //The following three lines work, but not entirely fit into my actual goal 
        //recordsTotal = Form_Col_List.Count(),
        //recordsFiltered = Form_Col_List.Count(),
        //data = Form_Col_List.Skip(start ?? 0).Take(length).ToList()
        
        recordsTotal = CountTest,
        recordsFiltered = CountTest,
        data = Form_Col_List
      }, JsonRequestBehavior.AllowGet);

      } 
      catch (Exception) {
        return null;
      }  
    }

My viewmodel:

//For table
public class VM_Column 
  {
    public int No { get; set;}

    public int ShowArtiID { get; set;}

    public int ID { get; set; }

    public string PublicationID  { get; set;}

    public int Review { get; set; }

    public string Authur { get; set; }

    public string CreateDate{ get;set;}
  }

//For drop-down list
public class VM_PublicatorInfo {
    public string PublicationID { get;set; }

    public string DataDesc  { get;set; }
  }

//For total counts of data in the supposed table
public class VM_TablePage {
    public int TotalCount{ get;set;} 
  }

My view/front-end:

@{
  ViewBag.Title = "Publishing Data";
  AjaxOptions ajaxOptions = new AjaxOptions {
    HttpMethod = "POST",
    InsertionMode = InsertionMode.Replace,
    UpdateTargetId = "Displayer"
  };
}

<h2>Publisher Data</h2>

<div id="pagenum">
  <p id="page"></p>
</div>

<!--Drop Down List-->
<div id="DropDownList">
 @Html.DropDownList("PubID", ViewBag.TheList as SelectList, "Please choose a publisher", new { @class = "Droplist" })
    <input id="P_Btn" class="btn-default" type="submit" />
    <br />


</div>

<!--Partial-->
<div id="Displayer" class="center-block" >
  <table id=TheTable style="visibility:hidden">
    <thead>
      <tr>
        <th>No</th>
        <th>ShowArtiID</th>
        <th>ID</th>
        <th>PublicationID</th>
        <th>Review</th>
        <th>Authur</th>
        <th>CreateDate</th>
      </tr>
    </thead>
  </table>
</div>



@section scripts{
  //I hid the Datatable.js reference in my _Layout
  <script>

    let PathRoot='@Url.Content("~/")';
    
    $('#P_Btn').click(function () {
      if ($('#PubID').val()=="") {
        alert("Please choose a publisher");
        return false;
      }

      else
      //Re-drawing table every time user send publisher's ID 
      $('#Displayer').empty();
      $('#Displayer').append("<table id=" "TheTable" ">"
         "<thead>"
         "<tr>"
         "<th>No</th>"
         "<th>ShowArtiID</th>"
         "<th>ID</th>"
         "<th>PublicationID</th>"
         "<th>Review</th>"
         "<th>Authur</th>"
         "<th>CreateDate</th>"
         "</tr>"
         "</thead >"
         "</table >");

    
      let table = $('#TheTable').DataTable({
        "processing": true,
        "serverSide": true,
        "ajax": {
          url: PathRoot   'Home/index?PubID='   $('#PubID').val(),
          type: "POST",
          error: function (jqXHR, exception) {
            alert(jqXHR);
          }
          },
        "columns": [
          { "data": "No", "bSortable": true },
          { "data": "ShowArtiID", "bSortable": true},
          { "data": "ID", "bSortable": true },
          { "data": "PublicationID", "bSortable": true, "bSearchable": true},
          { "data": "Review", "bSortable": true, "bSearchable": true},
          { "data": "Authur", "bSortable": true, "bSearchable": true },
          { "data": "CreateDate", "bSortable": true, "bSearchable": true }
        ],
        "bLengthChange":false
        
        //Doesn't seem to work?
        //"retrive":true,
        //"destory":true
      })
    });
  </script>

So my current problems are:

  1. I don't know how to send the page number that user selected to my back-end so it can dig the data out.

  2. I don't know why the "destroy" and "retrive" of Datatable.js doesn't seem to work as intended, so I have to re-create the table whenever a new ID is send out to avoid crush. How may I fix this?

CodePudding user response:

Regarding your question about page number, I had the same problem and created model which handles datatable request schema:

public class DataTablePostModel
{
    public int page { get { return GetPage(); } }
    public int draw { get; set; }
    public int start { get; set; }
    public int length { get; set; }
    public List<Column> columns { get; set; }
    public Search search { get; set; }
    public List<Order> order { get; set; }
    private int GetPage()
    {
        if (this.start == 0)
        {
            return 0;
        }
        else
        {
            return start / length;
        }
    }
}

public class Column
{
    public string data { get; set; }
    public string name { get; set; }
    public bool searchable { get; set; }
    public bool orderable { get; set; }
    public Search search { get; set; }
}

public class Search
{
    public string value { get; set; }
    public string regex { get; set; }
}

public class Order
{
    public int column { get; set; }
    public string dir { get; set; }
}

Then in controller you can use it like:

public ActionResult LoadProducts(DataTablePostModel model)
{
}

Answering you question in comment you can do something like this, because you intend to pass additional parameter to controller:

 let table = $('#TheTable').DataTable({
    "processing": true,
    "serverSide": true,
    "ajax": {
      url:'Home/index',
      data: function (d) {
            d.pubId = $('#PubID').val();
      }
      type: "POST",
      error: function (jqXHR, exception) {
        alert(jqXHR);
      }
      },
    "columns": [
      { "data": "No", "bSortable": true },
      { "data": "ShowArtiID", "bSortable": true},
      { "data": "ID", "bSortable": true },
      { "data": "PublicationID", "bSortable": true, "bSearchable": true},
      { "data": "Review", "bSortable": true, "bSearchable": true},
      { "data": "Authur", "bSortable": true, "bSearchable": true },
      { "data": "CreateDate", "bSortable": true, "bSearchable": true }
    ],

Then in you controller in this example index method:

public ActionResult Index (DataTablePostModel model, string pubId)
{
}
  • Related