angular 指令的内容未呈现,除非您手动强制页面重排

angular directive's content not rendered, unless you force page reflow manually

我在 ui-bootstrap 和 angular 1.4 中遇到以下奇怪行为。当我将 footable table 指令放入名为 hpanel 的自定义 bootstrap 面板时,footable 最初比面板本身占据更多位置:

但是如果我调整屏幕大小(例如,通过折叠此处的开发人员工具面板),footable 指令会自行绘制并适合面板:

重要的是,我在使用 angular-c3 图表指令时遇到过类似的问题(它们加载不正确,超出了 hpanel 的大小,但在调整页面大小时表现良好),所以它可能不仅仅是一个损坏的指令。

你见过类似的东西吗?

详情:

下面是一个 HTML 模板,表示页面的非功能部分。我们有一个 hpanel 并且在其中应用了 table 和 angular-footable directive ^1.0.3

这是模板 (toolList.html):

<div class="content">
    <div class="row">
        <div class="col-lg-12">
            <div class="hpanel">
                <div class="panel-heading">
                    <div class="panel-tools">
                        <a class="showhide"><i class="fa fa-chevron-up"></i></a>
                        <a class="closebox"><i class="fa fa-times"></i></a>
                    </div>
                    Available tools.
                </div>
                <div class="panel-body">
                    <input type="text" class="form-control input-sm m-b-md" id="filter" placeholder="Search in table">
                    <table id="example1" class="footable table table-stripped toggle-arrow-tiny" data-page-size="8" data-filter=#filter>
                        <thead>
                        <tr>
                            <th data-toggle="true">Id</th>
                            <th>Class</th>
                            <th>Label</th>
                            <th>Description</th>
                            <th data-hide="all">Owner</th>
                            <th data-hide="all">Contributor</th>
                            <th data-hide="all">Inputs</th>
                            <th data-hide="all">Outputs</th>
                            <th data-hide="all">Base command</th>
                            <th data-hide="all">Arguments</th>
                            <th data-hide="all">Requirements</th>
                            <th data-hide="all">Hints</th>
                        </tr>
                        </thead>
                        <tbody>
                        <tr ng-repeat="tool in vm.tools">
                            <td><a ui-sref="tool-detail({id: tool.id})">{{tool.id}}</a></td>
                            <td>{{tool.tool_class}}</td>
                            <td>{{tool.label}}</td>
                            <td>{{tool.description}}</td>
                            <td>{{tool.owner}}</td>
                            <td>{{tool.contributor}}</td>
                            <td>{{tool.baseCommand}}</td>
                            <td>{{tool.arguments}}</td>
                            <td>{{tool.requirements}}</td>
                            <td>{{tool.hints}}</td>
                        </tr>
                        </tbody>
                        <tfoot>
                        <tr>
                            <td colspan="5">
                                <ul class="pagination pull-right"></ul>
                            </td>
                        </tr>
                        </tfoot>
                    </table>

                </div>
            </div>
        </div>
    </div>
</div>

footable 指令用于隐藏 table 的某些列并在单击 table 行时显示它们。它还提供分页。它似乎在页面加载时不起作用,但是当我调整页面大小时并且屏幕大小超过媒体类型边距(因此从中等大小的屏幕变成大屏幕 bootstrap css 条款),分页按钮出现,隐藏的列被隐藏。

以下是我在主模块中导入 footable 指令的方法 app.js:

require("footable/js/footable");
require("footable/js/footable.filter");
require("footable/js/footable.striping");
require("footable/js/footable.sort");
require("footable/js/footable.paginate");
require("footable/css/footable.core.css")
require("angular-footable");

angular.module("app", [
    ...,
    "ui.footable",
])

我使用 webpack 加载所有这些模块,并使用 bower 安装依赖项。

hpanel 只是一个 scss class,这里是它的定义:

/* Panels */
.hpanel > .panel-heading {
  color: inherit;
  font-weight: 600;
  padding: 10px 4px;
  transition: all .3s;
  border: 1px solid transparent;
}

