0

This is what I am planning to do:

Initial Markup:

<div class="col-md-3 col-sm-3 col-xs-6">
<span class="control-label"><b>Doc. Number:</b></span>
<input name="documentNumber" class="form-control" type="text" ng-model="document.number" smrh-required />
</div>

Attempted Markup with my directive:

<div class="col-md-3 col-sm-3 col-xs-6" ng-class="{'has-error': t01Form.documentNumber.$invalid && t01Form.documentNumber.$dirty}">
<span class="control-label"><b>Doc. Number:</b></span>
<input name="documentNumber" class="form-control " type="text" ng-model="document.number" smrh-required="" required="" />
<p ng-show="t01Form.documentNumber.$invalid && t01Form.documentNumber.$dirty" class="help-block">Document Number is required.</p>
</div>

Below is the custom directive I have created to attempt this:

app.directive('smrhRequired', function ($compile) {
return {
    restrict: 'A',
    link: function (scope, element, attributes, controller) {
        element.attr('ng-required', "");
        //This way it will only show the red outline if the error happens.
        var errorClass = " {'has-error': " + scope.formName + "." + element[0].name + ".$valid && " + scope.formName + "." + element[0].name + ".$dirty }";
        var currentNgClass = element.parent().attr('ng-class');
        if (currentNgClass != null) {
            element.parent().attr('ng-class', currentNgClass + errorClass);
        } else {
            element.parent().attr('ng-class', errorClass);
        }
        //Adding the error message below the input
        var template = '<p ng-show="' + scope.formName + '.' + element[0].name + '.$invalid && ' + scope.formName + '.' + element[0].name + '.$dirty" class="help-block">' + ' is required.' + '</p>';
        element.parent().append(template);
        $compile(element.contents())(scope);
    },
};

});

Now the above functions adds the new markup correctly, but none of the new markup works. Even though I added the required attribute dynamically.. the control still show $valid.

The new

I added shows up regardless of the ng-show logic.

I am guessing it is because I am adding elements to DOM after angular has already compiled, but I thought that's what $compile is for?

1 Answer 1

1

There are a few things:

  • ng-class/ng-required are Angular directives. It has to be an attribute to the element you want to use it with.
  • You need to use Angular templates with the $compile service as described here, before appending your markup to the DOM
Sign up to request clarification or add additional context in comments.

2 Comments

Are you saying that ng-class and ng-required has to be present before I dynamically add them? I was thinking that I would be able to add these attributes on the fly. Due to the fact my ng-show and ng-class attributes (which I add dynamically) need scope values and the element name, I can't figure out a clean way to use the template. That's why I am trying to do everything dynamically.
Ng-class and ng-required are not DOM attributes, they are Angular directives. This is why they have to be there on page load.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.