5

WebアプリでUIにTwitterBootstrapを使用しています。特にそのアラートコンポーネント。Bootstrapのアラートをラップする単純なAngularサービスを作成して、Angularコードの平和からユーザーに通知できるようにしたいと思います。このような:

Informer.inform("message", "ERROR"); // will result in alerting with `alert-error` class
Informer.inform("message", "INFO"); // will result in alerting with `alert-info` class

<body>私の考えは、テンプレートを:の最後に追加することです。

<div class="alert {{alertClass}} fade in informer" id="informer">
    <button type="button" class="close" data-dismiss="alert">×</button>
    <div class="valignCenterWrapper">
        <div class="valignCenter" id="informerMessage">
            {{message}}
        </div>
    </div>
</div>

このようなもの:

grfx.factory("Informer", function() {
    return {
        inform : function(message, type) {
            // Here be dragons. How can I compile/append the template.

            $("#inform").alert();
        }
    };
});

私が知りたい唯一のこと:これをjQueryではなくangularで書くにはどうすればよいですか?上記のコードは開始に適していますか?インターネットの人々は、 DOM操作にはディレクティブのみを使用する必要があると言っています。しかし、私はそれを理解していません。ディレクティブを適用するための既存のマークアップがありません。いくつかの計算/ユーザーの相互作用の結果として、アラートがページに追加されます。temlateをコンパイルして本体のどこかに追加するには、どのサービス(、、)を使用する必要がありますか$compile$parse$document

編集:コントローラーの外部でangularjsサービスを取得することも可能ですか?通常のJSコードで書けるようにgetServiece("Informer").inform("", "")

編集2:わかりました、私が今持っているもの:

grfx.factory("Informer", function($compile, $rootScope) {
    return {
        inform : function(message, type) {
            var scope = $rootScope.$new();

            scope.message = message;
            scope.type = type;

            $(document.body).append($compile("<div class='alert {{type}} fade in informer' id='informer'><button type='button' class='close' data-dismiss='alert'>×</button><div class='valignCenterWrapper'><div class='valignCenter' id='informerMessage'>{{message}}</div></div></div>")(scope));
        }
    };
});

このコードを使用すると、コントローラーから注入されたサービスを使用できます。しかし、Angularコードの外部でサービスを呼び出そうとすると問題が発生します:

angular.element(document).injector().get("Informer").inform("Message", "alert-error");

これはポップアップを表示し{{message}}ます。たとえば、テンプレートが正しくコンパイルされません。

4

2 に答える 2

8

AngularJSでは、モデルの操作に焦点を当てる必要があります。Informerサービスも例外ではありません。モデルのみを保持し、DOMの操作に関係するべきではありません。DOM操作=ディレクティブの経験則は非常に優れており、それに従うと多くの頭痛の種を減らすことができます。

手元の問題に戻ると、解決策は、モデルの操作に焦点を当てたサービスと、このモデルを表示するためのディレクティブを用意することです。サービスから始めましょう:

app.factory('Informer', function(){

  var messages = [];  
  var Informer = {};

  Informer.inform = function(msg, type) {
    messages.push({
      msg: msg,
      type: type
    });
  };

  Informer.allInfos = function() {
    return messages;
  };

  Informer.remove = function(info) {
    messages.splice(messages.indexOf(info), 1);
  };  

  return Informer;
});

このサービスの準備ができたら、コントローラーで(または他のサービス内でも)簡単に使用できます。

app.controller('MainCtrl', function($scope, Informer) {

  Informer.inform("error message", "error");
  Informer.inform("info message", "info");

  $scope.allInfos = Informer.allInfos;  
  $scope.remove = Informer.remove;
});

最後に、アラートをレンダリングするには、ブートストラップのマークアップを直接使用するか、それをカプセル化する非常に単純なディレクティブを記述します。ここでは、 http://angular-ui.github.com/bootstrap/からのアラートディレクティブを使用しています

<body ng-controller="MainCtrl">
    <alert ng-repeat="alert in allInfos()" type="alert.type" close="remove(alert)">{{alert.msg}}</alert>
  </body>

もちろん、このリポジトリのディレクティブを使用する必要はありません。独自のディレクティブを作成するか、必要に応じて生のマークアップを使用できます。

これは、実際の例を示すプランカーです:http://plnkr.co/edit/VxAcjHFhxXODFB5iAfyX?p= preview

総括する:

  • 経験則として、ディレクティブの外部でDOM操作を行わないでください
  • モデルを扱うサービスは、モデルのプレゼンテーションから切り離す必要があります

また、 AngularJSを学習しながら、プロジェクトからjQueryを削除することをお勧めします。このようにして、AngularJS-zen状態にすばやく入ることができます!

于 2013-02-11T10:16:00.080 に答える
3

角度のある方法は、domをできるだけ手で操作することではないと私は信じています。そして、それを操作する必要がある場合でも、ディレクティブ内でのみ実行してください。

したがって、jQueryとは異なり、モデルを作成し、バインディングを使用してdomを変更する方法があります。

そのため、私が選択する方法は、レイアウトテンプレートのどこかにバインドされているInformerControllerを持ち、現在のインフォームの配列を反復処理して直接描画することです。

app.controller('InformersController', function($scope, InformerService) {
    $scope.informs = InformerService.get();
    $scope.close = function (index) {
          InformerService.close(index)
    }
});

そしてあなたのテンプレートで:

<div ng-controller="InformersController">
     <div ng-repeat="inform in informs">
         <div class="alert {{inform.alertClass}} fade in informer">
            <button type="button" ng-click="close($index)" class="close">×</button>
            <div class="valignCenterWrapper">
                <div class="valignCenter">
                    {{inform.message}}
                </div>
            </div>
        </div>
     </div>
 </div>

どこからでもアラートを表示する必要がある場合は、それを使用InformerServiceしてコントローラーに挿入し、それを使用してデータを追加します。

app.service('InformerService', function () {

    var informs = [];
    this.get = function () {
        return informs;   
    };
    this.inform = function (message, type) {
        informs.push({
            alertClass: 'alert-' + type,
            message: message
        });
    }
    this.close = function (index) {
       informs.splice(index, 1);
    }

});

例えば:

app.controller('SomeController', function($scope, InformerService) {
    $scope.doError = function (msg, type) {
        InformerService.inform(msg, type);
    };
});

そしてあなたのテンプレートで:

<div class="well" ng-controller="SomeController">
    <button class="btn btn-danger" ng-click="doError('Hello', 'error')">Error</button>  
    <button class="btn btn-info" ng-click="doError('Hello', 'info')">Info</button>  
</div>

あなたはこのフィドルでそれをすべて一緒に見ることができます:http://jsfiddle.net/zc3YH/6/

于 2013-02-11T09:31:30.823 に答える