3

我正在编写一个 angularjs 应用程序(带有 node/express 后端)。我在我的范围内有一个通过服务异步填充(和重新填充)的对象。

对象的内容是一系列“问题”对象,为简单起见具有“文本”和“类型”属性。

我想要实现的是能够为每种类型提供一个角度指令,并让这些指令正确呈现。例如,如果服务器返回 [{type:'booleanquestion',text:'Is the sky blue?'}] 我将创建一个元素,然后 booleanquestion 指令将启动并适当地呈现它。

到目前为止,我已经定义了一个运行良好的“questionset”指令,观察问题收集并编译所需的东西,以便指令显示 correclt.y

html

<div questionset="questions"/>

应用程序.js

...
scope.questions = questions; // e.g. [{text: 'some text',type: 'boolean'}]

指令.js

angular.module('myApp').directive('questionset',function($compile){
    return {
        transclude: 'true',
        compile: function(element,attr,linker){
            return function($scope,$element,$attr){
                var elements = [],
                    parent = $element.parent();

                $scope.$watchCollection('questions',function(questions){
                    var block, i, childScope;

                    if(elements.length > 0)
                    {
                        for( i = 0; i < elements.length ; i++)
                        {
                            elements[i].el.remove();
                            elements[i].scope.$destroy();
                        }
                        elements = [];
                    }
                    if(!questions) return;

                    for(i = 0; i < questions.length; i++)
                    {
                        childScope = $scope.$new();
                        childScope['question'] = questions[i];
                        var html = '<div class="'+questions[i].type+'"/>';
                        var e = angular.element(html);
                        block = {};
                        block.el = e;
                        block.scope = childScope;
                        $compile(e)(childScope);
                        element.append(e);
                        elements.push(block);
                    }
                });
            }
        }
    }
});

// For example, one type might be "boolean"
angular.module('myApp').directive('boolean',function($compile){
    return {
        restrict: 'AC',
        template: '<div class="question">{{question.text}}</div>',
        replace: true,
        link: function(scope,elem,attrs,ctrl){
            …….
       // for some reason, $compile will not be defined here?
        }
    };
});

虽然这工作正常,但我有 2 个问题

1)。这是执行此操作的“正确”角度方式吗?这是我的第一个角度项目,似乎我已经跳入了最深处(或者无论如何感觉就是这样)

2)。我的下一个目标是 question.text 能够包含 HTML 并被“编译”。例如,文本可能是

"Is the <strong>sky</strong> blue?"

我不确定如何使这项工作 - 正如我在代码中的评论所暗示的那样,由于某种原因 $compile 没有被注入我的布尔指令中。也许这是因为我已经为它手动创建了子范围?我试图再次 $compile 元素的内容对吗?我觉得最后一点可能很简单,但我没有看到。

4

1 回答 1

2

1)我不知道。在我看来,整体方法看起来非常好;只需要打磨它,我们将在下面看到。

2)也许 $compile 在嵌套函数中不可用,因为它没有在父级别中使用。尝试在父函数中引用 $compile 看看这是否真的是原因:

angular.module('achiive-vision').directive('boolean',function($compile){
    var justTesting = $compile;
    return {
        restrict: 'AC',
        template: '<div class="question">{{question.text}}</div>',
        replace: true,
        link: function(scope,elem,attrs,ctrl){
            …….
       // check if $compile is defined here now
        }
    };
});

我会通过将questionset元素 html 更改为:

var html = '<div class="question ' + questions[i].type + '">'
           + questions[i].text + '</div>';

这样,您不需要再次编译,并且您已经拥有 HTML 支持。

另外,有点奇怪

var html = '<div class="'+questions[i].type+'"/>';

上面,然后你将用类似的标记替换它:

template: '<div class="question">{{question.text}}</div>',

...然后您想再次编译它...

在我看来,您不需要也不replace: true需要templateat 问题类型指令。实现行为和其他任何东西,但让父级questionset包含问题文本并编译它 - 一切都准备好了。

另外,一个细节:我不会在循环中使用var html和。var e我会将它们添加到上面的列表中:

var block, i, childScope, html, e;

(另外,我会避免将变量命名为“i”和“e”......)

这些是我对您的代码的评论。正如我所说,我认为这种方法非常好,而不是对刚开始使用 AngularJS 的人说“高级”。我自己只用了不到两个月。

于 2013-10-12T05:15:09.197 回答