2013-04-10 63 views
2

我正在处理一个项目来呈现HTML,并将一个特殊的XML作为输入。 我已经成功的基本情况。例如:一个具有特定类型的通用指令(UI组件继承)

<mybutton name="layla"></mybutton> 

使用指令像

.directive('mybutton', function() { 
    return { 
     restrict: 'E', 
     scope: { 
      name: '@' 
     }, 
     templateUrl: 'uicomponents/uiButton.html' 
    } 
}) 

真正的XML输入我会收到转换为

<div class="btn">Layla</div> 

是:

<ui type="back_button" x="10.0" y="630.0"/> 

我d喜欢避免更改XML语法,但它可以不用如有必要。所有屏幕组件都在<ui></ui>标签中。 type属性定义组件。

你会如何为这类标签编写指令?为<ui>元素创建一个巨大的指令并为属性设置一个长开关箱并不明智。

回答

5

您可以创建一个转换基于该类型属性的元素,然后重新编译元素的UI指令 - 这样的事情:

app.directive('ui',function($compile){ 
    return { 
    restrict:'E', 
    compile:function(tElement,tAttrs){ 
     if(tAttrs.type){ 
     tElement.attr(tAttrs.type,''); 
     tElement.removeAttr('type'); 
     return function(scope,el){ 
      $compile(el)(scope); 
     } 
     } 

    } 
    } 
}); 


app.directive('backButton',function(){ 
    return { 
    replace:true, 
    template:'<button ng-click="btnClick()">A back-button template</button>' 
    } 
}); 

编辑:在我原来的例子,我做编译模板的错误元素 - 如果在ngRepeat中使用该指令,这将不起作用。修复很简单,而是编译链接元素。我已经更新了代码和示例。

结帐this plnkr example

+0

很好的答案。我尝试了类似的东西,但不是使用编译函数,而是使用链接函数将类型添加为应该触发第二个指令的CSS类。任何想法为什么它从不运行第二个指令? [小提琴](http://jsfiddle.net/yxFrN/) – mfelix 2013-04-10 20:07:33

+0

很难说 - 你记得包括[$ compile](http://docs.angularjs.org/api/ng.$compile)服务和在添加CSS类后重新编译元素?你可以阅读更多关于编译过程[这里](http://docs.angularjs.org/guide/directive)。如果你可以在[plnkr](http://plnkr.co)上创建一个例子,我可以看看 – joakimbl 2013-04-10 21:35:44

+0

我在上面的评论中放了一个小提琴链接;也许你没有看到它?我会阅读$ compile,谢谢。 – mfelix 2013-04-10 22:39:55

2

我不知道的建立必将对属性值的指令的一种方式,但也许你可以看看这个以前的SO回答:Custom Input Types

的想法是创建根据不同的模板使用指令的编译函数将其转换为属性的值。您可以在开始时放入所有自定义输入模板(不是必需的)。

angular.module('myapp', ['myapp.directives']) 
    .run(['$http', '$templateCache', function($http, $templateCache) { 
     $templateCache.put('span.html', '<span>text</span>'); 
     $http.get('back_button.html', {cache:$templateCache}); 
    }]); 

并从缓存检索输入模板根据所述类型属性:

angular.module('myapp.directives', []) 
    .directive('ui', ['$templateCache', function($templateCache) { 
     return { 
      restrict: 'E', 
      compile: function(elem, attrs) 
      { 
       var type = attrs.type || 'span.html'; // default value ? 
       elem.replaceWith($templateCache.get(type)); 
      } 
     } 
    }]); 

此代码未测试。

编辑:这也可以工作,我认为,使用带有$链接功能编译,不预压模板,但仍缓存他们:

angular.module('myapp.directives', []) 
    .directive('ui', ['$http', '$templateCache', '$compile', function($http, $templateCache, $compile) { 
     return { 
      restrict: 'E', 
      link: function(scope, elem, attrs) 
      { 
       var type = attrs.type || 'span.html'; // default value ? 
       $http.get('views/' + type + '.html', {cache: $templateCache}).then(function(result) { 
        elem.replaceWith($compile(result.data)(scope)); 
       }); 
      } 
     } 
    }]); 

此代码为我工作。

+0

这是一个非常好的主意。我开始将'>'(初始输入)转换为''(每个类型一个指令),最终转换为'

content
'(浏览器的html)。来自遗留系统的模板是'templateUrl'似乎很好的文件,但我担心动态加载它们的性能,而不是仅仅在链接/编译函数中对它们进行硬编码。您的文章显示了如何以清晰的方式使用缓存。谢谢! – 2013-07-23 12:26:58