将属性从custom指令复制到输入

时间:2015-02-08 09:43:34

标签: angularjs

我有一个自定义的driective,用div包装输入并添加标签。

<my-input label="My Label" name="myname" ng-model="mymodel" ng-pattern="/^[a-z]+$/">

我想选择使用所有可能的角度指令进行输入,如ng-pattern,ng-minlength等。现在它看起来像这样:

app.directive('myInput',[function () {
    return {
        restrict: "E",
        replace: true,
        scope: {
            ngModel: '=',
            name: '@',

            ngMinlength: '=',
            ngMaxlength: '=',
            ngPattern: '@',                
            label: '@'                
        },
        compile: function(element, attrs){

            if(!_.isUndefined(attrs['ngMinlength'])) {
                element.find('input').attr('ng-minlength', 'ngMinlength');
            }
            if(!_.isUndefined(attrs['ngMaxlength'])) {
                element.find('input').attr('ng-maxlength', 'ngMaxlength');
            }                
            if(!_.isUndefined(attrs['ngPattern'])) {
                element.find('input').attr('ng-pattern', attrs['ngPattern']);
            }               


        },
        template: '<div class="form-group">'
        + '<label>{{ label | translate }}</label>'
        + '<div>'
        + '<input type="text" class="form-control input-sm" name="{{ name }}" ng-model="ngModel">'           
        + '</div></div>'
    };
}]);

问题是我想要使用ng-pattern与输入中的ng-pattern完全相同,所以我希望有可能在ng-pattern中使用regexp,并且还可以使用模式使用范围变量($scope.mypattern = /^[a-z]+$/; ... ng-pattern="mypattern" )。如何管理?

我想要两个人都在工作:

1

<my-input label="My Label" name="myname" ng-model="mymodel" ng-pattern="/^[a-z]+$/">

2

$scope.myPattern = /^[a-z]+$/
...
<my-input label="My Label" name="myname" ng-model="mymodel" ng-pattern="myPattern">

2 个答案:

答案 0 :(得分:1)

我有三个答案。

  1. 通常,不建议同时支持模型属性和String。这种情况由指令范围内的=声明处理,如果要传递String,则应使用简单引号。例如,ngBind的工作方式如下:ng-bind="someModel"ng-bind="'some string'"

  2. 如果确实想要,您可以尝试解析表达式。如果它是可解析的,则意味着它是范围模型。否则,它可能是一个字符串。请参阅以下代码段中的工作示例:

  3. &#13;
    &#13;
    angular.module('test', [])
    
    .controller('test', function($scope) {
      $scope.model = "string from scope model";
    })
    
    .directive('turlututu', function($parse) {
     return {
       restrict: 'E',
       scope: {},
       template: '<div class="tu">{{content}}</div>',
       link: function(scope, elem, attrs) {
         try {
           scope.content = $parse(attrs.text)(scope.$parent);
         } catch(err) {
         } finally {
           if (!scope.content) {
             scope.content = attrs.text;
           }
         }
       }
     };
    });
    &#13;
    body { font-family: monospace; }
    
    .tu { padding: 10px; margin: 10px; background: #f5f5f5; border-bottom: 2px solid #e5e5e5; }
    &#13;
    <script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.2.23/angular.min.js"></script>
    <div ng-app="test" ng-controller="test">
      
      <turlututu text="hardcoded string"></turlututu>
      <turlututu text="model"></turlututu>
      
    </div>
    &#13;
    &#13;
    &#13;

    1. 在ngPattern的情况下,因为代码中的好奇心总是对你有所帮助,你可以在Angular的源代码中看到他们测试属性的第一个字符:如果是/它被认为是正则表达式,否则范围模型(见下面的例子)
    2. &#13;
      &#13;
      angular.module('test', [])
      
      .controller('test', function($scope) {
        $scope.model = /[a-z]*/;
      })
      
      .directive('turlututu', function($parse) {
       return {
         restrict: 'E',
         scope: {},
         template: '<div class="tu">{{content}}</div>',
         link: function(scope, elem, attrs) {
           if (attrs.regexp.charAt(0) === '/') {
             scope.reg = new RegExp( attrs.regexp.substring(1, attrs.regexp.length-1) );
           } else {     
             scope.reg = new RegExp( $parse(attrs.regexp)(scope.$parent) );
           }
           
           scope.content = scope.reg.toString()
         }
       };
      });
      &#13;
      body { font-family: monospace; }
      
      .tu { padding: 10px; margin: 10px; background: #f5f5f5; border-bottom: 2px solid #e5e5e5; }
      &#13;
      <script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.2.23/angular.min.js"></script>
      <div ng-app="test" ng-controller="test">
        
        <turlututu regexp="/[0-9]*/"></turlututu>
        <turlututu regexp="model"></turlututu>
        
      </div>
      &#13;
      &#13;
      &#13;

答案 1 :(得分:1)

我遇到了同样的问题 - 需要将我的自定义修饰输入视为常规输入元素。我也从孤立的范围开始,但最终认为它不够灵活。必须添加我可能需要的每个属性才能快速实现。 所以我提出了以下解决方案。不确定它是否是正确/规范的Angular方式,但对我有效。

我们的想法是构建一个&#34;视图模型&#34;来自指令属性的对象并将其提供给$ interpolate。视图模型中未使用的任何属性都将插入到实际的&lt;输入/&gt;元素通过视图模型的特殊 attributesToCopy 属性。它不会创建任何新的范围,只需将其放在当前范围内即可。 该指令使用lodash kebabCase:https://lodash.com/docs/4.17.4#kebabCase

如果您不想包含lodash,可以使用Angular本身的snake_case函数,但不会通过其API公开,因此您需要将其复制粘贴到代码中的某个位置。

    <my-textbox type="number" ng-model="foo" ng-min="0" ng-max="5" required></my-textbox>

用法:

margin-top