locked
What is best way of getting the id from edit mode into jQuery function RRS feed

  • Question

  • User-183185495 posted

    I am calling a JavaScript function which relies on the case Id being set this case Id is being set through the edit function. Obviously I need some way of getting the case Id into jQuery function I'm thinking maybe I should parse the query string for that as you see the pattern for that is MISObjects/Edit/5 where 5 would be the case Id?

    But of course my jquery is being called before the edit action is completed their for the variables I am using becomes null

    I am using asp.net core 3.1 and Entity Framework Core. I have this code in a component view so that I can pass a different model to it.

    // GET: MISObjects/Edit/5
    public async Task<IActionResult> Edit(int id) {
    if (id == null) {
        return NotFound();
    }
            SetupViewBags();      
            var list = _userManager.Users.ToListAsync();
            ViewBag.Users = list;
            var mISObject = await _context.MISobject.FindAsync(id);
            HttpContext.Session.SetString("CaseId", id.ToString());
            //Using temp data to store
            TempData["CaseId"] = id.ToString();
            SetupUploadsViewBags();    
          if (mISObject == null) {
          return NotFound();
     }
         return View(mISObject);
    }

    But when I debug the Value is blank because the GetAuditTrailData gets called before the edit function has fired at least it does when I place the brake points.

    HttpGet]
    public ActionResult<DataTableWrapper<List<MISAuditTrail>>> GetAuditTrailData() {           
            Int32.TryParse(TempData.Peek["CaseId"], out int resultCaseId);          
            var auditTrailsHistory = _context.MisAuditTrail.Where(w => w.isActive == true && w.isDeleted == false && w.MISObjectId== resultCaseId).ToList();
        string output = JsonConvert.SerializeObject(auditTrailsHistory);
            DataTableWrapper<List<MISAuditTrail>> data = new DataTableWrapper<List<MISAuditTrail>>() {
                data = auditTrailsHistory
            };
    
            return data;
    }

    This is the jQuery which resides in my components view I have included the whole viewcompoennts cshtml in case that helps

    @model IEnumerable<MISSystem.Models.MISAuditTrail>
    
    <div class="row">
        <div class="table-wrapper-scroll-y my-custom-scrollbar" style="width:100%;">
    
            @if (Model.Count() == 0) {
                <div class="alert alert-info alert-dismissible">
                    <button type="button" class="close" data-dismiss="alert" aria-hidden="true">×</button>
                    <h5><i class="icon fas fa-info"></i> Information !</h5>
                    Sorry here is no Notes for this case.
                </div>
            } else {
    
    
    
    
    
    
                <table id="audTrailTable" class="table table-striped table-bordered dt-responsive nowrap">
                    <thead>
                        <tr>
                            <th>CreatedDate</th>
                            <th>createdby</th>
                            <th>action</th>
                        </tr>
                    </thead>
                    <tbody>
                        <tr>
                            <td></td>
                            <td></td>
                            <td></td>
                        </tr>
                    </tbody>
    
                </table>
            }
        </div>
    </div>
    <!-- /.card-body -->
    <div class="card-footer">
    
    </div>
    <!-- /.card-footer-->
    <!-- /.card -->
    @section scripts {
        <script>
            
            $(document).ready(function () {
                $("#audTrailTable").DataTable({
                    "ajax": {
                        url: "/MISObjects/GetAuditTrailData/"  ,
                        type: "get",
                        database: "json"
                    },
                    "columns": [
                        { "data": "createdDate" },
                        { "data": "createdBy" },
                        { "data": "action" }
                    ],
                    "scrollY": "200px",
                    "scrollCollapse": true,
                    "paging": false,
                    "processing": true, // for show progress bar
                    "filter": true, // this is for disable filter (search box)
                    "orderMulti": false // for disable multiple column at once
                })
            });
            alert(caseId);
        </script>
    
    }

    My View Component

    namespace MISSystem.Web.ViewComponents {
    
     [ViewComponent(Name = "AudiTrailList")]
     public class AuditTrailViewComponent : ViewComponent {
        private readonly IHttpContextAccessor _contextAccessor;
    
        private readonly MISDBContext db;
        public int CaseId { get; set; }
        public AuditTrailViewComponent(MISDBContext context , IHttpContextAccessor contextAccessor) {
            db = context;
            _contextAccessor = contextAccessor;
    
        }
    
    
        public async Task<IViewComponentResult> InvokeAsync(
     int caseId) {
            CaseId = caseId;
    
            var items = await GetItemsAsync(caseId);
            
            _contextAccessor.HttpContext.Session.SetString("CaseId",CaseId.ToString());
             return View(items);
        }
        private Task<List<MISAuditTrail>> GetItemsAsync(int caseId) {
            return db.MisAuditTrail.Where(x => x.isActive ==true &&  x.MISObjectId == caseId).ToListAsync();
        }
     }
    }

    The component gets called as such which is fine when the edit mode fires it finds the id of the case but when the ajax calls thats functions its gone and is null.

    @await Component.InvokeAsync("AudiTrailList", new { caseId = Model.Id })
    

    Wednesday, August 5, 2020 10:55 AM

