6

大規模なアプリケーションでは、アプリケーションのモジュール性を高めるために、Webアプリケーションを個別の部分ページに編成する場合があります。場合によっては、Angular$http.getまたはJQuery$.loadのいずれかを使用してXHRまたはAjaxリクエストを介してロードされたページの一部をコンパイルすると、エラーが発生します。

シナリオを例として使用すると、正確にコハナPHPフレームワークを使用しているため、サーバーレベルでWebアプリケーションのモジュール性を制御できます。いつものように、すべてのテンプレートとページはビューに分離され、すべてのHTML、JS、CSSがプレゼンテーション層に一緒に残されます。

これにより、クライアント側の処理でJavascript MVW / MVCスタックを実装するための大きな柔軟性が得られます。これは、私のWebアプリがバックエンドアプリケーションからデータをフェッチするためのAJAX要求に大きく依存しているためです。私のシナリオでは、AngularJS以下を使用して、モデルからのデータがクライアントにどのように表示されるかについての単純な疑似です。

コハナモデル>コハナコントローラー>コハナビュー>XHR>JQuery \ Angular> DOM

私のアプリケーションでの私の役割の1つは、アプリケーションを解決するために、実際にバンプを与えて、代謝ドリンクを数本飲ませることです。モーダルダイアログがあり、ページの一部がサーバーからXHRを介して読み込まれ、選択したDOMにアタッチされている場所です。

問題は、Angularが部分ページをコンパイルしようとしたときに、ng-controllerディレクティブが見つかったときに、処理されたディレクティブを参照する関数を探すことです。DOMパーサーによってまだ評価されていないため、コントローラーが見つからない場合にエラーが発生しました。ただし、部分ページをロードする直前にアプリケーションのどこかで関数を事前に削除すると、すべて問題ありません。以下は、リンクをクリックしたときにリンクディレクティブから呼び出されるダイアログサービスを設定する方法の例です。

var dialogService = angular.module('dialog.service', []);
dialogService.factory('Dialog', function($http,$compile){
    var dialogService = {};
    dialogService.load = function(url, scope){
        $("#dialog:ui-dialog").dialog( "destroy" );
        $("#dialog").attr('title','Atlantis');

        $http.get(url).success(function (data) {
            html = $compile(data)(scope);
            $('#dialog-content').html(html);

            $("#dialog").dialog({
                width: '600px',
                buttons: {
                    "Ok": function() {
                        $( this ).dialog( "close" );
                        return true;
                    },
                },
                close: function(){
                    if (typeof (onClose) == 'function') { onClose(); }
                },
            });
        });
    }

    return dialogService;
});

いくつかの調査の後、私はいくつかの解決策を見つけ、私のような他の初心者のための私の答えについて仲間と共有しました。(私の英語はごめんなさい)。

4

2 に答える 2

5

このセットアップではAngularJSに問題はありません。他のJSの第一人者はすでに解決策を知っていて、別のクールなWeb開発ツールやフレームワークを発明している間私たちと共有するのに非常に忙しいかもしれません。それを続けても大丈夫です。これはクールまたは最終的な解決策ではない可能性があります。改善点やヒントを私たちと共有してください!

この問題を克服するには、セットアップするための戦略が必要です。情報が流れる間に脳が消化されるように、サンプルコードから始めましょう。以下のコードは、JQueryを使用してモーダルダイアログを作成するプレースホルダーであり、Ajaxコンテンツが挿入されます。

<div ng-app="asng" id="dialog" title="" style="display:none">
     <div id="dialog-content"></div>
</div>

基本的な知識として、DOMパーサーがどのように機能しているかを理解する必要があります。DOMP(DOMパーサー)はマルチスレッドであると考えるかもしれません。それが、複数の外部リソースを並行してロードできる理由です。実際、DOMPは、DOM要素のインデックスを上から下に解析している間はシングルスレッドです。以下は、#dialog-contentDIV要素にロードする部分ページの例です。

<script language="JavaScript" type="text/javascript">
    function Transaction ($scope,$http){
        $scope.items = [{"country":"VN","quantity":"100"}];
        $scope.country_name = $scope.items;
    }
</script>

<style>
</style>

<div id="transaction-panel" class="user" data-ng-controller="Transaction">
        <form id="{{ form_name }}" action="">
        Country : [[ items.country ]] </br>
        Total : [[ items.quantity ]]
    </form>
</div>

ng-controllerディレクティブを使用して要素の直前にスクリプトブロックを配置しましたが、実際にはこれらの部分はまだエラーを出します。実際にはそうではありません。私たちが取り組む必要のある部分は、AngularJSコンパイルサービスが部分的なDOMをコンパイルする方法です。上記の私の質問の部分に戻って、コンパイルする行がどこにあるかを調べてみましょう。

html = $compile(data)(scope);
$('#dialog-content').html(html);

上記の最初の行は、データ変数でDOMをコンパイルし、ルートDOMに挿入します。残念ながら、最初の行はエラーを叫びます:コントローラートランザクションが見つかりません。

これは、部分ページのスクリプトブロックがルートDOMPに挿入されていないため、DOMPパーサーによってまだ評価されていないために発生します。これでライトOKが表示されたので、新しいDOMを挿入してコンパイル戦略を少し変更する必要があります。次に、挿入されたDOMの外観の例を以下に解析します。-

html = $('#dialog-content').html(data);
$compile(html)(scope);

スリムでシンプルなソリューションであるため、DOM解析の単純な概念を無視したという理由だけで、この問題を解決するのに朝の頭を悩ませることはほとんどありませんでした。

于 2012-10-20T09:17:21.430 に答える
0

あなたがやろうとしていることを理解できたら、ここに簡単な例を示します。

AJAX 経由で Django フォームに投稿し、ページ内のフォーム コンテンツを返されたマークアップに置き換えたいと考えていました。返されたマークアップには、読み込み時に実行する必要がある ng-controller が含まれています。

.controller('MyForm', function($element, $compile, $scope){
    var scope = $scope;
    var $theForm = $element;
    var $formBlock = $element.find('.the_form');  // is replaced by the form response
    $element.find('.submit_the_form').click(function(){
        // submit the form and replace contents of $formBlock
        $.post($theForm.attr('action'), $theForm.serialize(), function(response){
            var newstuff = $formBlock.html(response);
            $compile(newstuff)(scope); // loads the angular stuff in the new markup
        });
    });
})

あなたが興味を持っている行は $compile(newstuff)(scope); だと思います。

編集:Crikey、今朝他のマークアップでこれを試してみましたが、うまくいきませんでした。理由はわかりませんでした。新しいマークアップで ng-model が割り当てられたフィールドがない場合、$compile は実行されないことが判明しました。追加した:

<input type="hidden" name="dummy" value="0" ng-model="dummy"/>

...そして今それはコンパイルされます。

于 2015-05-19T23:27:42.123 に答える