0

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">&nbsp;</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>



問題を再現したサンプルプロジェクトを作成しました。ここからダウンロードしてください

4

1 に答える 1

1

サービスが応答を送信し、$("#statisticsContent").html(data.d.ViewHtml);ブラウザーを使用して追加した後、html を解釈し、スクリプトの読み込みと実行を並行して開始します。どうすればそれを知ることができますか? ただ経験してください-私のプロジェクトでは、ブラウザーを挿入しようとするたびに<script src='...'>、スクリプトがロードされるのを待たずscript、カスタムコードを含む次のタグがすぐに実行されました。

これはあなたのケースであり、ロードを待ってjsapiから、パッケージをロードしてチャートのレンダリングを実行するコードを実行する必要があります。コードは次のとおりです。

<div id="chart_div"></div>

<script type="text/javascript" src="https://www.google.com/jsapi"></script>
<script type="text/javascript">
    waitForGoogleApiAndLoadPackages();
    function waitForGoogleApiAndLoadPackages() {
        if (typeof (google) === 'undefined')
            setTimeout(waitForGoogleApiAndLoadPackages, 100);
        else {
            google.load('visualization', '1.0', { 'callback': 'renderChart', 'packages': ['corechart'] });
        }
    }

    function renderChart() {
        var data = new google.visualization.DataTable();
        data.addColumn('string', 'Topping');
        data.addColumn('number', 'Slices');
        data.addRows([['Mushrooms', 3], ['Onions', 1], ['Olives', 1], ['Zucchini', 1], ['Pepperoni', 2]]);

        var options = { 'title': 'How Much Pizza I Ate Last Night', 'width': 400, 'height': 300 };

        var chart = new google.visualization.PieChart(document.getElementById('chart_div'));
        chart.draw(data, options);
    }
</script>

もう 1 つの興味深い部分は、機能のelseブロックwaitForGoogleApiAndLoadPackagesです。これは、google.load によってページが空白になるのはなぜですか?で説明されている問題の回避策です。質問。


からの引用google.load によってページが空白になるのはなぜですか? :

google.load が document.write() を使用してページにスクリプトを追加しているように見えます。これをページの読み込み後に使用すると、html が消去されます。

于 2013-04-25T09:43:29.623 に答える