Answers

  • User475983607 posted

    View components do not support the scripts section.  The JavaScript does not render.  Remove the script section and leave the JavaScript in place. Next, update the layout.cshtml view by moving the jQuery and DataTable JS references to the top of the _Layout.cshtml.  Otherwise; you'll get a JavaScript error. 

    There are several other issues with the design.  You've implemented competing technologies which is the heart of the problem.  Either drop the View Component and go with DataTable library and jQuery or drop DataTable/jQuery and go with a View Component.

    Anyway,  you can use the ViewBag to pass the caseId to a View.  I built simple test that illustrates how to pass the ViewBag.

    View Component InvokeAsync

    public async Task<IViewComponentResult> InvokeAsync(int caseId)
    {
        CaseId = caseId;
        var items = GetItemsAsync(caseId);
    
        ViewBag.CaseId = caseId;
        return View(items);
    }

    View Component View. Notice I removed the script section.  I also modified the layout....

    @{
        ViewData["Title"] = "Default";
    }
    
    <h1>Default</h1>
    
    <table id="audTrailTable">
        <thead>
            <tr>
                <th>CreatedDate</th>
                <th>createdby</th>
                <th>action</th>
            </tr>
        </thead>
        <tbody>
            <tr>
                <td></td>
                <td></td>
                <td></td>
            </tr>
        </tbody>
    </table>
    
    <script>
    
        $(document).ready(function () {
            var id = @ViewBag.CaseId ?? "";
            id = id == 0 ? "" : id;
    
            $("#audTrailTable").DataTable({
                "ajax": {
                    url: "/DataTable/GetAuditTrailData/" + id,
                    type: "get",
                    database: "json"
                },
                "columns": [
                    { "data": "createdDate" },
                    { "data": "createdBy" },
                    { "data": "action" }
                ],
                "scrollY": "200px",
                "scrollCollapse": true,
                "paging": false,
                "processing": true, // for show progress bar
                "filter": true, // this is for disable filter (search box)
                "orderMulti": false // for disable multiple column at once
            })
        });
    
    </script>
    
    
    
    
    

    _Layout.cshtml chages.

    <head>
        <meta charset="utf-8" />
        <meta name="viewport" content="width=device-width, initial-scale=1.0" />
        <title>@ViewData["Title"] - MvcBasic</title>
        <link rel="stylesheet" href="~/lib/bootstrap/dist/css/bootstrap.min.css" />
        <link href="~/lib/bootstrap-datepicker/css/bootstrap-datepicker.css" rel="stylesheet" />
        <link rel="stylesheet" href="https://cdn.datatables.net/1.10.21/css/jquery.dataTables.min.css" />
        <link rel="stylesheet" href="~/css/site.css" />
    
        <script src="~/lib/jquery/dist/jquery.min.js"></script>
        <script src="https://cdn.datatables.net/1.10.21/js/jquery.dataTables.min.js"></script>
    
    </head>

    MVC method that populates the DataTable.  Keep in mind that this code is a mock DB call.

    [HttpGet]
    public ActionResult<DataTableWrapper<List<MISAuditTrail>>> GetAuditTrailData(int? id)
    {
        DataTableWrapper<List<MISAuditTrail>> data = new DataTableWrapper<List<MISAuditTrail>>()
        {
            data = PopulateTestData(id)
        };
        return data;
    }

    As far as I can tell the View Component executes queries that never used.   The Data comes from an MVC action.

    • Marked as answer by Anonymous Thursday, October 7, 2021 12:00 AM
    Wednesday, August 5, 2020 3:01 PM
  • User475983607 posted

    It’s a client application yes but their is multiple tables on one page that is why it’s a view component so I can have different models in use I don’t want it to be in its own views

    I think you misunderstand the problem with the design.  Glad the ViewBag worked out.

    • Marked as answer by Anonymous Thursday, October 7, 2021 12:00 AM
    Wednesday, August 5, 2020 7:01 PM

