如何使用Angular从vanilla(非Angular)HTML创建交互式小部件?

时间:2015-05-21 21:10:08

标签: javascript angularjs

我正在构建一个Angular应用程序:一个培训引擎,它将向用户提供在线课程。

每门课程基本上都是一系列"幻灯片" - 用户可以按顺序浏览的HTML部分。每张幻灯片可以包含零个或多个不同类型的交互式小部件:简单的测验,动手练习等。

我的目标是让课程由纯HTML / CSS组成,这样技术水平较低的人就可以构建课程,而无需亲自使用JS或Angular。只要课程只包含静态HTML,这就没问题。但是当我想将交互式小部件添加到课程中时,它会变得棘手。

例如,一个示例课程" slide"可能看起来像这样:

<p>Here's some static content introducing the quiz.</p>

<div class="quiz">

    <ol class="questions" data-passing-score="50">
        <li>

            <p>What was Abraham Lincoln's last name?</p>

            <ul class="answers">
                <li>Smith</li>
                <li>Johnson</li>
                <li class="correct">Lincoln</li>
                <li>Liebowitz</li>
            </ul>

        </li>
        <li>

            <p>What were George Washington's false teeth made of?</p>

            <ul class="answers">
                <li>Particle board</li>
                <li class="correct">Wood</li>
                <li>The bones of his enemies</li>
                <li>Advanced space-age polymers</li>
            </ul>

        </li>
    </ol>

</div>

<p>Here's some static content that appears after the quiz.</p>

...而且,当这个HTML文件被加载时(可能是通过$http.get()),我的应用程序会注意到它包含divquiz,并会设置所需的交互性:调整标记的结构(例如,添加单选按钮和提交按钮),可能隐藏和显示元素(因此用户一次只能看到一个问题),得分提交测验,等等。

这是jQuery-land中非常常见的模式。当然,我们 jQuery-land。

如果我正确地考虑这个问题,我需要解决两个问题才能使其发挥作用。

问题1:首先,我需要从原始HTML和JavaScript对象中获取测验数据。例如,我可能会将上面的HTML解析为这样的结构:

var quiz = {
    passing_score: 50,
    questions: [
        {
            ask: "What was Abraham Lincoln's last name?",
            answers: [
                { text: "Smith", correct: false },
                { text: "Johnson", correct: false },
                { text: "Lincoln", correct: true },
                { text: "Liebowitz", correct: false }
            ]
        },
        ...
    ]
};

我想我想将加载的HTML转换为DOM树(仅在内存中,不附加到文档中),然后探索它(使用jQuery或jqLit​​e)来查找数据I&#39;我很感兴趣。

这是一种明智的做法吗?还有其他我想探索的方法吗?

问题2:其次,我需要在加载的HTML中使用测验模板的内容替换 div.quiz,如下所示:

<form ng-controller="QuizController as quizCtrl" ng-submit="quizCtrl.submit()">

    <ol>
        <li ng-repeat="question in quizCtrl.questions">
            <p ng-bind-html="question.ask"></p>
            <ul>
                <li ng-repeat="answer in question.answers">
                    <label>
                        <input type="radio" ng-attr-name="{{ 'q' + $parent.$index }}" ng-model="question.selected_answer" ng-value="answer">
                        <span ng-bind-html="answer.text"></span>
                    </label>
                </li>
            </ul>
        </li>
    </ol>

    <button type="submit">Score Quiz</button>

</form>

...并将该div绑定到QuizController。

如何将特定DOM节点动态绑定到特定控制器?如何将测验对象(我在上一步中构建的)导入控制器的范围?

Angular-land中是否有针对此问题的标准解决方案?或者整个方法完全是香蕉?

希望这是有道理的。感谢您提供的任何指导!

1 个答案:

答案 0 :(得分:0)

正如@dandavis在上述评论中所建议的那样,答案是custom directives

对于我的测验示例,我可以创建一个定义自定义元素的自定义指令。 (或者,我可以在指令定义中使用restrict: 'C'来匹配<div class="quiz">,或restrict: 'A'以匹配<div quiz>。)

然后,我将把所有的setup-and-DOM-massaging逻辑放在指令的链接函数中。

最后,我只需要向课程作者指明他们应该如何标记测验。

我还没有在实际代码中完全实现这一点,但我确信这一切都是准确的。