0

Using chartJS I'm trying to load a bar chart in a partial view. It works on my layout page. But I want it to work in a partial view. But, when I click on a link to render a partial view with the chart inside it doesn't work. What could I be doing wrong?

<html>
<head>
    <meta name="viewport" content="width=device-width" />
    <script src="https://canvasjs.com/assets/script/canvasjs.min.js"></script>
    <title>Index</title>
</head>
<body>
    <div id="chartContainer"></div>
    <script type="text/javascript">

        window.onload = function () {
            var chart = new CanvasJS.Chart("chartContainer", {
                theme: "theme2",
                animationEnabled: true,
                title: {
                    text: "Simple Column Chart in ASP.NET MVC"
                },
                subtitles: [
                    { text: "Try Resizing the Browser" }
                ],
                data: [
                {
                    type: "column", //change type to bar, line, area, pie, etc
                    dataPoints: [
                    { x: 10, y: 71 },
                    { x: 20, y: 55 },
                    { x: 30, y: 50 },
                    { x: 40, y: 65 },
                    { x: 50, y: 95 },
                    { x: 60, y: 68 },
                    { x: 70, y: 28 },
                    { x: 80, y: 34 },
                    { x: 90, y: 14 }
                    ]
                                        //Uncomment below line to add data coming from the controller.
                    dataPoints: @Html.Raw(ViewBag.DataPoints),
                }
                ]
            });
            chart.render();
        };
    </script>
</body>
</html> 

Here is the Layout page for a bit more detailed information of my code.

<!DOCTYPE html>
<html> 
    <head>
        <meta name="viewport" content="width=device-width, initial-scale=1.0">
        <title>@ViewBag.Title MM-3</title>
        <link href="@Url.Content("~/Content/bootstrap.css")" rel="stylesheet" type="text/css" />

        @Scripts.Render("~/bundles/modernizr")
        @Scripts.Render("~/bundles/jquery")
        @Scripts.Render("~/bundles/unobtrusive")
        @model IEnumerable<RoboticUI.Models.ResultantRead>
       <script src="https://cdn.jsdelivr.net/jquery.ajax.unobtrusive/3.2.4/jquery.unobtrusive-ajax.min.js"></script>



    <script src="@Url.Content("~/Scripts/kendo.modernizr.custom.js")"></script>    
        <script src="~/Scripts/AutocompleteScript.js"></script>
        <link rel="stylesheet" type="text/css" href="~/Content/MainRobotFrontier.css?version=1" />
    </head>
<body style="font-family:Verdana;">

    <div class="container">
        <header>
            <div class="headerContent">
            <p>Robot Gallery</p>

                </div>
        </header>

        <div class="menu-content" style="overflow:auto">
            <div class="menu">
                @Ajax.ActionLink("Robot", "Robot", "Chart", new AjaxOptions() { UpdateTargetId = "navResult" })
                @Ajax.ActionLink("Data", "Data", "Home", new AjaxOptions() { UpdateTargetId = "navResult" })
                @Ajax.ActionLink("Client", "Client", "Home", new AjaxOptions() { UpdateTargetId = "navResult" })
            </div>
            <div id="navResult" class="main">
                <h2>Lorum Ipsum</h2>
                <p>Lorem ipsum dolor sit amet, consectetuer adipiscing elit, sed diam nonummy nibh euismod tincidunt ut laoreet dolore magna aliquam erat volutpat.</p>
            </div>
        </div>

        <footer>Copyright &copy MMM</footer>
    </div>
    @RenderBody()
</body>

</html>

With help from Jesse, I turned my problem into a solution. But, now the my div element doesn't expand according to the chart's height and width.enter image description here

