如何使用AngularJS编写可重用的HTML组件

时间:2014-02-06 20:35:56

标签: angularjs angularjs-directive

Angular的新手,到目前为止,我很喜欢它,但学习曲线似乎相当陡峭。我想要做的是包含一些简单的业务逻辑,并构建一些可重用的DOM组件来模拟我系统的公共区域。具体来说,我正在编写一个具有不同问题类型的简单调查应用程我的目标是达到这样的程度,即当我处于ng-repeat块时,我可以做这样的事情:

<div ng-repeat="question in questions">
     <show-question></show-question>
</div>

理想情况下,我想将所有逻辑包装到一个语句中以打开问题类型,然后从templateUrl中提取不同的HTML集。因此,如果一个question.type =“text”,它将拉出“templates / textQuestion.html”的templateUrl,并能够在生成DOM元素时将范围注入该模板文件。

最大的问题是,我是否正确地进行了这一切?指令是否可行,我是否应该尝试在一个指令/标签中执行此操作?我愿意接受这个教育!

小问题是,如果我正朝着正确的方向前进,那么正确的实施是什么?

我已经尝试在IF和SWITCH等指令中加入一些逻辑,但这似乎没有效果。

欢迎任何和所有(建设性的)帮助。

全部谢谢!

2 个答案:

答案 0 :(得分:2)

它被称为指令。这里有一个完整的指南:http://docs.angularjs.org/guide/directive

它允许您将自定义属性,元素,CSS类和注释转换为组件。

我不会为每个问题类型提取单独的模板,我会为每个问题类型使用不同的指令。然后,您可以使用父指令在它们之间切换。

以下是加载不同指令的指令可能如下所示:

app.directive('question', function($compile){
  "use strict";
  return{
    restrict: 'E',
    replace: true,
    link: function(scope, element, attrs){
      var render = function(){
        var template = "";
        switch(attrs.type){
          case "truefalse":
            template = '<truefalse></truefalse>';
          break;
          case "multiplechoice":
            template = '<multiplechoice></multiplechoice>';
          break;
          case "essay":
            template = '<essay></essay>';
          break;
        }
        element.html(template);
        $compile(element.contents())(scope);
      }

      attrs.$observe('type', function(value) {
          render();
      });
      render();
    }
  }; 
});

现在你可以这样使用它:

<question ng-repeat="question in questions" type="question.type" ></question>

假设您对每种类型的问题都有一个指令,那么您将获得不同的指令。这类似于使用ng-if或不同的模板或其他任何模板,但我更喜欢它,因为我也可以使用可重复使用的一次性组件。

答案 1 :(得分:0)

因此,如果您的范围变量问题包含每个问题的所有信息,例如

$scope.questions = [
  { type: 'input',
    prompt: 'name'
  }
];

然后你可能会有一些看起来像

的html
<div question="question" ng-repeat="question in questions"></div>

并且有一个类似

的指令
app.directive('question', function() {
  return {
    scope: {
      question: '=' // Creates 2 way data binding with the object you passed in as attribute by the same name
    },
    link: function($scope, $element, $attrs) {
        $scope.question; // This will be equal the object you passed in
        // { type: 'input', prompt: 'name' }
        // You can modify the dom or whatever here
    }
  };
});

如果你想拥有不同的准备模板,那么你可以将$ templateCache注入你的指令

app.directive('question', function($templateCache) {

然后在你的链接功能中调用它们

link: function($scope, $element, $attrs) {
  var template = $templateCache.get('path/to/template.html');
  // and append it to the element
  $element.append(template);
}

你必须稍微玩一下,但这只是乐趣的一半。祝你好运!