.hpanel .hbuilt.panel-heading {
  border-bottom: none;
}

.hpanel > .panel-footer, .hpanel > .panel-section {
  color: inherit;
  border: 1px solid $border-color;
  border-top: none;
  font-size: 90%;
  background: $color-bright;
  padding: 10px 15px;
}

.hpanel.panel-collapse > .panel-heading, .hpanel .hbuilt {
  background: #fff;
  border-color: $border-color;
  border: 1px solid $border-color;
  padding: 10px 10px;
  border-radius: 2px;
}

.hpanel .panel-body {
  background: #fff;
  border: 1px solid $border-color;
  border-radius: 2px;
  padding: 20px;
  position: relative;
}


.hpanel.panel-group .panel-body:first-child {
  border-top: 1px solid $border-color;
}

.hpanel.panel-group .panel-body {
  border-top: none;
}

.panel-collapse .panel-body {
  border: none;
}

.hpanel {
  background-color: none;
  border: none;
  box-shadow: none;
  margin-bottom: 25px;
}

.panel-tools {
  display: inline-block;
  float: right;
  margin-top: 0;
  padding: 0;
  position: relative;
}

.hpanel .alert {
  margin-bottom: 0;
  border-radius: 0;
  border: 1px solid $border-color;
  border-bottom: none;
}

.panel-tools a {
  margin-left: 5px;
  color: lighten($color-text, 20%);
  cursor: pointer;
}

.hpanel.hgreen .panel-body {
  border-top: 2px solid $color-green;
}

.hpanel.hblue .panel-body {
  border-top: 2px solid $color-blue;
}

.hpanel.hyellow .panel-body {
  border-top: 2px solid $color-yellow;
}

.hpanel.hviolet .panel-body {
  border-top: 2px solid $color-violet;
}

.hpanel.horange .panel-body {
  border-top: 2px solid $color-orange;
}

.hpanel.hred .panel-body {
  border-top: 2px solid $color-red;
}

.hpanel.hreddeep .panel-body {
  border-top: 2px solid $color-red-deep;
}

.hpanel.hnavyblue .panel-body {
  border-top: 2px solid $color-navy-blue;
}

.hpanel.hbggreen .panel-body {
  background: $color-green;
  color: #fff;
  border:none;
}

.hpanel.hbgblue .panel-body {
  background: $color-blue;
  color: #fff;
  border:none;
}

.hpanel.hbgyellow .panel-body {
  background: $color-yellow;
  color: #fff;
  border:none;
}

.hpanel.hbgviolet .panel-body {
  background: $color-violet;
  color: #fff;
  border:none;
}

.hpanel.hbgorange .panel-body {
  background: $color-orange;
  color: #fff;
  border:none;
}

.hpanel.hbgred .panel-body {
  background: $color-red;
  color: #fff;
  border:none;
}

.hpanel.hbgreddeep .panel-body {
  background: $color-red-deep;
  color: #fff;
  border:none;
}

.hpanel.hbgnavyblue .panel-body {
  background: $color-navy-blue;
  color: #fff;
  border:none;
}

.panel-group .panel-heading {
  background-color: $color-bright;
}

.small-header .hpanel {
  margin-bottom: 0;
}

.small-header {
  padding: 0 !important;
}

.small-header .panel-body {
  padding: 15px 25px;
  border-right: none;
  border-left: none;
  border-top: none;
  border-radius: 0;
  //  background: $color-bright;
}

.panel-body h5, .panel-body h4 {
  font-weight: 600;
}

.small-header .panel-body h2 {
  font-size: 14px;
  font-weight: 600;
  text-transform: uppercase;
  margin: 0 0 0 0;
}

.small-header .panel-body small {
  color: lighten($color-text, 10%);
}