JD333
  • 501
  • 8
  • 22
  • what behavior are you seeing? where was it in your layout page in the ? – JBoothUA Nov 29 '17 at 20:49
  • if you open up your browser's dev tools are there any errors in the console? – JBoothUA Nov 29 '17 at 20:49
  • also depending on how your loading your partial view window.onload might not be being called when the view is on the page? can you put a console.log('test'); at the top of the window.onload to see if it's being hit.. test should appear in the same dev-tools console where you are checking for errors if it is indeed hitting the onload – JBoothUA Nov 29 '17 at 20:51
  • in my layout page it was in the body.... give me one second on the errors – JD333 Nov 29 '17 at 20:51
  • i don't see test in my console when added. Also I get a failed to load resource error. And, I get jquery.min.js errors at least 8 – JD333 Nov 29 '17 at 20:53
  • what resource is failing to load? jquery.min? – JBoothUA Nov 29 '17 at 20:54
  • and how are you trying to load the partial onto the page? EDIT: aka does a page reload happen when you click the link to view the partial? – JBoothUA Nov 29 '17 at 20:55
  • Maybe?.. all it says is "Failed to load resource: the server responded with a status of 404" – JD333 Nov 29 '17 at 20:55
  • 1
    Ajax the bit of code to create the link is "@Ajax.ActionLink("Data", "Data", "Home", new AjaxOptions() { UpdateTargetId = "navResult" })" – JD333 Nov 29 '17 at 20:56
  • i think if you hit F5 to reload the page hopefully to the right it should say what resource through the 404. you can also check the network tab depending on what browser you're using – JBoothUA Nov 29 '17 at 20:56
  • VM1328:28 Uncaught SyntaxError: Unexpected identifier at eval () at jquery.min.js:2 at Function.globalEval (jquery.min.js:2) at Ha (jquery.min.js:3) at n.fn.init.append (jquery.min.js:3) at n.fn.init. (jquery.min.js:3) at Y (jquery.min.js:3) at n.fn.init.html (jquery.min.js:3) at HTMLDivElement. (jquery.unobtrusive-ajax.min.js:19) at Function.each (jquery.min.js:2) – JD333 Nov 29 '17 at 20:58
  • i guess that error appears on page load? or after the link is pressed? i honestly cannot tell if that's the cause of the issue or if it's totally not related. unobtrusive-ajax sounds suspicious, but I've only used that library for client side validation, is it possible you have validation on the page too? if not that could the problem, but not sure exactly what that means. – JBoothUA Nov 29 '17 at 21:04
  • Uh yes, that appears after I click the link. – JD333 Nov 29 '17 at 21:07
  • 1
    Where is your layout page? where is the partial view? what is the html you posted? – Ziv Weissman Nov 29 '17 at 21:07
  • how about this? back when it worked when it was in the layout, where those errors present in the dev console? can you revert back to that revision to test? because at least then you'd know if what you're doing is causing a syntax error or not. or better yet, for a quick test, try REMOVING @Html.Raw(ViewBag.DataPoints), and see if that makes the error go away. on a hunch i think it might be the @ – JBoothUA Nov 29 '17 at 21:09
  • The only error when the script is placed in layout was the 404 error. I did try to remove the @, but that did not work. The point of the @ is to reference data from a model to set the coordinates for the graph – JD333 Nov 29 '17 at 21:14
  • im thinking that the @ (which is the mvc razor tag) might not be parsed correctly since it's being loaded through ajax and not through the mvc engine. – JBoothUA Nov 29 '17 at 21:17
  • I got rid of the @ and just use the hardcoded data, and the chart still won't show up – JD333 Nov 29 '17 at 21:18

1 Answers1

0

Thanks for working with me there. I think I know what's going on.
Since "test" isn't appearing in your dev console after adding a console log, we can be pretty sure that the function is not being called..

I'm not too familiar with the @Ajax.ActionLink, but I'm betting that it doesn't do a page refresh and uses Ajax to load the new view onto the page.

You might want to try to do what they did here: Running scripts in an ajax-loaded page fragment

Actually according to this post, it's not even a good practice to do this: ASP.NET MVC Loading scripts in partial views

