I have a usercontrol with some charts from Google chart api.
When the usercontrol is getting loaded and rendered by the server the usual way everything works as expected. But when I use a ajax webservice the render the control async and return the html with ajax and add it to the page, I get some script error in firebug(chrome calls it a ReferenceError):
"google is not defined"
My project is ASP.Net MVP Webforms with some javascript.
I have made a sample project where I have recreated the issue. Download it here.
Control renderer code:
public virtual string RenderControlToString(string path, bool htmlEncode)
{
StringWriter stringWriter = new StringWriter();
this.RenderControl(path, (TextWriter)stringWriter);
string s = stringWriter.ToString();
if (!htmlEncode)
return s;
else
return HttpContext.Current.Server.HtmlEncode(s);
}
public virtual void RenderControl(string path, TextWriter writer)
{
var page = new PageForRendering();
page.Controls.Add(page.LoadControl(path));
HttpContext.Current.Server.Execute((IHttpHandler)page, writer, true);
}
(To omit the "need to be in form" error - there is a form on the page the control is added to)
public class PageForRendering : Page
{
public override void VerifyRenderingInServerForm(Control control)
{}
}
Script on the usercontrol:
<script type="text/javascript" src="https://www.google.com/jsapi"></script>
<script type="text/javascript">
console.log("Loading Google Charts...");
google.load('visualization', '1.0', { 'packages': ['corechart'] });
console.log("Google Charts loaded!");
google.setOnLoadCallback(function () {
...some code...
});
</script>
With firebug I found out that https://www.google.com/jsapi is loaded fine but only the first one of my console logs is printed.
I think it might be some kind of scope issue... The google variable will be defined in this script:
<script type="text/javascript" src="https://www.google.com/jsapi"></script>
But in this case it is inaccessible in the next script block. With normal rendering it works normally. Either the script isn't done loading before the google.load call or the google variable is now somehow defined in another scope because of the different rendering method.
If I look in firebug DOM the google variable is defined like here. But I found out that if I place a break point a the line: google.load('visualization', '1.0', { 'packages': ['corechart'] });
, I find that at this moment the google variable is not defined in the DOM. So it might also be somethink about loading the script. But the line <script type="text/javascript" src="https://www.google.com/jsapi"></script>
is before it and it should be executed synchronzly right? When I check the Net in firebug I also find that the file is downloaded correctly.
I might also need to mention that the usercontrol loading ajax code looks like this:
<div id="statisticsContent"> </div>
<script type="text/javascript">
$(document).ready(function () {
function getStatisticsView() {
var id = $(".chooseStatisticsToShow input:radio:checked").val();
var statisticsType = (id == $(".choosePlayingGroupDropDownList option:selected").val() ? 1 : 0);
$.ajax({
cache: false,
global: false,
type: "POST",
contentType: "application/json; charset=utf-8",
dataType: "json",
url: '/Services/StatisticsService.svc/GetStatisticsView',
data: JSON.stringify({
statisticsType: statisticsType,
id: id
}),
success: function (data) {
$("#statisticsContent").html(data.d.ViewHtml);
}
});
}
getStatisticsView();
$(".chooseStatisticsToShow").change(function () {
getStatisticsView();
});
});
</script>
I have made a sample project where I have recreated the issue. Download it here.