4

angular jsを使用して要素をDOM内の別の場所に移動するにはどうすればよいですか?

私はそのような要素のリストを持っています

<ul id="list" ng-controller="ListController">
    <li ng-controller="ItemController"><div>content</div></li>
    <li ng-controller="ItemController"><div>content</div></li>
    <li ng-controller="ItemController"><div>content</div></li>
    <li ng-controller="ItemController">
        <div>content</div>
        <div id="overlay"></div>
    </li>
</ul>

私が達成しようとしているのは、#overlay をリスト内の場所から場所へ移動することです。非表示/非表示にフラグを立てるすべてのアイテムに重複を隠す必要はありません。

これがjqueryの場合、次のようなことができます:

$("#overlay").appendTo("#list li:first-child");

角度でこれを行う同等の方法はありますか?

4

2 に答える 2

11

あなたの明確化のおかげで、あなたがアイテムのリストを持っていることを理解できます. このリストで 1 つのアイテムを選択し (スワイプしますが、他のイベントも同様に可能性があります)、選択したアイテムの追加の DOM 要素 (div) を表示できるようにしたいと考えています。他の項目が選択されている場合は、選択を解除する必要があります。この方法では、1 つの項目だけに追加の div が表示されます。

上記の理解が正しければ、次のような単純な ng-repeat および ng-show ディレクティブでこれを解決できます。

<ul ng-controller="ListController">
    <li ng-repeat="item in items">
        <div ng-click="open(item)">{{item.content}}</div>
        <div ng-show="isOpen(item)">overlay: tweet, share, pin</div>
    </li>
</ul>

コントローラー内のコードは次のようになります (一部のみを示します)。

$scope.open = function(item){
    if ($scope.isOpen(item)){
        $scope.opened = undefined;
    } else {
        $scope.opened = item;
    }        
};

$scope.isOpen = function(item){
    return $scope.opened === item;
};

ここに完全な jsFiddle があります: http://jsfiddle.net/pkozlowski_opensource/65Cxv/7/

DOM 要素が多すぎることに懸念がある場合は、ng-switch ディレクティブを使用して同じことを実現できます。

<ul ng-controller="ListController">
    <li ng-repeat="item in items">
        <div ng-click="open(item)">{{item.content}}</div>
        <ng-switch on="isOpen(item)">
            <div ng-switch-when="true">overlay: tweet, share, pin</div>
        </ng-switch>        
    </li>
</ul>

これが jsFiddle です: http://jsfiddle.net/pkozlowski_opensource/bBtH3/2/

于 2012-09-14T19:34:01.297 に答える
4

読者 (私) の演習として、これを達成するためのカスタム ディレクティブを試してみました。これが私が思いついたものです(何度も失敗した後):

<ul ng-controller="ListController">
    <li ng-repeat="item in items">
        <div singleton-overlay>{{item.content}}</div>
    </li>
</ul>

現在オーバーレイがある要素がある場合は、その要素を格納するサービスが必要です。(「サービス + ディレクティブ」の方が「コントローラー + ディレクティブ」よりも再利用可能なコンポーネントになると思うので、これにはコントローラーを使用しないことにしました。)

service('singletonOverlayService', function() {
    this.overlayElement = undefined;
})

そしてディレクティブ:

directive('singletonOverlay', function(singletonOverlayService) {
    return {
        link: function(scope, element, attrs) {
            element.bind('click', moveOrToggleOverlay);

            function moveOrToggleOverlay() {
                if (singletonOverlayService.overlayElement === element) {
                    angular.element(element.children()).remove();
                    singletonOverlayService.overlayElement = undefined;
                } else {
                    if (singletonOverlayService.overlayElement != undefined) {
                        // this is a bit odd... modifying DOM elsewhere
                        angular.element(singletonOverlayService.overlayElement.children()).remove();
                    }
                    element.append('<div>overlay: tweet, share, pin</div>')
                    singletonOverlayService.overlayElement = element;

jsFiddle: http://jsfiddle.net/mrajcok/ya4De/

ただし、実装は少し型にはまらないと思います...ディレクティブは、独自の要素に関連付けられたDOMを変更するだけでなく、現在オーバーレイを持つ要素に関連付けられているDOMも変更する可能性があります。

スコープに $watches を設定し、シングルトンでスコープ オブジェクトを保存および変更しようとしましたが、moveOrToggleOverlay 関数内からスコープを変更したときに $watches を起動できませんでした。

于 2012-09-18T02:40:44.537 に答える