.hbreadcrumb {
  padding: 2px 0px;
  margin-top: 6px;
  margin-bottom: 0px;
  list-style: none;
  background-color: #fff;
  font-size: 11px;

  > li {
    display: inline-block;

    + li:before {
      padding: 0 5px;
      color: $color-navy-blue;
    }
  }

  > .active {
    color: lighten($color-text,20%);
  }
}

.wrapper {
  padding: 10px 20px;
}

.hpanel.collapsed .panel-body, .hpanel.collapsed .panel-footer {
  display: none;
}

.hpanel.collapsed .fa.fa-chevron-up:before {
  content: "\f078";
}
.hpanel.collapsed .fa.fa-chevron-down:before {
  content: "\f077";
}

.hpanel.collapsed.panel-collapse .panel-body {
  border-width: 0 1px 1px 1px;
  border-color: $border-color;
  border-style: solid;
}

.hpanel.collapsed .hbuilt.panel-heading {
  border-bottom: 1px solid $border-color;
}

body.fullscreen-panel-mode {
  overflow-y: hidden;
}

.hpanel.fullscreen {
  z-index: 2030;
  position: fixed;
  top: 0;
  left: 0;
  right: 0;
  bottom: 0;
  overflow: auto;
  margin-bottom: 0;
}

.hpanel.fullscreen .showhide {
  display: none;
}

.hpanel.fullscreen .panel-body {
  min-height: calc(100% - 77px);
}

这是 tool.module.js 文件,它使模板具有动画效果:

import angular from "angular";

var ToolResource = require("workflow/tool/tool.service");

class ToolListController {
    // @ngInject
    constructor($location, $stateParams, $state, tools) {
        this.$location = $location;
        this.$state = $state;
        this.$stateParams = $stateParams;

        this.tools = tools;
    }
}

// @ngInject
function routesList($stateProvider) {
    $stateProvider.state("tool-list", {
        url: "/tool",
        parent: "layout",
        templateUrl: "/app/workflow/tool/toolList.html",
        controller: "ToolListController",
        controllerAs: "vm",
        data: {
            pageTitle: "Tool",
            pareDesc: "List of tools, available for workflow construction.",
        },
        resolve: {
            ToolResource: "ToolResource",
            tools: function(ToolResource) {
                return ToolResource.query().$promise;
            }
        }
    });
}

module.exports = angular.module("tool", [])
  .service('ToolResource', ToolResource)
  .controller('ToolListController', ToolListController)
  .config(routesList);

tool.service.js:

module.exports = function ToolResource($resource) {
    return $resource('/api/tool/:id', {id: '@id'});
}

答案: 社区很棒!

所以,是的,指令中的一个错误导致它在从服务器获取数据之前自行绘制。通过错误修复,我刚刚向指令添加了 load-when="vm.tools" 属性,现在它工作正常。

谢谢 Alexryan、ziscloud、Walfrat 和其他 commenters/answerers。 Whosebug 和 Github 让我开心!

由于您是异步加载数据(如评论中所述),因此您的 html 在包含任何数据之前呈现。这意味着该指令可能会过早触发(如果它试图根据数据进行调整)。通常,在这种情况下,您需要在依赖于数据加载的 html 部分抛出一个 ng-if(并在其位置显示加载 gif 或其他内容)。您可以 运行 正在定义的数据本身的 ng-if,或者维护一个单独的布尔值,一旦承诺得到解决,您就可以设置它。

你在使用这个指令吗? https://github.com/ziscloud/angular-footable/blob/master/src/angular-footable.js。这是一个自制的(意思不是由 footable 的编辑完成的)指令,所以它不能正确地实现与 Angularjs.

一起工作

看代码似乎你必须使用属性 load-when 如果你想延迟网格的初始化,即使你在你的状态中使用了 resolve 属性,也值得测试it.load-when 在开始时应该是一个空数组,并且会在数组不再为空后触发加载,但是绑定的数据不会用于我所看到的初始化。

注意:我自己无法设置正确的 plnkr,我不知道您使用的版本(以及与哪个 jQuery 版本一起使用)并且在线链接似乎不可用。