locked
Update a partial view on a parent view from another partial view on the same parent view. RRS feed

  • Question

  • User-305496339 posted

    I have discovered that it is impossible using jquery ajax to update a partial view from another partial view where they both reside on the same parent view. when i save a record on a partial view  it is not immediately saved to the database (Why is the record not immediately saved to the database) in order for me to retrieve the new record and display it on the other partial view. The only way I can get all the records + the newly saved records is when i refresh the browser which causes a postback and the parent view is reloaded. I just want some ideas concerning this functionality that seems impossible in MVC, but yet I have been told that I can accomplish this functionality. Do I need to just use a modal form to add the record and then i can see all the records displayed in my partial view? I have been working on this for a very long time. The reason why I made this post is because I think I can learn a lot about how MVC and Entity Framework works by understanding why the aforementioned functionality is impossible. Thanks for any suggestions.

    Tried this code and it will not work

    $(document).ready(function () {
                    //First ajax call to save data
                    $.ajax({
                        url: '@Url.Action("SaveData","Sample")',
                        type: 'POST',
                        data: { name: 'Name1' },
                        dataType: 'json',
                        success: function (data) {
                            console.log(data);
                                // call next ajax function to retrive the data
                                $.ajax({
                                    url: '@Url.Action("ChangeData", "Sample")',
                                    data: { name1: data },
                                    dataType: 'json',
                                });
                        }
                    });
                });
    Friday, January 26, 2018 4:32 PM

