【问题标题】:adding dynamic content to a dynamically created content in angular js在angular js中将动态内容添加到动态创建的内容中
【发布时间】:2014-05-24 08:11:55
【问题描述】:

我想像树状结构一样展示购物车类别。当我单击父 ul>li 元素时,它会从服务器获取数据并动态添加新的数据集。我有 n 个级别,最初当我单击第一个级别时,我创建了一个动态子集并使用其类名将其放在父级之下。为新创建的子元素调用相同的函数,但这次它更新了单击元素的超级父元素。我创建了一个plunker 进行详细说明。

当我点击 men 类别时,其子元素会填充:

  • 男士腕表
  • 衬衫

当我点击“男士腕表”时,它应该在其下方添加下一个级别 - 但它会覆盖现有数据。

请帮助我。我是 Angular 新手。

HTML:

<!DOCTYPE html>
<html ng-app="plunker">

<head>
  <meta charset="utf-8" />
  <title>AngularJS Plunker</title>
  <script>
    document.write('<base href="' + document.location + '" />');
  </script>
  <link rel="stylesheet" href="style.css" />
  <script src="https://ajax.googleapis.com/ajax/libs/jquery/1.7.1/jquery.min.js"></script>
  <script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.2.0-rc.3/angular.js"></script>
  <script src="app.js"></script>
</head>

<body ng-controller="MainCtrl">
  <ul class="navigation">
    <li ng-repeat='category in fullTree.category[0]' ng-class='category.category_id' ng-click='dropmenu(category.category_id,category.level,category.has_child_category,$event);event.stopImmediatePropagation()'>
      <p>{{category.category_name}} <i class="ion-chevron-down"></i>
      </p>
    </li>
  </ul>
</body>

</html>

脚本:

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

app.controller('MainCtrl', function($scope, $sce, $compile) {
  $scope.name = 'World';
  $scope.html = "";

  $scope.htmlElement = function() {
    var html = "<input type='text' ng-model='html'></input>";
    return $sce.trustAsHtml(html);
  }

  $scope.fullTree = {
    "result": "true",
    "success": 1,
    "category": [
      [{
        "category_id": "prdcat01",
        "category_name": "Men",
        "level": "1",
        "higher_level_catg_no": "0",
        "total_level": "3",
        "has_child_category": "true",
        "total_product": "0"
      }, {
        "category_id": "prdcat02",
        "category_name": "Women",
        "level": "1",
        "higher_level_catg_no": "0",
        "total_level": "3",
        "has_child_category": "true",
        "total_product": "0"
      }, {
        "category_id": "prdcat03",
        "category_name": "Kids",
        "level": "1",
        "higher_level_catg_no": "0",
        "total_level": "1",
        "has_child_category": "false",
        "total_product": "0"
      }],
      [{
        "category_id": "cat01c01",
        "category_name": "Wrist Watch For Men",
        "level": "2",
        "higher_level_catg_no": "prdcat01",
        "has_child_category": "true",
        "total_product": "1"
      }, {
        "category_id": "cat02c01",
        "category_name": "Wrist Watch For Women",
        "level": "2",
        "higher_level_catg_no": "prdcat02",
        "has_child_category": "true",
        "total_product": "0"
      }, {
        "category_id": "cat01c02",
        "category_name": "Shirt for men",
        "level": "2",
        "higher_level_catg_no": "prdcat01",
        "has_child_category": "false",
        "total_product": "0"
      }, {
        "category_id": "cat02c02",
        "category_name": "Shirt For Women",
        "level": "2",
        "higher_level_catg_no": "prdcat02",
        "has_child_category": "false",
        "total_product": "0"
      }],
      [{
        "category_id": "cat0101c01",
        "category_name": "Fastrack Watch For Men",
        "level": "3",
        "higher_level_catg_no": "cat01c01",
        "has_child_category": "false",
        "total_product": "0"
      }, {
        "category_id": "cat0201c01",
        "category_name": "Fastrack Watch For Women",
        "level": "3",
        "higher_level_catg_no": "cat02c01",
        "has_child_category": "false",
        "total_product": "1"
      }, {
        "category_id": "cat0101c02",
        "category_name": "Casio watch for men",
        "level": "3",
        "higher_level_catg_no": "cat01c01",
        "has_child_category": "false",
        "total_product": "1"
      }]
    ],
    "msg": "Data retrieved successfuly"
  };

  $scope.dropmenu = function(category_id, level, has_child_category, $event) {
    $event.stopPropagation();

    $scope.dummy = [];

    for (var i = 0; i < $scope.fullTree.category[level].length; i++) {
      if ($scope.fullTree.category[level][i].higher_level_catg_no == category_id) {
        $scope.dummy.push($scope.fullTree.category[level][i]);
      }
    }

    alert(JSON.stringify($scope.dummy))

    var fieldHtml = "<ul class='navigation'><li ng-class={{category.category_id}} ng-repeat='category in dummy' ng-click='dropmenu(category.category_id,category.level,category.has_child_category,$event);event.stopPropagation()'><p>{{category.category_name}} <i class='ion-chevron-down'></i></p></li></ul>";

    var compiledElement = $compile(fieldHtml)($scope);

    $($event.target).closest("." + category_id).append(compiledElement);
  }
});

