是否可以在Angularjs中基于模型数据在指令中添加愤怒的html标签和属性?

时间:2014-02-02 07:20:58

标签: forms angularjs

我想构建一个指令,它将根据包含输入类型,绑定模型和html属性的设置的嵌套对象构建表单输入。我一直在冲我的脑袋,也许,我接近得出结论认为这是Angular无法做到的事情。我想建立一个可以采用一系列对象的指令,如:

[{
    "label":"When did it happen",
    "model": $scope.event.date,
    "element":"input",
    "type": "date",
    "options":{
       "class":"big",
       "required": true,
     },
  },{
    "label":"How did it happen?",
    "model": $scope.event.cause,
    "element":"textarea",
    "options":{
      "cols":45,
      "rows":55,
    },
  },{
    "label":"How many times did it happen?",
    "model": $scope.event.times,
    "element":"input",
    "options":{},
  }],

我在指令的许多不同方面都苦苦挣扎。我一直在讨论一些问题。

  • 模板和控制器指令功能都无法访问任何类型的范围,可以访问任何类型的数据 - 尤其是我的数组。这意味着我无法决定如何构建我的DOM(即标记类型和属性),直到稍后。
  • 所有编译都在链接功能之前完成。我能够在链接函数中操作DOM,但没有一个是偏心的。这意味着如果我添加一个必需属性angular的ngValidate不知道它。如果我尝试更改标签类型,我会重置丢失模型绑定等。

这似乎只是角度运行的方式。是否没有好的方法可以根据模型数据影响DOM标记类型和属性,而无需具体指定所有内容?

1 个答案:

答案 0 :(得分:3)

这样的事情怎么样:

$scope.event = {
    date: new Date(),
    cause:'It was the colonel in the kitchen with the revolver',
    time:5, //...
    $metadata: data
};

这里data只是你已经展示过的数组。 (除了模型属性,它只是一个表示事件属性的字符串,如下所示:

{
    "label":"When did it happen",
    "model":'date',
    "element":"input",
    "type": "date",
    "options":{
      "class":"big",
      "required": true,
     }
}

然后您的指令将只访问父作用域上给定的属性。 (event)并将元数据处理为可用模板。哪个可以编译。

这是一个指令和指令......

myApp.directive('contentForm',function($compile,$interpolate){
  var template = "<span class='lbl'>{{label}}</span><{{element ||'input'}} {{options}}"+
             " ng-model='{{root+'.'+model}}'></{{element}}>";                 

  function linkerFunction(scope,element,attrs){
    if(!scope[attrs.contentForm])return;
    var metadata = scope[attrs.contentForm].$metadata || false;
    if(!metadata)return;
    element.html(getHtml(metadata,attrs.contentForm));
    $compile(element.contents())(scope);
  }
  return {
    restrict: 'A',
    replace: true,
    link:linkerFunction
  };
  //interpolate the template with each set of metadata
  function getHtml(metadata,root){
    var interpolation = $interpolate(template);
    var html = '';
    if(angular.isArray(metadata)){
      for(var i = 0; i < metadata.length; i++){
        metadata[i].root = root;
        metadata[i].options = processOptions(metadata[i].options);
        html += interpolation(metadata[i]) + '</br>'
      }
    }else{
      html = interpolation(metadata);
      metadata.options = processOptions(metadata.options);
    }
    return html;
  }                
  // parse object into html attributes 
  function processOptions(options){
    var result = '';
    for(var key in options){
      if(options.hasOwnProperty(key)){
        result += ' '+key+"='"+options[key]+"'"
      }
    }
    return result.trim();
  } 
});

您可能想要更改模板。我似乎忘了输入一个类型。但那应该是相当直接的。我希望这有帮助!