Angular 表达式中加载的 JS 指令

Angular JS Directive loaded in expression

我是 Angular 的新手,找到了大量关于指令和嵌套的资源,但似乎无法让这个简单的示例发挥作用。所以基本上我正在制作一个标签集,我有一个 HTML 模板:

tabset.html

<div>
    <ul>
        <li ng-repeat="tab in tabset.tabs" ng-class="{active:tabset.current()==$index}">
            <a href ng-click="tabset.current($index)">{{tab}}</a>
        </li>
    </ul>
    <div>
        <div ng-repeat="pane in tabset.panes">
            <div ng-show="tabset.current()==$index">
                {{pane.contents}}
            </div>
        </div>
    </div>
</div>

还有一个搜索表单模板:

search-form.html

<div>
    <form name="ytSearch" ng-submit="YTCtrl.submit()" novalidate>
        <label for="search_box">Search For: </label>
        <input id="search_box" ng-model="YTCtrl.searchString"/>
        <br>
        <label for="location">Location: </label>
        <input id="location" ng-model="YTCtrl.location"/>
        within
        <input type="numeric" value="100" ng-model="YTCtrl.locationRadius" />
        <select ng-model="YTCtrl.locationUnit">
            <option value="ft">Feet</option>
            <option value="m">Meters</option>
            <option value="mi">Miles</option>
            <option value="km">Kilometers</option>
        </select>
        <br>
        <label for="search_order">Sort By: </label>
        <select id="search_order" ng-model="YTCtrl.order">
            <option value="relevance">Relevance</option>
            <option value="date">Date</option>
            <option value="rating">Rating</option>
        </select>
        <br>
        <button id="search">
            Search
        </button>
    </form>
</div>

还有一个简单的应用程序文件,其中包含 2 个指令来处理每个模板:

app.js

(function() {
    angular.module("JHYT", [])
        .directive("sidebarTabset", function($compile) {
            return {
                restrict : 'E',
                templateUrl : 'tabset.html',
                controller : function($scope, $compile, $http) {
                    this._current = 0;
                    this.current = function(i) {
                        if (i != null)
                            this._current = i;
                        return this._current;
                    };
                    this.tabs = ['Search', 'Favorite'];
                    this.panes = [{
                        contents : "<search-form></search-form>"
                    }, {
                        contents : "Favorite Pane"
                    }];
                },
                controllerAs : 'tabset',
            };
        }).
        directive("searchForm", function() {
            return {
                restrict : 'E',
                templateUrl : 'search-form.html',
                controller : function($scope, $compile, $http) {
                    this.searchString = '';
                    this.location = '';
                    this.locationRadius = '';
                    this.locationUnit = 'mi';
                    this.order = 'relevance';
                    this.submit = function() {
                        console.log("Submit");
                    };
                },
                controllerAs : 'YTCtrl',
            }
        });
})();

所以你可能会说,这个想法是能够将 JSON 对象发送到选项卡集中(可能通过服务)并让它构建一个动态选项卡集,它实际上与我期望它。不起作用的是,在第一个选项卡中,<search-form></search-form> 的内容未被处理,并且标签在内容区域中呈现为纯文本。

由于这是一个选项卡集,"child" 不需要 "parent" 中的任何内容,搜索表单和选项卡本身没有范围依赖性。在看到一些嵌套结构的示例后,我尝试使用 link 和编译函数,但似乎无法使它们工作。

如何处理该变量的内容,以便使用其模板呈现元素指令?

编辑:

@sielakos 给了我我所希望的,一个可重复使用的方法。

我在我的模块中添加了一个名为 compile 的指令,它添加了一个包装器以允许我使用纯文本:

.directive("compile", function($compile){
            return {
                restrict: 'A',
                link: function(scope, element, attr){
                    attr.$observe("compile", function(str){
                        var compiled = $compile("<div>"+str+"</div>")(scope);
                        jQuery(element).replaceWith(compiled);
                    })
                }
            }
        })

并且我更改了我的标签集以使用此指令:

<div>
    <ul>
        <li ng-repeat="tab in tabset.tabs" ng-class="{active:tabset.current()==$index}">
            <a href ng-click="tabset.current($index)">{{tab}}</a>
        </li>
    </ul>
    <div>
        <div ng-repeat="pane in tabset.panes">
            <div ng-show="tabset.current()==$index">
                <div compile="{{pane.contents}}"></div>
            </div>
        </div>
    </div>
</div>

如果您希望像使用模板一样使用它,则需要使用 $compile 服务编译您的字符串。否则它将被视为普通字符串并按原样显示。

以下是如何在指令中使用它的示例:

var compiled = $compile(str)(scope);
element.empty();
element.append(compiled); 

如果您愿意,可以查看此 fiddle 以获取更复杂的示例: https://jsfiddle.net/x78uuwp2/

我在这里创建了简单的编译指令,它接受字符串编译它并将其作为具有当前范围的元素主体。