自定义Angular指令,数据绑定不起作用

Custom Angular Directive, Databinding not working

本文关键字:数据绑定 不起作用 指令 Angular 自定义      更新时间:2023-09-26

我是Angularjs的新手,曾经尝试过写一个指令,从一个存储库动态创建一个完整的页面。

下面是一个数组中布局的模拟,它被转换为父/子层次结构,并存储在$scope.layoutAsHierachy中。

我的指令只是迭代和编译我的layoutAsHierarchy图的每个元素。

现在页面已经创建好了,但是没有发生数据绑定。我做错了什么?有一个更好的角度解决方案,我想要实现什么?

        $scope.layout = [{ "id": 1, "parent_id": 0, "name": "root", "html": "<div class='"rootContainer'" style='"float:left; width:100%;'"/>" }, //root
                        { "id": 2, "parent_id": 1, "name": "first row", "html": "<div class='"row1'" style='"height:15%;'"/>" }, //first row for header
                        { "id": 3, "parent_id": 1, "name": "second row", "html": "<div class='"row2'" style='"height:85%;'"/>" }, //second row
                        { "id": 4, "parent_id": 3, "name": "second row, left column", "html": "<div class='"column1'" style='"float:left; width:50%;'"/>" }, //second row, left column
                        { "id": 5, "parent_id": 3, "name": "second row, right column", "html": "<div class='"column2'" style='"float:left; width:50%;'"/>" }, //second row, right column
                        { "id": 6, "parent_id": 4, "name": "second row, left column, QR Code", "html": "<center>Bar / QR Code<br/><input ng-model='"buildModel.ProccesableMoveable.Model.QRCode'"autofocus class='"text-center'" type='"text'" style='"width:200px; height:30px; font-size:28px;'" ng-keyup='"loadData($event)'"/></center><br/>" }, //second row, left column QR Code
                        { "id": 7, "parent_id": 4, "name": "second row, left column, Item Table", "html": "<center><input ng-model='"buildModel.ProccesableMoveable.Model.RedNumber'" type='"text'" style='"width:110px;vertical-align:central'" readonly/><input ng-model='"buildModel.ProccesableMoveable.Model.OrderNumber'" type='"text'" style='"width:110px'" readonly/></center><center><input ng-model='"buildModel.ProccesableMoveable.Model.Species'" class='"text-center'" type='"text'" style='"vertical-align:central;width:110px'" readonly/><input ng-model='"buildModel.ProccesableMoveable.Model.Width'" class='"text-center'" type='"text'" style='"vertical-align:central;width:110px'" readonly/></center><center><input ng-model='"buildModel.ProccesableMoveable.Model.Color'" class='"text-center'" type='"text'" style='"vertical-align:central;width:110px'" readonly/><input ng-model='"buildModel.ProccesableMoveable.Model.ItemNumber'" class='"text-center'" type='"text'" style='"vertical-align:central;width:110px'" readonly/></center>" }, //second row, left column Item Table
                        { "id": 8, "parent_id": 4, "name": "second row, left column, Item Description", "html": "<br/><br/><center>Door Type<br/><input name='"txtDoorType'" class='"text-center'" type='"text'" style='"width:200px; height:30px; font-size:28px;'"/></center>" }, //second row, left column Item Description
                        { "id": 9, "parent_id": 5, "name": "second row, right column, Moveable Table", "html": "<div style='"width:100%'"><center><table border='"1'"><thead style='"border-bottom:double;font-weight:bold'"><tr><td style='"text-align:center;width:100px'">Doors</td><td style='"text-align:center;width:100px'">Rack#</td></tr></thead><tr ng-repeat='"(DoorId, Description) in processableMoveable.Model.Moveable'"><td width='"100'" style='"text-align:center'">{{DoorId}}</td><td width='"175'" style='"text-align:center'">{{Description}}</td></tr></table></center></div>" }, //second row, right column Moveable Table
                        { "id": 10, "parent_id": 2, "name": "first row, header", "html": "<center><h2>Some place</h2><h3>Locator - Sort</h3></center>" }]; //first row, header];
    $scope.layoutAsHierarchy = unflatten($scope.layout);

指令代码:

function wwAppsecLayout($compile) {
    return {
        restrict: "E",
        scope: { collection: '=' },
        link: function (scope, element, attrs) {
            if (angular.isArray(scope.collection)) {
                angular.forEach(scope.collection, function (value, key) {
                    var c = $compile(value.html)(scope);
                    element.replaceWith(c);
                    buildHierachy($compile, scope, c, value.children);
               });
            }
        }
    };
};
app.directive('wwAppsecLayout', ['$compile', wwAppsecLayout]);
function buildHierachy($compile, scope, element, collection) {
    if (angular.isArray(collection)) {
        angular.forEach(collection, function (value, key) {
            var c = $compile(value.html)(scope);
            element.append(c);
            buildHierachy($compile, scope, c, value.children);
        });
    }
};

我最终做了下面的操作,这是有效的。

<ww-appsec-layout layout="layoutAsHierarchy"></ww-appsec-layout>
function wwAppsecLayout($compile ) {
    return {
        restrict: "E",
        scope: true,
        link: function (scope, element, attrs) {
            if (!angular.isUndefined(attrs.layout)) {
                var layout = scope.$eval(attrs.layout);
                if (angular.isArray(layout)) {
                    angular.forEach(layout, function (value, key) {
                        var c = $compile(value.html)(scope);
                        element.replaceWith(c);
                        buildHierachy($compile, scope, c, value.children);
                    });
                }
            }
        }
    };
};
app.directive('wwAppsecLayout', ['$compile', wwAppsecLayout]);
function buildHierachy($compile, scope, element, collection) {
    if (angular.isArray(collection)) {
        angular.forEach(collection, function (value, key) {
            var c = $compile(value.html)(scope);
            element.append(c);
            buildHierachy($compile, scope, c, value.children);
        });
    }
};

但是下面的代码几乎可以工作。除了我的ng-keyup="(loadData($event))"不能工作。我猜,因为我的隔离作用域不知道loaddatfunction。有什么好主意吗?

<ww-appsec-layout layout="layoutAsHierarchy" ng-model="buildModel"></ww-appsec-layout>
function wwAppsecLayout($compile)
{
    return {
        restrict: "E",
        scope: { layout: '=', model: '=ngModel' },
        require: 'ngModel',
        link: linker,
        replace: true
    };
    function linker(scope, element, attrs, ctrl) {
        if (angular.isArray(scope.layout)) {
            angular.forEach(scope.layout, function (value, key) {
                var c = $compile(value.html)(scope);
                element.replaceWith(c);
                buildHierachy($compile, scope, c, value.children);
            });
            scope.$watch('model', function (newValue, oldValue) {
                if (!angular.isUndefined(newValue) && newValue != null)
                    scope.buildModel = newValue;
            });
        }
    }
};
app.directive('wwAppsecLayout', ['$compile', wwAppsecLayout]);
function buildHierachy($compile, scope, element, collection) {
    if (angular.isArray(collection)) {
        angular.forEach(collection, function (value, key) {
            var c = $compile(value.html)(scope);
            element.append(c);
            buildHierachy($compile, scope, c, value.children);
        });
    }
};