如何使用angular.js在DOM周围移动视图?

时间:2012-09-14 16:34:29

标签: javascript angularjs

如何使用角度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");

是否有相同的方法在角度中执行此操作?

2 个答案:

答案 0 :(得分: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/

答案 1 :(得分:4)

作为读者(我)的练习,我想尝试一个自定义指令来实现这一目标。这是我想出的(经过多次尝试失败后):

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

需要服务来存储当前具有叠加层的元素(如果有)。 (我决定不使用控制器,因为我认为'service + directive'会产生比'controller + directive'更可重用的组件。)

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。

我尝试在示波器上设置$ watch并使用单例存储并修改范围对象,但是当我从moveOrToggleOverlay函数内部更改范围时,我无法触发$ watches。