Answers

  • User475983607 posted

    This is not an MVC limitation.  There are a couple of key concepts that you need to understand first. 

    1. Partial view exist on the server not within the browser where JavaScript runs.  The results if a partial view (HTML) exists in the browser.
    2. AJAX does not update the browser automatically like a full POST or GET.  It is up to the developer to write code that updates DOM (HTML in the browser) when the AJAX request returns.

    rkrex

    Tried this code and it will not work

    $(document).ready(function () {
                    //First ajax call to save data
                    $.ajax({
                        url: '@Url.Action("SaveData","Sample")',
                        type: 'POST',
                        data: { name: 'Name1' },
                        dataType: 'json',
                        success: function (data) {
                            console.log(data);
                                // call next ajax function to retrive the data
                                $.ajax({
                                    url: '@Url.Action("ChangeData", "Sample")',
                                    data: { name1: data },
                                    dataType: 'json',
                                });
                        }
                    });
                });

    First "does not work" is not specific enough.  Does the request make it to the controller?  Or are there errors are there errors in the Network or Console? 

    The code shown above does not update the DOM so you won't see any changes in the browser window.

    Assuming that the controller action (/Sample/SaveData) returns a partial view and not an error, the AJAX code should look something like this.

    $(document).ready(function () {
        $.ajax({
            url: '@Url.Action("SaveData","Sample")',
            type: 'POST',
            data: { name: 'Name1' },
            dataType: 'json',
            success: function (data) {
                console.log(data);
                $('#Id_Of_the_DOM_element_to_update').html(data);
            }
        });
    });

    • Marked as answer by Anonymous Thursday, October 7, 2021 12:00 AM
    Friday, January 26, 2018 4:58 PM
  • User-474980206 posted

    as stated an ajax call just returns data to a javascript variable. you need to write code to update the dom with this data, which can be text, json, html or xml. with MVC your ajax can call an action to return a html fragment via return partial. you then update the dom with this html. 

    but this is an old fashioned way to write client code. nowadays its better to use a client framework like react, angular or vue. then the ajax call just returns json, that the client template engine renders. 

    modern web apps are written in javascript (usually using node tool chain) and asp.net is just used to host static files, and ajax requests.

    • Marked as answer by Anonymous Thursday, October 7, 2021 12:00 AM
    Friday, January 26, 2018 5:33 PM
  • User475983607 posted

    To answer your question, yes it does make it to the controller methods although it jumps from the save record method too the show records method. It also invokes the methods again as if the main view is reloading. I have no idea what is going on, maybe I need to use another type of submit button. so as to not cause the main view to reload. And then as i said you have the issue with the record not actually being saved when you invoke the db.savechanges. I know there is a video about using bootstrap modal forms. But i'm thinking this may be the reason why in tutorials they teach to add a record on another form and then redirect to the main view to see the new record added in the list.

    The posted code runs when the page loads not when a button is clicked. 

    • Marked as answer by Anonymous Thursday, October 7, 2021 12:00 AM
    Friday, January 26, 2018 7:48 PM
  • User-474980206 posted

    you seem to be missing how the web works. 

    the browser request a page (url) --->
       <-- the server builds the html (mvc - calls action to build a model and selects a view, then calls the view to produce html), then sends html to browser
    the browser replaces the current page with the returned html

    there are three ways to update the html in the browser

      1) type url in url bar
      2) click on a link (<a>)
      3) form post

    in all cases the server is expected to return a new html page (there is an exception for attachment content type, which can be saved instead of displayed). the browser has no support for a partial update of the page. (iframes can be used to emulate this, but each iframe is its own page).

    the final way to change the html on a page is for javascript to modify the dom directly, usually based on a keyboard or mouse event, but timers can be used. sometimes (but not required) the javascript will make an ajax call to get the data to modify the dom with. but again the javascript must do it, the browser will not process ajax returned data.

    partial views are one way for MVC to return html snippets which can be used by calling client code. but the client code must know what action to call and what part of the dom to update. it will get no help from the server.

     

    • Marked as answer by Anonymous Thursday, October 7, 2021 12:00 AM
    Friday, January 26, 2018 9:04 PM
  • User475983607 posted

    rkrex

    Thats obvious. But it doesnt resolve the issues that I addressed.

    Update a partial view on a parent view from another partial view on the same parent view.

    This example has one View and two partials; Index, Input, Result.  Basically the Greeting input Element in the Input partial is POSTed to the Input action.  The Input action returns the same value to the AJAX function.  The AJAX function updates the Result partial.

    Model

        public class InputViewModel
        {
            public string Greeting { get; set; }
        }

    Actions

        public class AjaxDemoController : Controller
        {
            // GET: AjaxDemo
            public ActionResult Index()
            {
                return View();
            }
    
            [HttpPost]
            public ActionResult Input(InputViewModel vm)
            {
                if (Request.IsAjaxRequest())
                {
                    return Json(vm);
                }
                return PartialView();
            }
        }

    Index View

    @{
        ViewBag.Title = "Index";
    }
    
    <h2>Index</h2>
    <script src="https://code.jquery.com/jquery-3.2.1.js" integrity="sha256-DZAnKJ/6XZ9si04Hgrsxu/8s717jcIzLy3oi35EouyE=" crossorigin="anonymous"></script>
    <script>
        $(function () {
    
            $('#Greeting').val("Hello World!");
    
            $('#Button1').click(function () {
                
                var data = {};
                data.Greeting = $('#Greeting').val();
    
                $.ajax({
                    method: 'POST',
                    url: 'http://localhost:50391/AjaxDemo/Input',
                    contentType: 'application/json;charset=utf-8',
                    dataType: "json",
                    data: JSON.stringify(data)
                }).done(function (data) {
                    console.log(data);
                    $('#result').text(data.Greeting);
                }).fail(function (err, textStatus, status) {
                    console.log(status);
                    console.log(err);
                });
    
            });
    
        });
    
    </script>
    <div>
        <div>
            @Html.Partial("Input")
        </div>
        <div>
            @Html.Partial("Result")
        </div>
        <div class="form-group">
            <div class="col-md-offset-2 col-md-10">
                <input id="Button1" type="button" value="Create" class="btn btn-default" />
            </div>
        </div>
    
    </div>
    
    

    Input Partial View

    @model MvcApiDemo.Models.InputViewModel
    
    <div class="form-horizontal">
        <div class="form-group">
            @Html.LabelFor(model => model.Greeting, htmlAttributes: new { @class = "control-label col-md-2" })
            <div class="col-md-10">
                @Html.EditorFor(model => model.Greeting, new { htmlAttributes = new { @class = "form-control" } })
            </div>
        </div>
    </div>
    
    

    Result Partial View

    <div id="result"></div>
    

    rkrex

    If we could address whats going on as to the reason why a controller method cannot read a record in a database that does not exist I think we could all move on.

    Are you having problems handling a null result after querying the database?  Can you post the controller method source code? 

    • Marked as answer by Anonymous Thursday, October 7, 2021 12:00 AM
    Friday, January 26, 2018 11:43 PM
  • User-474980206 posted

    we are all confused because your thread is about partial views, your sample code is an ajax call, and your complaint is something to do with a database call not working.

    there is no issue using ajax to call an MVC action to read/write to a database and update the pages html (with json or html from a partial). people do what your thread title implies all the time (some solutions are more elegant then others). if its not working, you have a fundemential logic error. writing and reading a database is so trivial in an action, we assume you are having some trouble calling the action, or handling the actions result. we assume you don't understand ajax, because you have no code to process the results in your sample ajax call.

     

    • Marked as answer by Anonymous Thursday, October 7, 2021 12:00 AM
    Saturday, January 27, 2018 12:07 AM
  • User-474980206 posted

    not sure why you would use 2 ajax calls, 1 update, and one fetch, but if you do, the "a" in ajax is async. you must complete the first call before making the second call. just uses promises (or await if using babel to transpire your client code).

       

    $((function () {
         // why this is done on page load insead of during the render action?
         // or on a click event
        
         //First ajax call to save data
         $.ajax({
             url: '@Url.Action("SaveData","Sample")',
             type: 'POST',
             data: { name: 'Name1' },
             dataType: 'json'
         }).done(function (data) {
             // call next ajax function to retrive the html
             // action should return partial
             // return new promise
             return $.ajax({
                 url: '@Url.Action("ChangeData", "Sample")',
                 data: { name1: data }
    }); }).done(function(html) { // the action returned a partial (html snippet) // update the dom $('#theid').html(html); }).catch(function(e) { alert('got an error: ' + e); }); });

    note: I noticed your original ajax chained the calls, but did nothing with the second action response. did the first action really return a json object? if not the second ajax call will have a bad data. also in your sample code, the second ajax expected a json result, but unless you are using a client template engine, this should be the html you want to display.

    also I expect the first action to look like:

    public ActionResult SaveDate(string name) {
       // save data
       ...
       return Json(name);
    }
    
    public ActionResult ChangeData(string name) {
       // lookup model data
       ....
       return PartialView(model);
    }
    
    


     

    • Marked as answer by Anonymous Thursday, October 7, 2021 12:00 AM
    Sunday, January 28, 2018 8:37 PM
  • User-474980206 posted

    there is nothing to duplicate. your text description is not true of a correctly coded site. you have coding errors.

    I based my code on the sample ajax in your original post. looking at  the code, we can see you have no code to display the results of the ajax calls in the browser (thus the coding error we can see). you don't show your action methods, so we can guess what coding errors they have.

    • Marked as answer by Anonymous Thursday, October 7, 2021 12:00 AM
    Monday, January 29, 2018 8:31 PM

All replies

  • User475983607 posted

    This is not an MVC limitation.  There are a couple of key concepts that you need to understand first. 

    1. Partial view exist on the server not within the browser where JavaScript runs.  The results if a partial view (HTML) exists in the browser.
    2. AJAX does not update the browser automatically like a full POST or GET.  It is up to the developer to write code that updates DOM (HTML in the browser) when the AJAX request returns.

    rkrex

    Tried this code and it will not work

    $(document).ready(function () {
                    //First ajax call to save data
                    $.ajax({
                        url: '@Url.Action("SaveData","Sample")',
                        type: 'POST',
                        data: { name: 'Name1' },
                        dataType: 'json',
                        success: function (data) {
                            console.log(data);
                                // call next ajax function to retrive the data
                                $.ajax({
                                    url: '@Url.Action("ChangeData", "Sample")',
                                    data: { name1: data },
                                    dataType: 'json',
                                });
                        }
                    });
                });

    First "does not work" is not specific enough.  Does the request make it to the controller?  Or are there errors are there errors in the Network or Console? 

    The code shown above does not update the DOM so you won't see any changes in the browser window.

    Assuming that the controller action (/Sample/SaveData) returns a partial view and not an error, the AJAX code should look something like this.

    $(document).ready(function () {
        $.ajax({
            url: '@Url.Action("SaveData","Sample")',
            type: 'POST',
            data: { name: 'Name1' },
            dataType: 'json',
            success: function (data) {
                console.log(data);
                $('#Id_Of_the_DOM_element_to_update').html(data);
            }
        });
    });

    • Marked as answer by Anonymous Thursday, October 7, 2021 12:00 AM
    Friday, January 26, 2018 4:58 PM
  • User-474980206 posted

    as stated an ajax call just returns data to a javascript variable. you need to write code to update the dom with this data, which can be text, json, html or xml. with MVC your ajax can call an action to return a html fragment via return partial. you then update the dom with this html. 

    but this is an old fashioned way to write client code. nowadays its better to use a client framework like react, angular or vue. then the ajax call just returns json, that the client template engine renders. 

    modern web apps are written in javascript (usually using node tool chain) and asp.net is just used to host static files, and ajax requests.

    • Marked as answer by Anonymous Thursday, October 7, 2021 12:00 AM
    Friday, January 26, 2018 5:33 PM
  • User-305496339 posted

    Thanks for your help. But are you considering the Entity Framework and the contexts that you must create to connect to the database. After performing a db.savechanges the record is not immediately saved to the database. And i dont know what is going on between the time you execute the savechanges and the time it is actually saved to the database.  Therefore i cannot query the table or Entity and return all of the records until the record is saved.

    Friday, January 26, 2018 6:01 PM
  • User-305496339 posted

    Thanks! Where would you recommend i find a good tutorial that I can begin learning Angular to do CRUD actions? And what other functionality are Angular and react good at performing? Thanks Again !

    Friday, January 26, 2018 6:05 PM
  • User-305496339 posted

    To answer your question, yes it does make it to the controller methods although it jumps from the save record method too the show records method. It also invokes the methods again as if the main view is reloading. I have no idea what is going on, maybe I need to use another type of submit button. so as to not cause the main view to reload. And then as i said you have the issue with the record not actually being saved when you invoke the db.savechanges. I know there is a video about using bootstrap modal forms. But i'm thinking this may be the reason why in tutorials they teach to add a record on another form and then redirect to the main view to see the new record added in the list.

    Friday, January 26, 2018 6:54 PM
  • User475983607 posted

    To answer your question, yes it does make it to the controller methods although it jumps from the save record method too the show records method. It also invokes the methods again as if the main view is reloading. I have no idea what is going on, maybe I need to use another type of submit button. so as to not cause the main view to reload. And then as i said you have the issue with the record not actually being saved when you invoke the db.savechanges. I know there is a video about using bootstrap modal forms. But i'm thinking this may be the reason why in tutorials they teach to add a record on another form and then redirect to the main view to see the new record added in the list.

    The posted code runs when the page loads not when a button is clicked. 

    • Marked as answer by Anonymous Thursday, October 7, 2021 12:00 AM
    Friday, January 26, 2018 7:48 PM
  • User-474980206 posted

    you seem to be missing how the web works. 

    the browser request a page (url) --->
       <-- the server builds the html (mvc - calls action to build a model and selects a view, then calls the view to produce html), then sends html to browser
    the browser replaces the current page with the returned html

    there are three ways to update the html in the browser

      1) type url in url bar
      2) click on a link (<a>)
      3) form post

    in all cases the server is expected to return a new html page (there is an exception for attachment content type, which can be saved instead of displayed). the browser has no support for a partial update of the page. (iframes can be used to emulate this, but each iframe is its own page).

    the final way to change the html on a page is for javascript to modify the dom directly, usually based on a keyboard or mouse event, but timers can be used. sometimes (but not required) the javascript will make an ajax call to get the data to modify the dom with. but again the javascript must do it, the browser will not process ajax returned data.

    partial views are one way for MVC to return html snippets which can be used by calling client code. but the client code must know what action to call and what part of the dom to update. it will get no help from the server.

     

    • Marked as answer by Anonymous Thursday, October 7, 2021 12:00 AM
    Friday, January 26, 2018 9:04 PM
  • User-305496339 posted

    Thats obvious. But it doesnt resolve the issues that I addressed.

    Friday, January 26, 2018 10:12 PM
  • User-305496339 posted

    I'm wondering what did I say in my comments that implied that I didnt understand how the web works. I have been working with asp.net for over 10 years. I'm not sure if anyone knows how to address my problem. If we could address whats going on as to the reason why a controller method cannot read a record in a database that does not exist I think we could all move on.

    Friday, January 26, 2018 10:17 PM
  • User475983607 posted

    rkrex

    Thats obvious. But it doesnt resolve the issues that I addressed.

    Update a partial view on a parent view from another partial view on the same parent view.

    This example has one View and two partials; Index, Input, Result.  Basically the Greeting input Element in the Input partial is POSTed to the Input action.  The Input action returns the same value to the AJAX function.  The AJAX function updates the Result partial.

    Model

        public class InputViewModel
        {
            public string Greeting { get; set; }
        }

    Actions

        public class AjaxDemoController : Controller
        {
            // GET: AjaxDemo
            public ActionResult Index()
            {
                return View();
            }
    
            [HttpPost]
            public ActionResult Input(InputViewModel vm)
            {
                if (Request.IsAjaxRequest())
                {
                    return Json(vm);
                }
                return PartialView();
            }
        }

    Index View

    @{
        ViewBag.Title = "Index";
    }
    
    <h2>Index</h2>
    <script src="https://code.jquery.com/jquery-3.2.1.js" integrity="sha256-DZAnKJ/6XZ9si04Hgrsxu/8s717jcIzLy3oi35EouyE=" crossorigin="anonymous"></script>
    <script>
        $(function () {
    
            $('#Greeting').val("Hello World!");
    
            $('#Button1').click(function () {
                
                var data = {};
                data.Greeting = $('#Greeting').val();
    
                $.ajax({
                    method: 'POST',
                    url: 'http://localhost:50391/AjaxDemo/Input',
                    contentType: 'application/json;charset=utf-8',
                    dataType: "json",
                    data: JSON.stringify(data)
                }).done(function (data) {
                    console.log(data);
                    $('#result').text(data.Greeting);
                }).fail(function (err, textStatus, status) {
                    console.log(status);
                    console.log(err);
                });
    
            });
    
        });
    
    </script>
    <div>
        <div>
            @Html.Partial("Input")
        </div>
        <div>
            @Html.Partial("Result")
        </div>
        <div class="form-group">
            <div class="col-md-offset-2 col-md-10">
                <input id="Button1" type="button" value="Create" class="btn btn-default" />
            </div>
        </div>
    
    </div>
    
    

    Input Partial View

    @model MvcApiDemo.Models.InputViewModel
    
    <div class="form-horizontal">
        <div class="form-group">
            @Html.LabelFor(model => model.Greeting, htmlAttributes: new { @class = "control-label col-md-2" })
            <div class="col-md-10">
                @Html.EditorFor(model => model.Greeting, new { htmlAttributes = new { @class = "form-control" } })
            </div>
        </div>
    </div>
    
    

    Result Partial View

    <div id="result"></div>
    

    rkrex

    If we could address whats going on as to the reason why a controller method cannot read a record in a database that does not exist I think we could all move on.

    Are you having problems handling a null result after querying the database?  Can you post the controller method source code? 

    • Marked as answer by Anonymous Thursday, October 7, 2021 12:00 AM
    Friday, January 26, 2018 11:43 PM
  • User-474980206 posted

    we are all confused because your thread is about partial views, your sample code is an ajax call, and your complaint is something to do with a database call not working.

    there is no issue using ajax to call an MVC action to read/write to a database and update the pages html (with json or html from a partial). people do what your thread title implies all the time (some solutions are more elegant then others). if its not working, you have a fundemential logic error. writing and reading a database is so trivial in an action, we assume you are having some trouble calling the action, or handling the actions result. we assume you don't understand ajax, because you have no code to process the results in your sample ajax call.

     

    • Marked as answer by Anonymous Thursday, October 7, 2021 12:00 AM
    Saturday, January 27, 2018 12:07 AM
  • User-305496339 posted

    [HttpPost]

    public ActionResult CreateItemPurchased(ItemsPurchased itemspurchased)
    {
    MvcMusicStoreEntities2 db = new MvcMusicStoreEntities2();
    itemspurchased.PurchaseId = 5;
    if (ModelState.IsValid)
    {

    db.ItemsPurchaseds.Add(itemspurchased);
    db.SaveChanges();
    }

    return View();

    }


    [HttpPost]
    public ActionResult GetData(ItemsPurchased item)
    {
    MvcMusicStoreEntities2 dbcontext = new MvcMusicStoreEntities2();
    var resultid = item.PurchaseId;


    var data = (from s in dbcontext.ItemsPurchaseds
    where s.PurchaseId == resultid
    select s).ToList();


    List<CRUD.Models.ItemsPurchased> PurchaseList = data;
    var ListPurchases = PurchaseList ;
    return PartialView("_ItemsPurchased", ListPurchases );
    }

    Thank You for your help. I was unable to get the id of the Parent View so I hard coded it for now. But if you notice when you make your ajax call for the GetData method the record is not in the table so it does not get returned with the preexisting records during your return PartialView.

    Saturday, January 27, 2018 12:54 AM
  • User-305496339 posted

    I thought I explained to you that the record is not in the database table when i make the ajax call to get the data. I am creating a record and saving it. Then I want to show a partial view using an ajax call with the list of preexisting records plus the newly added record. You sound very upset and I apologize about whatever is going on.

    Saturday, January 27, 2018 1:01 AM
  • User-474980206 posted
    It’s still not clear your issue. Is the database not updating, or the ajax is not updating the page. As stated, your sample ajax code did not update the page with the actions response. Did you update your Ajax code?

    Saturday, January 27, 2018 9:03 PM
  • User-305496339 posted

    Are you reading my replies? I have explained this issue at least 5 times if you read through this thread. And I have explained it in detail. I said that during the time that I make the second ajax call to render the partial view I notice that the record is not present in the table. And therefore the method that loads a list of the records does not contain the last record that I added. What do you mean about did I update my ajax code? Have you indicated that it needs to be updated.

    Saturday, January 27, 2018 9:44 PM
  • User-305496339 posted

    I appreciate the example code that was posted. However, the code is not retrieving data from a database, or more specifically it is not using the .net entity framework which "may" be the root of my problem. I don't know if their is an ajax parameter that waits until the record is saved before proceeding with the next Ajax call to retrieve the records. I am fairly new at using Ajax and the .net entity framework to retrieve data. 

    Saturday, January 27, 2018 10:03 PM
  • User-474980206 posted

    not sure why you would use 2 ajax calls, 1 update, and one fetch, but if you do, the "a" in ajax is async. you must complete the first call before making the second call. just uses promises (or await if using babel to transpire your client code).

       

    $((function () {
         // why this is done on page load insead of during the render action?
         // or on a click event
        
         //First ajax call to save data
         $.ajax({
             url: '@Url.Action("SaveData","Sample")',
             type: 'POST',
             data: { name: 'Name1' },
             dataType: 'json'
         }).done(function (data) {
             // call next ajax function to retrive the html
             // action should return partial
             // return new promise
             return $.ajax({
                 url: '@Url.Action("ChangeData", "Sample")',
                 data: { name1: data }
    }); }).done(function(html) { // the action returned a partial (html snippet) // update the dom $('#theid').html(html); }).catch(function(e) { alert('got an error: ' + e); }); });

    note: I noticed your original ajax chained the calls, but did nothing with the second action response. did the first action really return a json object? if not the second ajax call will have a bad data. also in your sample code, the second ajax expected a json result, but unless you are using a client template engine, this should be the html you want to display.

    also I expect the first action to look like:

    public ActionResult SaveDate(string name) {
       // save data
       ...
       return Json(name);
    }
    
    public ActionResult ChangeData(string name) {
       // lookup model data
       ....
       return PartialView(model);
    }
    
    


     

    • Marked as answer by Anonymous Thursday, October 7, 2021 12:00 AM
    Sunday, January 28, 2018 8:37 PM
  • User-305496339 posted

    Another symptom was that the execution of the code in the controller methods that i called from ajax was sporadic, or it would jump from the Save Method To The Display method. I knew something was wrong, but i cant believe nobody has tried to duplicate what I did. That example that you commented on was not my code and nor does it use entity framework

    Monday, January 29, 2018 4:21 PM
  • User-474980206 posted

    there is nothing to duplicate. your text description is not true of a correctly coded site. you have coding errors.

    I based my code on the sample ajax in your original post. looking at  the code, we can see you have no code to display the results of the ajax calls in the browser (thus the coding error we can see). you don't show your action methods, so we can guess what coding errors they have.

    • Marked as answer by Anonymous Thursday, October 7, 2021 12:00 AM
    Monday, January 29, 2018 8:31 PM