Customizing the template within a Directive

前端 未结 4 1461
醉话见心
醉话见心 2020-11-28 00:25

I have a form that is using markup from Bootstrap, like the following:

Legend tex
相关标签:
4条回答
  • 2020-11-28 01:03

    Here's what I ended up using.

    I'm very new to AngularJS, so would love to see better / alternative solutions.

    angular.module('formComponents', [])
        .directive('formInput', function() {
            return {
                restrict: 'E',
                scope: {},
                link: function(scope, element, attrs)
                {
                    var type = attrs.type || 'text';
                    var required = attrs.hasOwnProperty('required') ? "required='required'" : "";
                    var htmlText = '<div class="control-group">' +
                        '<label class="control-label" for="' + attrs.formId + '">' + attrs.label + '</label>' +
                            '<div class="controls">' +
                            '<input type="' + type + '" class="input-xlarge" id="' + attrs.formId + '" name="' + attrs.formId + '" ' + required + '>' +
                            '</div>' +
                        '</div>';
                    element.html(htmlText);
                }
            }
        })
    

    Example usage:

    <form-input label="Application Name" form-id="appName" required/></form-input>
    <form-input type="email" label="Email address" form-id="emailAddress" required/></form-input>
    <form-input type="password" label="Password" form-id="password" /></form-input>
    
    0 讨论(0)
  • 2020-11-28 01:04

    The above answers unfortunately don't quite work. In particular, the compile stage does not have access to scope, so you can't customize the field based on dynamic attributes. Using the linking stage seems to offer the most flexibility (in terms of asynchronously creating dom, etc.) The below approach addresses that:

    <!-- Usage: -->
    <form>
      <form-field ng-model="formModel[field.attr]" field="field" ng-repeat="field in fields">
    </form>
    
    // directive
    angular.module('app')
    .directive('formField', function($compile, $parse) {
      return { 
        restrict: 'E', 
        compile: function(element, attrs) {
          var fieldGetter = $parse(attrs.field);
    
          return function (scope, element, attrs) {
            var template, field, id;
            field = fieldGetter(scope);
            template = '..your dom structure here...'
            element.replaceWith($compile(template)(scope));
          }
        }
      }
    })
    

    I've created a gist with more complete code and a writeup of the approach.

    0 讨论(0)
  • 2020-11-28 01:09

    Tried to use the solution proposed by Misko, but in my situation, some attributes, which needed to be merged into my template html, were themselves directives.

    Unfortunately, not all of the directives referenced by the resulting template did work correctly. I did not have enough time to dive into angular code and find out the root cause, but found a workaround, which could potentially be helpful.

    The solution was to move the code, which creates the template html, from compile to a template function. Example based on code from above:

        angular.module('formComponents', [])
      .directive('formInput', function() {
        return {
            restrict: 'E',
            template: function(element, attrs) {
               var type = attrs.type || 'text';
                var required = attrs.hasOwnProperty('required') ? "required='required'" : "";
                var htmlText = '<div class="control-group">' +
                    '<label class="control-label" for="' + attrs.formId + '">' + attrs.label + '</label>' +
                        '<div class="controls">' +
                        '<input type="' + type + '" class="input-xlarge" id="' + attrs.formId + '" name="' + attrs.formId + '" ' + required + '>' +
                        '</div>' +
                    '</div>';
                 return htmlText;
            }
            compile: function(element, attrs)
            {
               //do whatever else is necessary
            }
        }
    })
    
    0 讨论(0)
  • 2020-11-28 01:17
    angular.module('formComponents', [])
      .directive('formInput', function() {
        return {
            restrict: 'E',
            compile: function(element, attrs) {
                var type = attrs.type || 'text';
                var required = attrs.hasOwnProperty('required') ? "required='required'" : "";
                var htmlText = '<div class="control-group">' +
                    '<label class="control-label" for="' + attrs.formId + '">' + attrs.label + '</label>' +
                        '<div class="controls">' +
                        '<input type="' + type + '" class="input-xlarge" id="' + attrs.formId + '" name="' + attrs.formId + '" ' + required + '>' +
                        '</div>' +
                    '</div>';
                element.replaceWith(htmlText);
            }
        };
    })
    
    0 讨论(0)
提交回复
热议问题