2

updated According to angularjs passing parameters through directive and ng-repeat non-compile version is working now. But the main question is still valid: to compile or not to compile

I'm trying to make dynamic formfields (my app needs lots of forms with lots of fields)

so I created a controller as:

KPNControllers.controller('panelAccountCtrl', ['$scope',
  function panelAccountCtrl($scope) {
    $scope.panelAccountTabItems = [
      {"title" : "Personal Data",
       "contentUrl":"partials/panel/account/personal.html",
       "fields" : [
         {"name" : "first_name", "label" : "First name", "required" : "true", "min" : 3, "max":20, "type":"text"},
         {"name" : "last_name", "label" : "Last Name", "required" : "true", "min" : 3, "max":20, "type":"text"}
        ]},
      {"title" : "Login", "contentUrl" : "partials/panel/account/login.html"},
      {"title" : "Password", "contentUrl" : "partials/panel/account/password.html"}
  ];
  }])

(only first item has fields [] but of course finally all of them will have it)

Then I created html as:

 <div class="box all-borders">
    <h3 class="special">{{tabItem.title}}</h3>
    <form name="mainForm" class="form-horizontal" novalidate>
        <form-field ng-repeat="field in tabItem.fields" form="mainForm" label="{{field.label}}" field-type="{{field.type}}" field-id="{{field.id}}"></form-field>
    </form>
  </div>

(not all attrs are set - but this is only for example)

So now it's a time for a directive.

I found two solutions:

With Compile: (not edited after update)

KPNDirectives.directive("formField", function () {
  return {
    restrict: 'E',
    replace: true,
    compile: function (element, attrs) {
      var type = attrs.type || 'text';
      var required = attrs.hasOwnProperty('required') ? "required" : "";
      var formName = 'Form';
      var fqFieldName = formName + '.' + attrs.fieldId;
      var inlineErrorRequired = attrs.hasOwnProperty('required') ? '<span class="help-block" ng-show="' +fqFieldName+ '.$error.required">Required</span>' : "";
      var htmlText = 
        '<div>' +
          '<div class="form-group" ng-class="{true: \'has-error\', false: \'has-success\'}['+ fqFieldName + '.$invalid]">'+
            '<label class="control-label col-sm-2" for=' +attrs.fieldId + '">' +attrs.label+ '</label>' +
            '<div class="col-sm-6">' +
              '<input type="' + type+ '" class="form-control" id="' +attrs.fieldId + '" name="' +attrs.fieldId + '" ng-model="'+ attrs.ngModel + '" '+ required + ' />' +
              inlineErrorRequired +
            '</div>' +    
          '</div>' +
        '</div>';
      element.replaceWith(htmlText);
    }
  };   
})

And without Compile: edited after update

KPNDirectives.directive("formField", function () {
  return {
    restrict: 'E',
    replace: true,
    scope: {
      fieldModel: '=',
      fieldLabel: '=',
      fieldType: '=',
      fieldName: '='
    },
    templateUrl: 'templates/formField.html'
  };   
})

with template:

<div class="form-group" ng-form="form" ng-class="{true: 'has-error', false: 'has-success'}[form.fieldName.$invalid]">
  <label class="control-label col-sm-2" for="fieldName">{{fieldLabel}}</label>
  <div class="col-sm-6">
    <input class="form-control" type="{{fieldType}}" placeholder="wprowadź aktualny email" name="fieldName" ng-model="fieldModel" ng-minlength=6 ng-maxlength=20 required/>
    <span class="help-block">
      <span ng-show="form.fieldName.$error.required">Wymagane</span>
      <span ng-show="form.fieldName.$error.minlength">Zbyt mało znaków (minimalna liczba to 6)</span>
      <span ng-show="form.fieldName.$error.maxlength">Zbyt dużo znaków (maxymalna liczba to 20)</span>
      &nbsp;
    </span>
  </div>
</div>

I want to know which method is the best or more angularish.

Here is a plunker with compile: http://plnkr.co/edit/BDIn5weqima5ve3G0Q2l?p=preview And here is a plunker without compile: http://plnkr.co/edit/8cP5YMKUGu6LfBCsRxAZ?p=preview

Community
  • 1
  • 1
Tomasz Brzezina
  • 1,452
  • 5
  • 21
  • 44
  • I prefer method 2. It is more readable and maintainable. They are not exactly equivalent as Method 2 introduces an isolated scope, while Method 1 uses prototypical scope inheritance. However, it would not be hard to make them equivalent. – Michael Kang Jun 03 '14 at 01:49

0 Answers0