如何使用Angular.js动态生成DOM?

时间:2014-07-07 02:17:03

标签: javascript angularjs

我开始使用Angular.js,我想知道如何按照这种方式做一些事情(伪代码):

<li ng-repeat="item in items">
    <# if(item.dataType == "string") { #>
        <input type="text" />
    <# } else if(...) { #>
        <input type="password" />
    <# } #>
</li>

我知道上面的代码没有棱角分明,我知道为了简单处理,我可以使用条件ng-hideng-show或类似的东西。但是对于复杂的行为,如果我必须执行各种数据检查和业务逻辑,我怎么能用Angular.js动态生成DOM元素?

4 个答案:

答案 0 :(得分:4)

在角度世界中,使用angularjs指令完成DOM操作。以下是有关指令的角度文档:https://docs.angularjs.org/guide/directive,您最好仔细阅读。

以下是一些示例代码,可以实现伪代码的概念:

var myApp = angular.module('myApp', []);

myApp.controller('MyController', function ($scope){
  $scope.items = [
    42, "hello, world!", 3.14, "i'm alive!"
    ]
});

myApp.directive('myInputDirective', function () {
  return {
    restrict: 'E',
    replace: true,
    template: '<div></div>',
    link: function (scope, element, attrs) {
      if (typeof scope.current === "string") {
        element.append('<input type="text">');
      } else {
        element.append('<input type="password">');
      }
    }
  }
});

以及html的外观:

<div ng-controller="MyController">
  <ul ng-repeat="item in items" ng-init="current = item">
    <my-input-directive></my-input-directive>
  </ul>
</div>

这是一个带有工作示例的plnkr:http://plnkr.co/edit/iiS4G2Bsfwjsl6ThNrnS?p=preview

指令是角度操纵DOM的方式。首先要注意的是,angular有一组开箱即用的指令,我们使用上面的一些指令(ng-repeatng-initng-controller)。上面我们创建了一个自定义指令,用于分析item控制器的items数组中每个MyController的数据类型,并附加正确的html元素。

我想你已经理解了ng-repeat指令,所以我会跳过它。我将解释我在ng-init指令中所做的事情。 ng-init指令允许您评估当前范围中的表达式。这意味着我们可以编写一个在当前控制器范围内计算的表达式,在本例中为MyController范围。我正在使用此指令为名为current的当前项创建别名。我们可以在我们的指令中使用它来检查数组迭代中当前项的类型。

我们的指令myInputDirective正在返回一个具有几个不同属性的对象。我不会在这里解释它们(我会让你阅读文档),但我将解释link函数是什么以及我在做什么。 link函数通常是我们修改DOM的方式。链接函数接受当前scope(在本例中为MyController的范围),与指令关联的jqLit​​e包裹element,以及attrs具有标准化属性名称和值的键值对的哈希对象。在我们的示例中,重要的参数是scope,其中包含current变量,element,我们会将正确的输入附加到其上。在我们的link函数中,我们从items数组中检查typeof我们的current项,然后我们根据类型的内容将一个元素附加到我们的根元素上当前项目是。

对于这个特殊的问题,我上面所做的是矫枉过正。但基于你的问题,我认为除了角度提供的内置指令之外,你正在寻找更高级角度使用的起点。这些是有点高级的主题,所以我希望我所说的有些道理。查看plunker并稍微玩一下,然后阅读https://docs.angularjs.org/guide上的一些教程。希望这有帮助!

答案 1 :(得分:1)

您可以使用ng-show有条件地隐藏和显示元素,例如:

<input ng-show="item.dataType === 'string'" type="text"/>
<input ng-show="..." type="password"/>

答案 2 :(得分:1)

假设您的对象如下所示:

$scope.items = [
  {
    dataType: 'string',
    value: 'André Pena'
  }, 
  {
    dataType: 'password',
    value: '1234'
  }, 
  {
    dataType: 'check',
    value: true
  }
];

选项#1 - ng-switch plunker

<body ng-controller="MainCtrl">
  <ul>
    <li ng-repeat="item in items">

      <div ng-switch="item.dataType">
        <div ng-switch-when="string" ><input type="text" ng-model="item.value" /></div>
        <div ng-switch-when="password" ><input type="password" ng-model="item.value" /></div>
        <div ng-switch-when="check" ><input type="checkbox" ng-model="item.value" /></div>
      </div>

    </li>
  </ul>
</body>

选项#2 - ng-show plunker

<body ng-controller="MainCtrl">
  <ul>
    <li ng-repeat="item in items">

      <div ng-show="item.dataType == 'string'" ><input type="text" ng-model="item.value" /></div>
      <div ng-show="item.dataType == 'password'" ><input type="password" ng-model="item.value" /></div>
      <div ng-show="item.dataType == 'check'" ><input type="checkbox" ng-model="item.value" /></div>

    </li>
  </ul>
</body>

选项#3 - ng-hide plunker

<body ng-controller="MainCtrl">
  <ul>
    <li ng-repeat="item in items">

      <div ng-hide="!(item.dataType == 'string')" ><input type="text" ng-model="item.value" /></div>
      <div ng-hide="!(item.dataType == 'password')" ><input type="password" ng-model="item.value" /></div>
      <div ng-hide="!(item.dataType == 'check')" ><input type="checkbox" ng-model="item.value" /></div>

    </li>
  </ul>
</body>

答案 3 :(得分:0)

您应该使用ng-if指令。

<input ng-if="item.dataType === 'string'" type="text"/>
<input ng-if="..." type="password"/>

使用像@rob建议的ng-show的问题是,它只使用CSS来隐藏元素,如果你想让这两个输入具有相同的名称/ ID,这是不理想的。

如果条件不正确,

ng-if将从DOM中删除该元素。

对于一个简单的问题,没有必要去实现你自己的指令。