All replies

  • User475983607 posted

    View components do not support the scripts section.  The JavaScript does not render.  Remove the script section and leave the JavaScript in place. Next, update the layout.cshtml view by moving the jQuery and DataTable JS references to the top of the _Layout.cshtml.  Otherwise; you'll get a JavaScript error. 

    There are several other issues with the design.  You've implemented competing technologies which is the heart of the problem.  Either drop the View Component and go with DataTable library and jQuery or drop DataTable/jQuery and go with a View Component.

    Anyway,  you can use the ViewBag to pass the caseId to a View.  I built simple test that illustrates how to pass the ViewBag.

    View Component InvokeAsync

    public async Task<IViewComponentResult> InvokeAsync(int caseId)
    {
        CaseId = caseId;
        var items = GetItemsAsync(caseId);
    
        ViewBag.CaseId = caseId;
        return View(items);
    }

    View Component View. Notice I removed the script section.  I also modified the layout....

    @{
        ViewData["Title"] = "Default";
    }
    
    <h1>Default</h1>
    
    <table id="audTrailTable">
        <thead>
            <tr>
                <th>CreatedDate</th>
                <th>createdby</th>
                <th>action</th>
            </tr>
        </thead>
        <tbody>
            <tr>
                <td></td>
                <td></td>
                <td></td>
            </tr>
        </tbody>
    </table>
    
    <script>
    
        $(document).ready(function () {
            var id = @ViewBag.CaseId ?? "";
            id = id == 0 ? "" : id;
    
            $("#audTrailTable").DataTable({
                "ajax": {
                    url: "/DataTable/GetAuditTrailData/" + id,
                    type: "get",
                    database: "json"
                },
                "columns": [
                    { "data": "createdDate" },
                    { "data": "createdBy" },
                    { "data": "action" }
                ],
                "scrollY": "200px",
                "scrollCollapse": true,
                "paging": false,
                "processing": true, // for show progress bar
                "filter": true, // this is for disable filter (search box)
                "orderMulti": false // for disable multiple column at once
            })
        });
    
    </script>
    
    
    
    
    

    _Layout.cshtml chages.

    <head>
        <meta charset="utf-8" />
        <meta name="viewport" content="width=device-width, initial-scale=1.0" />
        <title>@ViewData["Title"] - MvcBasic</title>
        <link rel="stylesheet" href="~/lib/bootstrap/dist/css/bootstrap.min.css" />
        <link href="~/lib/bootstrap-datepicker/css/bootstrap-datepicker.css" rel="stylesheet" />
        <link rel="stylesheet" href="https://cdn.datatables.net/1.10.21/css/jquery.dataTables.min.css" />
        <link rel="stylesheet" href="~/css/site.css" />
    
        <script src="~/lib/jquery/dist/jquery.min.js"></script>
        <script src="https://cdn.datatables.net/1.10.21/js/jquery.dataTables.min.js"></script>
    
    </head>

    MVC method that populates the DataTable.  Keep in mind that this code is a mock DB call.

    [HttpGet]
    public ActionResult<DataTableWrapper<List<MISAuditTrail>>> GetAuditTrailData(int? id)
    {
        DataTableWrapper<List<MISAuditTrail>> data = new DataTableWrapper<List<MISAuditTrail>>()
        {
            data = PopulateTestData(id)
        };
        return data;
    }

    As far as I can tell the View Component executes queries that never used.   The Data comes from an MVC action.

    • Marked as answer by Anonymous Thursday, October 7, 2021 12:00 AM
    Wednesday, August 5, 2020 3:01 PM
  • User-183185495 posted

    The reason I need the jQuery is to make the scroll bar visible using the data table  scrollY 

    Unless u no another way around it ? Without having to resort to the jquery

     

    View components do not support the scripts section.  The JavaScript does not render.  Remove the script section and leave the JavaScript in place. Next, update the layout.cshtml view by moving the jQuery and DataTable JS references to the top of the _Layout.cshtml.  Otherwise; you'll get a JavaScript error. 

    There are several other issues with the design.  You've implemented competing technologies which is the heart of the problem.  Either drop the View Component and go with DataTable library and jQuery or drop DataTable/jQuery and go with a View Component.

    Anyway,  you can use the ViewBag to pass the caseId to a View.  I built simple test that illustrates how to pass the ViewBag.

    View Component InvokeAsync

    public async Task<IViewComponentResult> InvokeAsync(int caseId)
    {
        CaseId = caseId;
        var items = GetItemsAsync(caseId);
    
        ViewBag.CaseId = caseId;
        return View(items);
    }

    View Component View. Notice I removed the script section.  I also modified the layout....

    @{
        ViewData["Title"] = "Default";
    }
    
    <h1>Default</h1>
    
    <table id="audTrailTable">
        <thead>
            <tr>
                <th>CreatedDate</th>
                <th>createdby</th>
                <th>action</th>
            </tr>
        </thead>
        <tbody>
            <tr>
                <td></td>
                <td></td>
                <td></td>
            </tr>
        </tbody>
    </table>
    
    <script>
    
        $(document).ready(function () {
            var id = @ViewBag.CaseId ?? "";
            id = id == 0 ? "" : id;
    
            $("#audTrailTable").DataTable({
                "ajax": {
                    url: "/DataTable/GetAuditTrailData/" + id,
                    type: "get",
                    database: "json"
                },
                "columns": [
                    { "data": "createdDate" },
                    { "data": "createdBy" },
                    { "data": "action" }
                ],
                "scrollY": "200px",
                "scrollCollapse": true,
                "paging": false,
                "processing": true, // for show progress bar
                "filter": true, // this is for disable filter (search box)
                "orderMulti": false // for disable multiple column at once
            })
        });
    
    </script>
    
    
    
    

    _Layout.cshtml chages.

    <head>
        <meta charset="utf-8" />
        <meta name="viewport" content="width=device-width, initial-scale=1.0" />
        <title>@ViewData["Title"] - MvcBasic</title>
        <link rel="stylesheet" href="~/lib/bootstrap/dist/css/bootstrap.min.css" />
        <link href="~/lib/bootstrap-datepicker/css/bootstrap-datepicker.css" rel="stylesheet" />
        <link rel="stylesheet" href="https://cdn.datatables.net/1.10.21/css/jquery.dataTables.min.css" />
        <link rel="stylesheet" href="~/css/site.css" />
    
        <script src="~/lib/jquery/dist/jquery.min.js"></script>
        <script src="https://cdn.datatables.net/1.10.21/js/jquery.dataTables.min.js"></script>
    
    </head>

    MVC method that populates the DataTable.  Keep in mind that this code is a mock DB call.

    [HttpGet]
    public ActionResult<DataTableWrapper<List<MISAuditTrail>>> GetAuditTrailData(int? id)
    {
        DataTableWrapper<List<MISAuditTrail>> data = new DataTableWrapper<List<MISAuditTrail>>()
        {
            data = PopulateTestData(id)
        };
        return data;
    }

    As far as I can tell the View Component executes queries that never used.   The Data comes from an MVC action.

    Wednesday, August 5, 2020 3:18 PM
  • User475983607 posted

    The reason I need the jQuery is to make the scroll bar visible using the data table scrollY
    Unless u no another way around it ? Without having to resort to the jquery

    Your response indicates the need for a client side application.  Move the table HTML to a View rather than a View Component. 

    Do realize the current View Component design executes LINQ queries and does nothing with the results?  If you remove the View Component the code will be much simpler and more efficient. 

    Wednesday, August 5, 2020 4:15 PM
  • User-183185495 posted
    It’s a client application yes but their is multiple tables on one page that is why it’s a view component so I can have different models in use I don’t want it to be in its own views
    Wednesday, August 5, 2020 6:40 PM
  • User475983607 posted

    It’s a client application yes but their is multiple tables on one page that is why it’s a view component so I can have different models in use I don’t want it to be in its own views

    I think you misunderstand the problem with the design.  Glad the ViewBag worked out.

    • Marked as answer by Anonymous Thursday, October 7, 2021 12:00 AM
    Wednesday, August 5, 2020 7:01 PM
  • User-183185495 posted

    For some reason its throwing me SyntaxError for Uncaught SyntaxError: Unexpected token '??'

    View components do not support the scripts section.  The JavaScript does not render.  Remove the script section and leave the JavaScript in place. Next, update the layout.cshtml view by moving the jQuery and DataTable JS references to the top of the _Layout.cshtml.  Otherwise; you'll get a JavaScript error. 

    There are several other issues with the design.  You've implemented competing technologies which is the heart of the problem.  Either drop the View Component and go with DataTable library and jQuery or drop DataTable/jQuery and go with a View Component.

    Anyway,  you can use the ViewBag to pass the caseId to a View.  I built simple test that illustrates how to pass the ViewBag.

    View Component InvokeAsync

    public async Task<IViewComponentResult> InvokeAsync(int caseId)
    {
        CaseId = caseId;
        var items = GetItemsAsync(caseId);
    
        ViewBag.CaseId = caseId;
        return View(items);
    }

    View Component View. Notice I removed the script section.  I also modified the layout....

    @{
        ViewData["Title"] = "Default";
    }
    
    <h1>Default</h1>
    
    <table id="audTrailTable">
        <thead>
            <tr>
                <th>CreatedDate</th>
                <th>createdby</th>
                <th>action</th>
            </tr>
        </thead>
        <tbody>
            <tr>
                <td></td>
                <td></td>
                <td></td>
            </tr>
        </tbody>
    </table>
    
    <script>
    
        $(document).ready(function () {
            var id = @ViewBag.CaseId ?? "";
            id = id == 0 ? "" : id;
    
            $("#audTrailTable").DataTable({
                "ajax": {
                    url: "/DataTable/GetAuditTrailData/" + id,
                    type: "get",
                    database: "json"
                },
                "columns": [
                    { "data": "createdDate" },
                    { "data": "createdBy" },
                    { "data": "action" }
                ],
                "scrollY": "200px",
                "scrollCollapse": true,
                "paging": false,
                "processing": true, // for show progress bar
                "filter": true, // this is for disable filter (search box)
                "orderMulti": false // for disable multiple column at once
            })
        });
    
    </script>
    
    
    
    

    _Layout.cshtml chages.

    <head>
        <meta charset="utf-8" />
        <meta name="viewport" content="width=device-width, initial-scale=1.0" />
        <title>@ViewData["Title"] - MvcBasic</title>
        <link rel="stylesheet" href="~/lib/bootstrap/dist/css/bootstrap.min.css" />
        <link href="~/lib/bootstrap-datepicker/css/bootstrap-datepicker.css" rel="stylesheet" />
        <link rel="stylesheet" href="https://cdn.datatables.net/1.10.21/css/jquery.dataTables.min.css" />
        <link rel="stylesheet" href="~/css/site.css" />
    
        <script src="~/lib/jquery/dist/jquery.min.js"></script>
        <script src="https://cdn.datatables.net/1.10.21/js/jquery.dataTables.min.js"></script>
    
    </head>

    MVC method that populates the DataTable.  Keep in mind that this code is a mock DB call.

    [HttpGet]
    public ActionResult<DataTableWrapper<List<MISAuditTrail>>> GetAuditTrailData(int? id)
    {
        DataTableWrapper<List<MISAuditTrail>> data = new DataTableWrapper<List<MISAuditTrail>>()
        {
            data = PopulateTestData(id)
        };
        return data;
    }

    As far as I can tell the View Component executes queries that never used.   The Data comes from an MVC action.

    Wednesday, August 5, 2020 7:37 PM
  • User-183185495 posted

    Never mind my last got it working thanks very much

    roguenidb

    It’s a client application yes but their is multiple tables on one page that is why it’s a view component so I can have different models in use I don’t want it to be in its own views

    I think you misunderstand the problem with the design.  Glad the ViewBag worked out.

    roguenidb

    It’s a client application yes but their is multiple tables on one page that is why it’s a view component so I can have different models in use I don’t want it to be in its own views

    I think you misunderstand the problem with the design.  Glad the ViewBag worked out.

    Wednesday, August 5, 2020 7:48 PM