Tomasz Brzezina
Tomasz Brzezina

Reputation: 1534

AngularJS conditional attribute (directive)

The concept:

<form-field ng-repeat="field in fields" field-model='settings[field.name]'
   {{field.match == undefined && '' || 'field-match="settings[field.match]"'}}>
</form-field>

As you can see, i'm trying to get conditional attribute - if field.match is set - I'd like to get:

<form-field field-model='settings[field.name]' field.match="settings[field.match]"></form-field>

otherwise:

<form-field field-model='settings[field.name]'></form-field>

Unfortunately I got Error: The string contains invalid characters.

I tried (? : ) syntax with the same result, but I found AngularJS conditionals in HTML Attribute that it should be && || syntax... What I'm doing wrong?

edited Here's my directive:

KPNDirectives.directive("formField", function ($compile) {
  return {
    restrict: 'E',
    replace:true,
    scope: {
      fieldModel : '=', 
      fieldMatch : '=' 
    },
    template:"<div></div>",
    link: function (scope, element, attrs) {
      var type = attrs.fieldType || 'text';
      var requiredAttr = attrs.fieldRequired ? ' required' : ""
      var requiredHelp = ""
      var matchAttr = ""
      var matchHelp = ""
      console.log(attrs);
      if (attrs.hasOwnProperty('fieldMatch')) {
        matchAttr = " password-match=\"fieldMatch\"";
        matchHelp = '<span ng-show="form.'+attrs.fieldName+'.$error.unique">NOT UNIQUE</span>';
      } else {
        matchAttr = ""
        matchHelp = ""
      }
      if (attrs.fieldRequired == "true") {
        var requiredAttr="required"
        var requiredHelp = '<span ng-show="form.'+attrs.fieldName+'.$error.required">REQUIRED</span>';
      } else {
        requiredAttr = ""
        requiredHelp = ""
      }

      var htmlText =  
      '<div class="form-group" ng-form="form" ng-class="{true: \'has-error\', false: \'has-success\'}[form.'+attrs.fieldName+'.$invalid]">'+
      '<label class="control-label col-sm-2" for="'+attrs.fieldName+'">'+attrs.fieldLabel+'</label>'+
      '<div class="col-sm-6">'+ 
      '<input class="form-control" type="'+type+'" placeholder="enter valid name" name="'+attrs.fieldName+'" ng-model="fieldModel" ng-minlength=3 ng-maxlength=20 '+ matchAttr + requiredAttr+'/>'+
      '<span class="help-block">'+
      requiredHelp +
      matchHelp+
      '<span ng-show="form.'+attrs.fieldName+'.$error.minlength">TOO LESS CHARS</span>'+
      '<span ng-show="form.'+attrs.fieldName+'.$error.maxlength">TOO MUCH CHARS</span>'+
      '&nbsp;'+
      '</span>'+
      '</div>'+
      '</div>';
      // console.log(htmlText)
      element.append(htmlText);
      $compile(element.contents())(scope); 
    }
  }
});

Upvotes: 0

Views: 625

Answers (1)

rewritten
rewritten

Reputation: 16435

Templates and in general parseable text only goes inside attribute values (when some directive uses them) or in plain text nodes, surrounded by curlies.

You can obtain the needed result by putting your codintional inside of the field-match attibute, like

<form-field ng-repeat="field in fields" field-model='settings[field.name]'
   field-match="{{field.match && settings[field.match]}}">
</form-field>

Edit (after the OP added his code):

To interpolate values in attributes, use attrs.$observe (see ng.$compile.directive.Attributes ) in the link function, instead of linking the attribute in the isolated scope definition.

attrs.$observe("fieldMatch", function(fieldMatch) {
     $scope.fieldMatch = fieldMatch;
  }
)

Upvotes: 1

Related Questions