AngularJs。灵活的指令

时间:2015-01-30 08:14:51

标签: angularjs angularjs-directive angular-directive

我正在开发一个简单的HTML编辑器。主要想法是为布局设置"默认主题"和组件可以覆盖主题的值。为了管理主题和组件的样式,我创建了简单的隔离指令,它接受对象和索引。主要问题是,当组件没有样式时,输入标记是空的并且是逻辑上的。有没有办法做不同的事情?

例如,如果组件没有样式,那么在内部指令中它将显示主题的值,但在更改时它将修改组件的样式,而不是主题的。

如果这种架构不是一种有角度的方式,那么你可以建议其他方法吗?

谢谢。 Plunker

这是代码片段:

<!DOCTYPE html>
<html>
<head>
    <title>Theme</title>
</head>

<body>
<div data-ng-app="myApp" data-ng-controller="defaultCtrl" style="margin: 100px 100px">
    <ol>
        <li data-ng-repeat="component in document" data-ng-style="m(theme, component.style)" data-ng-controller="componentController" data-ng-init="init(component)">
            {{ theme }}
            {{ component }}
            {{ component.content }}
            <button data-ng-click="editComponent()">Edit component</button>
        </li>
    </ol>
    <button data-ng-click="editTheme()">Edit theme</button>
    <div id="editor"></div>

    <script type="text/ng-template" id="component.html">
        <p>Component</p>
        <border-editor  ref-obj="component.style" ref-index="border"></border-editor>
    </script>
    <script type="text/ng-template" id="theme.html">
        <p>Theme</p>
        <border-editor ref-obj="theme" ref-index="border"></border-editor>
    </script>
</div>
<script type="text/javascript" src="//code.jquery.com/jquery-1.10.2.js"></script>
<script type="text/javascript" src="http://ajax.googleapis.com/ajax/libs/angularjs/1.3.5/angular.min.js"></script>
<script type="text/javascript">
    var app = angular.module("myApp", []);
    app.controller("defaultCtrl", ["$scope", "$templateCache", "$compile", function($scope, $templateCache, $compile) {
        $scope.theme = {
            border: "1px solid red"
        }

        $scope.document = [
            {
                content: "First block",
                style: {
                    border: "1px solid green"
                }
            },
            {
                content: "Second Block",
                style: {}
            },
            {
                content: "Third block",
                style: {}
            }
        ];

        $scope.m = function() {
            var merged = {},
                    args = arguments.length;
            for (var i = 0; i < args; i++) {
                for (var k in arguments[i]) {
                    if (arguments[i].hasOwnProperty(k) && arguments[i][k] !== undefined) {
                        merged[k] = arguments[i][k]
                    }
                }
            }
            return merged;
        }

        $scope.editTheme = function() {
            $scope.createEditor($scope, 'theme.html');
        }

        var editorScope;
        function createEditor(scope, tpl) {
            if(editorScope) {
                editorScope.$destroy();
            }
            var tpl = $templateCache.get(tpl);
            editorScope = scope.$new();
            var content = $compile(tpl)(editorScope);
            $("#editor").html(content);
        }
        $scope.createEditor = createEditor;
    }]);

    app.controller("componentController", ["$scope", function($scope) {
        $scope.init = function(component) { $scope.component = component; }
        $scope.editComponent = function() {
            $scope.createEditor($scope, 'component.html');
        }
    }]);

    app.directive("borderEditor", function() {
        return {
            restrict: "E",
            scope: {
                refObj: "=",
                refIndex: "@"
            },
            template: '<input data-ng-model="refObj[refIndex]" />',
            link: function(scope, el, a) {}
        }
    })
</script>
</body>
</html>

1 个答案:

答案 0 :(得分:0)

行。我找到了解决方案。我将 ng-model $ parsers $ formatters 属性结合使用。

我建议每个不了解ng模型如何运作的人 - read this article

这是updated plunker

app.directive("borderEditor", function() {
    return {
        restrict: "E",
        scope: {
            ngModel: "=",
            alternate: "="
        },
        require: "^ngModel",
        template: '{{ngModel || "undefined" }} <input data-ng-model="border"/>',
        link: function(scope, el, a, ngModel) {
            ngModel.$formatters.push(function(modelValue) {
                return !modelValue ? scope.alternate : modelValue;
            });

            ngModel.$parsers.push(function(viewValue) {
                return viewValue;
            });

            ngModel.$render = function() {
                scope.border = ngModel.$viewValue;
            }

            scope.$watch("border", function(newValue, oldValue) {
                if(newValue != oldValue) {
                    ngModel.$setViewValue(newValue);
                }
            });
        }
    }
})