AngularJS代理指令

时间:2014-10-29 09:18:22

标签: angularjs interface proxy directive facade

我正在尝试创建一个代理指令,如下所示:

<x-field x-purpose="choice" x-values="data.countries" ng-model="model.country"/>

field指令将此转发给另一个指令,导致以下替换:

<x-choiceField x-values="data.countries" ng-model="model.country"/>

[注意:] ng-model可以替换为对一些新的隔离范围的引用。

&#34;字段目的&#34;指令根据可供选择的值,客户端设备大小等决定使用哪种实现(例如下拉列表/列表框/自动完成?) - 最终产生如下结果:

<select ng-model="model.country" ng-options="data.countries">

这个设计很大程度上是出于好奇而不是出于任何实际原因,我对如何实现它感兴趣,而不是从性能/简单的角度来看它是否真的是一个好主意......

阅读[https://stackoverflow.com/a/18895441/1156377]后,我有类似的内容:

function proxyDirective($injector, $parse, element) {
    return function (scope, element, attrs) {
        var target = element.camelCase(attrs.name + '-field');
        var model = attrs.ngModel;
        var value = $parse(model);
        var directive = $injector.get(target);
        /* Bind ngModel to new isolated scope "value" property */
        scope.$watch(model, function () {
            ???
        });
        /* Generate new directive element */
        var pElement = angular.element.html('');
        var pAttrs = {
            value: ???
        };
        /* Forward to new directive */
        return directive.compile(element, attrs, null)(scope, element, attrs);
    };
}

function alphaFieldDirective() {
    return {
        replace: 'true',
        template: '<input type="text" ng-value="forwarded value?">'
    };
}

function betaFieldDirective() {
    return {
        replace: 'true',
        template: '<textarea attributes? >{{ value }}</textarea>'
    };
} 

但我不确定如何实现转发或绑定。这是我第一次进入Angular指令,它似乎并不是一种特别受欢迎的使用方法!

这样做的目的是将表单字段的用途与其外观/实现分开,并提供一个简单的指令来实例化字段。

1 个答案:

答案 0 :(得分:2)

我是通过代理指令的服务实现的:

小提琴:http://jsfiddle.net/HB7LU/7779/

HTML:

<body ng-app="myApp">
    <h1>Directive proxying</h1>
    <proxy target="bold" text="Bold text"></proxy>
    <h1>Attribute forwarding</h1>
    <proxy target="italic" style="color: red;" text="Red, italic text"></proxy>
</body>

使用Javascript:

angular.module('myApp', [])
    .factory('directiveProxyService', directiveProxyService)
    .directive('proxy', dirProxy)
    .directive('bold', boldDirective)
    .directive('italic', italicDirective)
    ;

function directiveProxyService($compile) {
    return function (target, scope, element, attrs, ignoreAttrs) {
        var forward = angular.element('<' + target + '/>');
        /* Move attributes over */
        _(attrs).chain()
            .omit(ignoreAttrs || [])
            .omit('class', 'id')
            .omit(function (val, key) { return key.charAt(0) === '$'; })
            .each(function (val, key) {
                element.removeAttr(attrs.$attr[key]);
                forward.attr(attrs.$attr[key], val);
            });
        $compile(forward)(scope);
        element.append(forward);
        return forward;
    };
}

function dirProxy(directiveProxyService) {
    return {
        restrict: 'E',
        terminal: true,
        priority: 1000000,
        replace: true,
        template: '<span></span>',
        link: function (scope, element, attrs) {
            directiveProxyService(attrs.target, scope, element, attrs, ['target']);
        }
    };
}

function boldDirective() {
    return {
        restrict: 'E',
        replace: true,
        template: '<i>{{ text }}</i>',
        scope: { text: '@' }
    };
}

function italicDirective() {
    return {
        restrict: 'E',
        replace: true,
        template: '<i>{{ text }}</i>',
        scope: { text: '@' }
    };
}