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

感谢您的澄清,我可以理解您有一个项目清单。您希望能够在此列表中选择一个项目(滑动但可能还有其他事件),然后为所选项目显示一个额外的 DOM 元素 (div)。如果另一个项目被选中,它应该被取消选择 - 这样只有一个项目应该显示一个额外的 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 回答