I also think that the function that you're expecting to be called will not be called after the ajax takes place as the "window" has already been loaded. when you had the script in the layout, it was present when the window was loading, but in your current scenario the script isn't on your page until AFTER your window is done loading, so it will never fire.

(that's why i was thinking the first link would help with an "ajax on load" callback vs the "window on load" callback)

Beyond that I was afraid of mvc razor's @ not being handled correctly if it's loaded through ajax, but that may not end up being an issue if you can figure out the rest.

I think the best practice here might be a success callback after the Ajax.ActionLink is done doing its thing.

If you look here (and i'm sure elsewhere) you can see an example of people using a success callback for your Ajax.ActionLink: How to tell Ajax.ActionLink OnSuccess callback which element initiated the ajax

I think what you're going to want to is remove your script from the partial view and put it somewhere that it is always present, like back in your layout. However, you're just going to encase it in a regular javascript function, and it's just going to be hanging out on the page.

function myfunction() {}

instead of your

window.onload = {}

Now to tie it all together you'll just call this myfunction() as your ActionLink's success callback.

The idea here is after your ActionLink loads the new elements onto the page, the success callback will call the myfunction and run your custom code. It should give you the same effect as if the script had just been loaded through the Ajax.ActionLink

JBoothUA
  • 3,040
  • 3
  • 17
  • 46
  • There's not a more simple approach :( – JD333 Nov 29 '17 at 21:07
  • ahhh ok, that does make sense! I will look into that second link you provided – JD333 Nov 29 '17 at 21:23
  • good luck, let me know what you come up with.. i did think of a workaround.. ill add it to my answer – JBoothUA Nov 29 '17 at 21:57
  • ok thank you. I tried that... @Ajax.ActionLink("Client", "Client", "Home", new AjaxOptions() { UpdateTargetId = "navResult", HttpMethod = "POST", OnSuccess = "getFun()" }) What's the point of the new id=""? – JD333 Nov 29 '17 at 22:30
  • Oh wow, it worked. But when the chart loads, it doesn't expand the element. so I'm stuck scrolling vertically. – JD333 Nov 29 '17 at 22:41
  • if you're looking at question from the last link? he/she's using that argument to set the HTML properties of the link.. with id="" he/she's setting the id property on the HTML element itself. (you can see he/she can then refer to the by id via javascript) – JBoothUA Nov 29 '17 at 22:42
  • ok good we're on the right track! maybe your getFun() can somehow control the scrolling too? – JBoothUA Nov 29 '17 at 22:43
  • Maybe.. but if I click on the other two links. The page will expand depending on how much content is inside the partial view. – JD333 Nov 29 '17 at 22:48
  • i think i'm a little lost on the whole expanding thing.. but thx for accepting my answer! maybe open a new question about the expanding and include that code, i guess i'm missing it. maybe your getFun() can do a .scrollTop() at the end if you always wish to be at the top? i guess the "expanding" is throwing me off. thanks! – JBoothUA Nov 29 '17 at 22:51
  • Hey, that's totally fine. Thank you very much for getting me through that. Great help! – JD333 Nov 29 '17 at 22:53
  • Actually you know what. I get this error when I load the page . "CanvasJS Error: Chart Container with id "chartContainer" was not found". – JD333 Nov 29 '17 at 22:55
  • load the partial or the page? i'm assuming that code is in your new getFun() call, which shouldn't be being called until the onsuccess callback. is something else calling your getFun() call? it sounds like your getFun() call is happening too soon before the chartContainer is on the page, (which shouldn't be the case if it's only used as that success callback) – JBoothUA Nov 29 '17 at 22:57
  • again you can add a console.log('test'); to make sure it's only being called when it should. (which should be ONLY after your partial is loaded) – JBoothUA Nov 29 '17 at 22:58
  • It actually comes up when I load the main page. I did also put a piece of debug code inside the script. And the console only writes test when I click on the link. – JD333 Nov 29 '17 at 23:01