【问题讨论】:

    标签: jquery angularjs ionic-framework


    【解决方案1】:

    更新未知数量的级别
    您可以将我为这 3 个级别中的每一个编写的内容概括为一个模板,然后递归地使用它来处理任意数量的子类别级别。

    模板.html:

    <ul ng-show="$parent.category.expand" class="navigation" ng-init="level = $parent.level+1">
      <li ng-repeat="category in fullTree.category[level]" ng-if="category.higher_level_catg_no == $parent.category.category_id" ng-class="category.category_id">
        <p>{{category.category_name}}
          <i ng-click="category.expand = !category.expand" class="ion-chevron-down"></i>
        </p>
        <ng-include src="'template.html'" ng-if="fullTree.category[level+1]"></ng-include>
      </li>
    </ul>
    

    index.html 中有一些重复,如果对设置进行更多考虑,可能会消除这些重复。但这有效,并且不需要任何 DOM 操作。

    这是更新后的演示:http://plnkr.co/edit/DJ3hXHwYmf3n1LHArzWn?p=preview


    3 个级别的原始答案

    我建议阅读这个问题:"Thinking in AngularJS" if I have a jQuery background?

    您可以嵌套ng-repeat 来创建列表结构,而不是尝试在控制器中构建DOM,然后不得不使用jQuery 编译和插入它。然后在点击父类时使用ng-if渲染子类。

    <ul class="navigation">
      <li ng-repeat="category in fullTree.category[0]" ng-class="category.category_id">
        <p>{{category.category_name}}
          <i ng-click="category.expand = !category.expand" class="ion-chevron-down"></i>
        </p>
        <ul ng-if="category.expand" class="navigation">
          <li ng-repeat="subcategory in fullTree.category[1]" ng-if="subcategory.higher_level_catg_no == category.category_id">
            <p>{{subcategory.category_name}}
              <i ng-click="subcategory.expand = !subcategory.expand" class="ion-chevron-down"></i>
            </p>
            <ul ng-if="subcategory.expand" class="navigation">
              <li ng-repeat="subcategory2 in fullTree.category[2]" ng-if="subcategory2.higher_level_catg_no == subcategory.category_id">
                <p>{{subcategory2.category_name}}
                </p>
              </li>
            </ul>
          </li>
        </ul>
      </li>
    </ul>
    

    这是一个工作演示:http://plnkr.co/edit/lgYb8vFsFYpdXqKcMDad?p=preview

    【讨论】:

    • 但是在视图中你已经在视图中写了ul,但是我的要求我不知道它之前有多少个子级别
    • ok @user1386579,我将重复的 html 重构为模板,并与 ng-include 递归地使用它来处理任意数量的级别。这是一个有趣的挑战!
    【解决方案2】:

    与其使用控制器来操作 DOM,不如使用 Angular 指令——它们是基于这个目的而构建的。

    您可以将内容包装在指令中,如下例所示:

    app.directive('collection', function () {
        return {
            restrict: "E",
            replace: true,
            scope: {
                collection: '=',
                catTree: '='
            },
            template: '<ul><member full-tree="catTree" cat-tree="catTree[category.level]" ng-repeat="category in collection track by category.category_id" category="category"></member></ul>'
        };
    });
    
    app.directive('member', function ($compile) {
        return {
            restrict: "E",
            replace: true,
            scope: {
                member: '=category',
                catTree: '=',
                fullTree: '='
            },
            template: '<li class="ng-hide" ng-show="showItem">{{member.category_name}}</li>',
    
            link: function (scope, element, attrs) {
    
                scope.currentTree = {};
                scope.currentTree.category = [];
    
                scope.showItem = (scope.member.level == '1');
    
                element.bind('click', function (ev) {
                    jQuery(ev.target).siblings('ul').children('li').toggleClass('ng-hide');
                    // Prevent Bubble
                    return false;
                });
    
                if (scope.member.has_child_category) {
                    for (var cat in scope.catTree) {
                        if (scope.catTree[cat].higher_level_catg_no == scope.member.category_id) {
                            scope.currentTree.category.push(scope.catTree[cat]);
                        }
                    }               
                    element.append('<collection collection="currentTree.category" cat-tree="fullTree"></collection>');
                    $compile(element.contents())(scope);
                }           
    
            }
        };
    });
    

    虽然这些指令到目前为止还没有优化,但它们的目的是演示如何动态地向 DOM 添加内容以及如何操作各种项目。

    完整代码可以在这里测试:http://plnkr.co/edit/W5K77XlvhcaAoYl0TEpJ?p=preview

    您可以在此处找到有关指令的更多信息:http://www.sitepoint.com/practical-guide-angularjs-directives/

    【讨论】:

    • 非常感谢,您不仅解决了我的问题,还通过分享正确的教程让我克服了对指令的恐惧。它干净简单。
    猜你喜欢
    • 2012-08-05
    • 2019-07-16
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2017-06-05
    • 2014-09-13
    • 1970-01-01
    相关资源
    最近更新 更多