2

I'm trying to create a directive for an input element that will dynamically create an ng-pattern to check for a valid IP address in the input field. All of my attempts to do so have been completely unsuccessful. While I can dynamically modify other attributes, I can't create an ng-pattern that will affect the $valid status.

Here's the code that I've been working on which seems like it should work, but it doesn't do anything to the ng-pattern.

app.directive('ipAddress', function($parse) {
    return {
        link: function(scope, element, attrs) {
            var model = $parse(attrs.ngPattern);
            model.assign(scope, "/^(25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)\.(25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)\.(25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)\.(25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)$/");
            scope.$apply();
        };
});

Directive:

<input ng-model="ip" ip-address required type="text" id="inputIP" placeholder="xxx.xxx.xxx.xxx">

Yes, I know I can just specify the ng-pattern inline with the <input> tag but the point is that I want to be able to do this dynamically in the code, and I'd like to keep the <input> tag cleaner by not embedding a bunch of regex code there.

Can anyone please help me? Thanks!

2 Answers 2

9

You can define pattern in controller and then use in html:

$scope.pat=/^.*$/

And then in html

<input ng-pattern="pat" ... >
Sign up to request clarification or add additional context in comments.

4 Comments

That's really good (thanks!), but I was hoping for a way to set the ngPattern variable inside the directive so that the HTML element doesn't even need to have the "ng-pattern" attribute defined.
Look here: piotrbuda.eu/2013/02/… The trick here is that "ctrl.$parsers.push" is called when Angular try to move data to model. You can prevent this, by not returning value. As in this example you can also set validity for input. Based on this example I have build input that allows only numbers to be entered. You can do the same with IP.
actually the proposed solution by @user2543349 doesn't work. Take a look at jsfiddle.net/8JzDb/70 If I replace ng-pattern="mypattern" with ng-pattern="/^\d*$/" it works as expected accepting only numbers. Any ideas?
Do not quote patterns in code. Try exactly (without ' ): $scope.mypattern = /^\d*$/;
1

Although you would like an answer without the use of ng-pattern but I would suggest you not use a directive for that as using it would not add much benefits over the use of another file to include in your code.

Rather I would suggest you use constants to make your pattern globally available so other forms can use it too, like a directive but without the overhead.

You can declare a constant like:

app.constant('FORMATS', { "ipAdressRegex": /^your-regex-here)*$/i });

And use this constant in your controller or service :

var Controller = app.controller('Controller', ['$scope','FORMATS',
function ($scope,FORMATS) {

    $scope.ipAddressPattern = FORMATS.ipAdressRegex;
    .
    .
    .

In your view :

<input class="form-control" type="text"
       id="input_ip" name="email" data-ng-model="user.ip_add"
       data-ng-pattern="ipAddressRegex" />

Also further if you only want to use it in your views you can instead add the constant in your $rootScope instead of creating a local scope variable in the controller:

So instead of

$scope.ipAddressPattern = FORMATS.ipAdressRegex;

You can do in your config.js

_.assign($rootScope, _.pick(FORMATS, 'ipAddressRegex'));

View will remain as before

Comments

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.