Google チャート API のチャートを含むユーザー コントロールがあります。
ユーザーコントロールがサーバーによってロードおよびレンダリングされると、通常の方法ですべてが期待どおりに機能します。しかし、ajax Webサービスを使用してコントロールを非同期にレンダリングし、ajaxでhtmlを返してページに追加すると、firebugでスクリプトエラーが発生します(chromeはそれをReferenceErrorと呼びます):
「Google が定義されていません」
私のプロジェクトは、JavaScript を使用した ASP.Net MVP Webforms です。
問題を再現したサンプルプロジェクトを作成しました。ここからダウンロードしてください。
コントロール レンダラー コード:
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);
}
(「フォームに必要」というエラーを省略するには、コントロールが追加されたページにフォームがあります)
public class PageForRendering : Page
{
public override void VerifyRenderingInServerForm(Control control)
{}
}
ユーザーコントロールのスクリプト:
<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>
firebug を使用すると、https://www.google.com/jsapiが正常に読み込まれていることがわかりましたが、コンソール ログの最初の 1 つだけが出力されます。
ある種のスコープの問題かもしれないと思います... google 変数はこのスクリプトで定義されます:
<script type="text/javascript" src="https://www.google.com/jsapi"></script>
ただし、この場合、次のスクリプト ブロックではアクセスできません。通常のレンダリングでは正常に動作します。google.load 呼び出しの前にスクリプトの読み込みが完了していないか、レンダリング方法が異なるために google 変数が何らかの形で別のスコープで定義されています。
firebug DOM を見ると、google 変数はhereのように定義されています。しかし、ブレークポイントを行:google.load('visualization', '1.0', { 'packages': ['corechart'] });
に配置すると、現時点では google 変数が DOM で定義されていないことがわかりました。そのため、スクリプトのロードについても考えているかもしれません。しかし、行<script type="text/javascript" src="https://www.google.com/jsapi"></script>
はその前にあり、同期して実行する必要がありますよね? firebug でネットをチェックすると、ファイルが正しくダウンロードされていることもわかります。
また、ajax コードをロードするユーザーコントロールが次のようになっていることにも言及する必要があるかもしれません。
<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>
問題を再現したサンプルプロジェクトを作成しました。ここからダウンロードしてください。