是否可以动态更改 angular bootstrap uib-dropdown templateUrl?

Is it possible to change angular bootstrap uib-dropdown templateUrl dynamically?

我想在用户单击其中一个 <li> 时动态更改 uib-dropdown 模板,就像他可以 "navigate" 在该下拉列表中一样。

我试图通过 templateUrl 实现它,但是 ng-templates 和独立部分都不能成功地动态更改下拉模板,就像 plunkr 演示的那样。

我的目标是通过此下拉菜单创建多面导航以直观地构建查询,如 Fieldbook's Sprint tracker (account required), which is something really like Pure Angular Advanced Searchbox 中所示,但我在使用此库时遇到了很多问题。

仅使用 AngularJS 和 angular-bootstrap 是否可以实现?

编辑:您应该使用控制器变量分配 template-url 的值,该变量随着用户 select 的任何选项而改变,然后您 "repaint" 组件,这样 "new" 下拉菜单是 "repainted" 新模板。

是的,根据 the official documentation,这是可能的,尽管我以前从未这样做过。

您可以指定一个名为 template-urluib-dropdown-menu 设置

根据文档

default value is none

you may specify a template for the dropdown menu

演示(尝试最后一个):

http://plnkr.co/edit/1yLmarsQFDzcLd0e8Afu?p=preview

如何让它工作?

根据你的 plunkr,你应该改变

<div class="input-group" uib-dropdown auto-close="disabled">
    <input type="text" class="form-control" placeholder="Click to start a visual query search..." autocomplete="off" uib-dropdown-toggle/>
    <ul class="dropdown-menu" role="menu" ng-if="ctrl.dropdownReady" uib-dropdown-menu template-url="{{ctrl.dropdownTemplateFour}}">
    </ul>
    <span class="input-group-btn">
    <button type="submit" name="search" id="search-btn" class="btn btn-flat"><i class="fa fa-search"></i>
    </button>
    </span>
</div>

<div class="input-group" uib-dropdown auto-close="disabled"  ng-if="ctrl.dropdownReady">
    <input type="text" class="form-control" placeholder="Click to start a visual query search..." autocomplete="off" uib-dropdown-toggle/>
    <ul class="dropdown-menu" role="menu" uib-dropdown-menu template-url="{{ctrl.dropdownTemplateFour}}">
    </ul>
    <span class="input-group-btn">
    <button type="submit" name="search" id="search-btn" class="btn btn-flat"><i class="fa fa-search"></i>
    </button>
    </span>
</div>

其中ng-if="ctrl.dropdownReady"移动到div.input-group

并改变

vm.dropdownReady = false;
console.log('vm.dropdownReady =', vm.dropdownReady, ' partial = ', partial);
switch (template) {
  case 'word':
    partial ? vm.dropdownTemplateFour = 'word-dropdown-dom.template.html' : vm.dropdownTemplateThree = 'word-dropdown-dom.html';
    break;
  case 'main':
    partial ? vm.dropdownTemplateFour = 'main-dropdown-dom.template.html' : vm.dropdownTemplateThree = 'main-dropdown-dom.html';
    break;
}
vm.dropdownReady = true;

vm.dropdownReady = false;
console.log('vm.dropdownReady =', vm.dropdownReady, ' partial = ', partial);
switch (template) {
  case 'word':
    partial ? vm.dropdownTemplateFour = 'word-dropdown-dom.template.html' : vm.dropdownTemplateThree = 'word-dropdown-dom.html';
    break;
  case 'main':
    partial ? vm.dropdownTemplateFour = 'main-dropdown-dom.template.html' : vm.dropdownTemplateThree = 'main-dropdown-dom.html';
    break;
}
$timeout(function(){
  vm.dropdownReady = true;
});

其中有一个 $timeout 包裹着 vm.dropdownReady = true;。你应该手动注入 $timeout;

保持菜单打开

根据documentation,我们可以用is-open属性选择下拉菜单的初始状态。我们可以使用 on-toggle attr 监听切换事件。所以如果我们想在用户点击输入后保持菜单打开,我们应该像这样设置 uib-dropdown 的属性:

<div class="input-group" uib-dropdown auto-close="disabled"  ng-if="ctrl.dropdownReady" is-open="ctrl.open" on-toggle="ctrl.toggled(open)">

在控制器中:

vm.toggled = function (open) {
    // the parameter `open` is maintained by *angular-ui/bootstrap*
    vm.open=open;//we don't need to init the `open` attr, since it's undefined at beginning
}

完成这些操作后,一旦菜单打开,除非用户再次单击输入,否则它不会关闭。

为什么?

让我们检查一下 snippet:

$templateRequest(self.dropdownMenuTemplateUrl)
    .then(function(tplContent) {
    templateScope = scope.$new();
    $compile(tplContent.trim())(templateScope, function(dropdownElement) {
        var newEl = dropdownElement;
        self.dropdownMenu.replaceWith(newEl);//important
        self.dropdownMenu = newEl;
        $document.on('keydown', uibDropdownService.keybindFilter);
    });
});

上面的代码片段显示了 angular-ui/bootstrap 如何使用 template-url 属性来检索模板和生效。它用新创建的元素替换原始 ul 元素。这就是为什么在单击 ul 后缺少 uib-dropdown-menutemplate-url 的原因。由于它们不存在,您不能再更改模板-url 与 angular 绑定。

vm.dropdownReady = false; 之后立即执行 vm.dropdownReady = true; 不起作用的原因是 angular 没有机会检测到此更改并执行 "ng-if" 以实际删除dom。您必须使 vm.dropdownReady 的切换异步,以便 angular 有机会实现此目的。