【问题标题】:Manipulating DOM with AngularJS使用 AngularJS 操作 DOM
【发布时间】:2014-08-18 13:25:30
【问题描述】:

我正在尝试使用指令使用 angularjs 来操作我的表格。

我想向第一个 id=2 的 td 添加一个新类,如下所示:

gameApp.directive('mapActivity', function() {
    return {
        link: function(scope, element, attrs) {
            angular.element('.click#1').addClass('dotted');
        }
    };
});

我试图在这里“使用”驱动:

<map-activity>
<table ng-bind-html="safeHtml()">
</table>
</map-activity>

但是什么也没发生。第一个 TD 没有得到“dotted”类。我做错了什么?

这是我的控制器:

var gameApp = angular.module("gameApp", ['ngRoute','ngSanitize']);

gameApp.service('link', function() {
    this.user = false;
});
gameApp.filter('unsafe', function($sce) {
    return function(val) {
        return $sce.trustAsHtml(val);
    };
});

gameApp.directive('mapActivity', function() {
    return {
        priority: 1,
        restrict: 'A',
        link: function(scope, element, attrs) {
            angular.element('.click#1').addClass('dotted');
        }
    };
});
function makeTableFrom(str) {
    var k = 1;
    result = "";

    for(var i = 1; i <= 8; i++) {
        result += '<tr>';

        for(var j = 1; j <= 20; j++) {
            if(str[k] == '#') {
                result += '<td id=' + k + '">#</td>';
            }
            else if(str[k] == '&') {
                result += '<td class="click" val="water" id="' + k + '">&</td>';
            }
            else {
                result += '<td class="click" id="' + k + '"><a href="#"></a></td>';
            }

            k++;
        }
        result += '</tr>';
    }
    return result;
}


gameApp.config(function($routeProvider) {
    $routeProvider

    .when('/', {
            templateUrl : 'partials/firstpage.html',
            controller  : 'firstPageCtrl'
    })

    .when('/game', {
            templateUrl : 'partials/game.html',
            controller  : 'gameCtrl'
    });

});

gameApp.controller("firstPageCtrl", function($scope,$http,link,$location) {
    $scope.doLogin = function() {
        $http.post("lib/action.php", {username: $scope.username, password: $scope.password}).success(function(data) {
            if(data) {
                link.user = data;
                console.log(link.user);
                $location.path("/game");
            }
        }).error(function(data) {
            console.log(data);
        });
    };
});


gameApp.controller("gameCtrl", function($scope,$http,link,$location,$sce) {
    //$scope.trr = [1,2,3,4,5,6,7,8];
    //$scope.tdd = [1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20];
    $scope.getMonsters = "1";
    var map;

    $http.post("lib/action.php", {monsters: $scope.getMonsters}).success(function(data) {
        map = data;
        console.log(map);
        $scope.result = makeTableFrom(data);
        console.log($scope.result);
    });

    $scope.safeHtml = function() {
        return $sce.trustAsHtml($scope.result);
    };
    if(link.user) {
        /*$scope.message = "fisk";
        console.log(link.user);*/
    } else {
        /*$scope.message = "Ledsen fisk";
        console.log("Är inte satt");*/
    }

});

如您所见,我使用 javascript 函数为 HTML 分配一个变量,然后在我的视图中使用它,通过过滤器传递它。

当我按 Ctrl+u 查看页面源时,我看不到正在打印的 td 和 tr。这会影响它为什么不工作吗?

【问题讨论】:

  • 请用你的代码创建 jsfiddle。
  • 你确定你的指令码是在表格内容填完后触发的吗?也许您尝试将类添加到不存在的元素,然后填充表格。可能将 $timeout 与 0 添加到您的指令中,因此它首先获取内容。

标签: javascript angularjs dom


【解决方案1】:

尝试将不同的priority 分配给map-activity 指令,这样它会在ng-bind-html 之后处理

正如@Abhishek Jain 和@Dalorzo 指出的那样,您的指令必须是应用于同一个DOM 元素的属性

.directive('mapActivity', function() {
    return {
       priority: 0,   // check what priority ng-bind-html have and set it to be more than that.
       link: function(scope, element, attrs) {
          ...
       }
    }
})

优先级

当在单个 DOM 元素上定义了多个指令时, 有时需要指定指令的顺序 被应用。优先级用于在指令之前对指令进行排序 编译函数被调用。优先级被定义为一个数字。 首先编译具有更高数值优先级的指令。 预链接功能也按优先级顺序运行,但后链接 函数以相反的顺序运行。 指令的顺序与 相同的优先级未定义。默认优先级为 0。

【讨论】:

  • 如何设置指令的优先级?
  • 我附加了链接 - 它是您从指令返回的对象的属性。更新了我的答案。
  • 优先级仅适用于同一元素级别的指令。除非指令是表级别的属性,否则修改优先级不会有任何效果。顺便说一句,共享链接上提到了它
  • @user500468 你问错问题了。在这种情况下,设置优先级对您没有任何帮助。您的问题是该指令未在正确的位置使用。
  • @Dalorzo 你是对的,两个指令必须在同一个元素上
【解决方案2】:

您需要将指令添加到要附加到的标记中。在您的指令声明中,您已将 myDirective 声明为属性指令,但您将其用作 html 中的元素指令。

假设 .click#1 选择器对应于第一个 td 并且您希望该指令是一个属性,您需要这样做:-

<table ng-bind-html="safeHtml()" map-activity>

编辑:-

如果你想定位每行的第一个 td,你可以像这样定义你的指令:-

app.directive('mapActivity', [function(){
   return {
        restrict: 'A',
        link: function($scope, iElm, iAttrs, controller) {
            iElm.find('tr td:first-of-type').addClass('dotted');
        }
    };
}]);

【讨论】:

  • 我相信你的意思是&lt;table ng-bind-html="safeHtml()" map-activity&gt;
  • 哦,是的,抱歉打错了,感谢指正!! :-) 我已经编辑了答案。
【解决方案3】:

您所做的有点奇怪,因为您所做的是创建一个新元素,而不是使用属性修改当前表格元素,例如:

<table ng-bind-html="safeHtml()" map-Activity="">
</table>

然后:

gameApp.directive('mapActivity', function() {
    return {
        restrict: 'A',
        link: function(scope, element, attrs) {
           scope.$watch(attr.ngBindHtml, function(value) {
              angular.element('.click#1').addClass('dotted');                              
           });
        }
    };
});

另外,请确保您指定使用 restrict 属性的指令类型 A= Attribute, E= Element, C= Class,... 这些可以组合restrict: 'EAC',

您的示例版本中的link 函数将首先执行,另外一些浏览器将难以理解未知元素,因此最好在表级别移动您的指令。

【讨论】:

  • @Dolarzo:表级别?如何设置 my 指令的优先级,以便首先执行 ng-bind-html?
  • 上次我检查ng-bind 使用了priority:100,它只适用于同一元素级别的指令。除非您将指令移动为表级别的属性,否则修改优先级不会产生任何影响
  • 谢谢。但是,它不起作用。如何查看指令是否已加载甚至使用?它与我如何用我的 td 和行填充我的表有关吗?检查我的问题的更新版本,看看我如何用 td 和 tr 填充我的表格
  • 不,当您添加 scope.$watch 时,它似乎有效。那是什么?
猜你喜欢
  • 2016-01-03
  • 1970-01-01
  • 2017-01-23
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2015-03-14
  • 2017-01-21
  • 2014-07-24
相关资源
最近更新 更多