如何正确地使嵌套指令与jQuery Layout插件和AngularJS一起使用?

时间:2013-11-06 15:37:50

标签: jquery angularjs layout plugins angularjs-directive

我正在尝试将jQuery Layout plugin合并到我的AngularJS项目中。

我有一个只使用jQuery,jQuery-UI和jQuery Layout插件构建的工作版Here

现在我想在AngularJS中拥有相同的东西。

我在将默认值传递给插件的嵌套实例方面遇到了麻烦。

一个简单的例子就是这样:

HTML:

<body ng-app="myApp">
    <div id="outer-container" layout-container>
        <div class="ui-layout-west pane">WEST</div>
        <div class="ui-layout-center pane">MIDDLE</div>
        <div class="ui-layout-east pane">EAST</div>
    </div>
</body>

JavaScript的:

var app = angular.module('myApp', []);

app.directive('layoutContainer', function() {
    return {
        scope: {},
        link: function (scope, element, attrs) {
                var layout = element.layout({
                    west: {
                      resizable : true,
                      initClosed : false,
                      livePaneResizing: true,
                      size: 150
                    },
                    east: {
                      resizable : true,
                      initClosed : false,
                      livePaneResizing: true,
                      size: 150
                    }
                });
        }
    }
});

jsFiddle

然而,当我这样做时,我试图复制的例子不起作用:

HTML:

<body ng-app="myApp">
    <div id="outer-container" layout-container>
        <div class="ui-layout-west pane">WEST</div>
        <div class="ui-layout-center pane">
            <div id="middle-container" layout-middle>
                <div class="ui-layout-north pane top-panel">
                    <div id="top-container" layout-top>
                        <div class="ui-layout-center pane">TOP LEFT</div>
                        <div class="ui-layout-east pane">TOP RIGHT</div>
                    </div>
                </div>
                <div class="ui-layout-center pane bottom-panel">
                    <div id="bottom-container" layout-bottom>
                        <div class="ui-layout-center pane">BOTTOM LEFT</div>
                        <div class="ui-layout-east pane">BOTTOM RIGHT</div>
                    </div>
                </div>
            </div>
        </div>
        <div class="ui-layout-east pane">EAST</div>
    </div>
</body>

JavaScript的:

var app = angular.module('myApp', []);

app.directive('layoutContainer', function() {
    return {
        scope: {},
        link: function (scope, element, attrs) {
                var layout = element.layout({
                    west: {
                      resizable : true,
                      initClosed : true,
                      livePaneResizing: true,
                      size: 350
                    },
                    east: {
                      resizable : true,
                      initClosed : true,
                      livePaneResizing: true,
                      size: 350
                    }
                });
        }
    }
});

app.directive('layoutMiddle', function() {
    return {
        scope: {},
        link: function (scope, element, attrs) {
                var layout = element.layout({
                    north: {
                          size: .5,
                          livePaneResizing: true
                        }
                });
        }
    }
});

app.directive('layoutTop', function() {
    return {
        link: function (scope, element, attrs) {
            angular.element(element).layout({
                east: {
                      size: .5,
                      livePaneResizing: true
                    }
            });
        }
    };
});

app.directive('layoutBottom', function() {
    return {
        link: function (scope, element, attrs) {
            angular.element(element).layout({
                east: {
                      size: .5
                    }
            });

        }
    };
});

jsFiddle

我的目标是让面板TOP LEFTTOP RIGHTBOTTOM LEFTBOTTOM RIGHT默认占用所有空间。

编辑:问题在于指令是异步编译的。顺序编译指令的正确AngularJS方法是什么[在这种情况下,layoutContainer必须先是,然后是layoutMiddle,然后是其余的layoutTop和layoutBottom]?

1 个答案:

答案 0 :(得分:0)

Angular的指令编译和链接是顺序的,但它的顺序与你所假设的相反。元素在其后代之前编译,并在其祖先之前链接。

解决此问题的一种方法是在link()期间构建一系列延迟操作,然后在Container转弯后以lifo顺序清空此堆栈。

查看this fork of your fiddle进行演示和一种可能的解决方案。扭转element.layout()调用顺序的差异如下:

  1. 创建了一个名为lifoRunner的服务,它具有用于构建函数堆栈的push()方法和一个弹出堆栈并运行每个方法直到堆栈为空的runStack()方法。 / LI>
  2. 注入lifoRunner作为每个指令的依赖。
  3. 将每个链接功能的主体迁移到新功能。现在,每个link()方法都将其新的封装函数传递给lifoRunner.push(),而不是执行以前的代码。
  4. 最后一个要链接的指令layoutContainer在调用lifoRunner.runStack()后立即调用lifoRunner.push()。其他三个指令链接方法只调用lifoRunner.push()
  5. 为了进一步说明这一点,我还在每个指令的相同位置添加了两次console.log()调用。

    • 在link()的正文中,在致电lifoRunner.push()之前,我log("Link <DirectiveName>")
    • 在传递给lifoRunner.push()的函数的第一行,我log("Stack <DirectiveName>")

    在加载小提琴时,您会看到单元格现在按照您的预期大小调整,您将在控制台中找到以下内容以建立评估顺序:

    Link Top
    Link Bottom
    Link Middle
    Link Container
    Stack Container
    Stack Middle
    Stack Bottom
    Stack Top
    

    干杯!