GithubHelp home page GithubHelp logo

Comments (17)

jonsamwell avatar jonsamwell commented on May 23, 2024

Hi,

Could you provide a plunkr so I can test it out?

from angular-auto-validate.

jonsamwell avatar jonsamwell commented on May 23, 2024

Just mock the ValidatePhoneService to return a valid phone number and I'll be able to see what is going on :-)

from angular-auto-validate.

sarg3nt avatar sarg3nt commented on May 23, 2024

Sure thing. Here you go
http://plnkr.co/edit/Ri5LOss3zod0u8DADFrS
I have some comments in there to guide and a console.log to show how it's being called multiple times.

from angular-auto-validate.

jonsamwell avatar jonsamwell commented on May 23, 2024

Thanks, I'll take a look :-)

from angular-auto-validate.

sarg3nt avatar sarg3nt commented on May 23, 2024

I've been playing with this some more and have discovered that when the directive is applied to the text box setting the scope value in the controller has no affect. i.e. if from the controller I set $scope.technicalContactPhone = 'foo'
foo is not set in the textbox on page load. If I remove the directive from the text box it is. Something in the directive is breaking this.
Also if I try to manually set the scope value from the directive it just blanks out the textbox.
I've also tried setting elm.text(result.PhoneNumber); as the Angular docs show. That sets the text in the dob but the textbox / scope value do not change.
I have no idea what to do next. I must be missing something fundamental here.

from angular-auto-validate.

jonsamwell avatar jonsamwell commented on May 23, 2024

Hi - I'm hopefully going to get time to look at this tonight :-) Sorry for
the hold up!

On Thu, Oct 9, 2014 at 5:15 PM, dsargent3220 [email protected]
wrote:

I've been playing with this some more and have discovered that when the
directive is applied to the text box setting the scope value in the
controller has no affect. i.e. if from the controller I set
$scope.technicalContactPhone = 'foo'
foo is not set in the textbox on page load. If I remove the directive from
the text box it is. Something in the directive is breaking this.
Also if I try to manually set the scope value from the directive it just
blanks out the textbox.
I've also tried setting elm.text(result.PhoneNumber); as the Angular docs
show. That sets the text in the dob but the textbox / scope value do not
change.
I have no idea what to do next. I must be missing something fundamental
here.


Reply to this email directly or view it on GitHub
#18 (comment)
.

from angular-auto-validate.

sarg3nt avatar sarg3nt commented on May 23, 2024

I've got part of it figured out.
Because I'm calling a service with a promise like so
ValidatePhoneService.get({ phone: viewValue }).$promise.then(function (result)
. . . . .
});
That promise is not getting returned immediately, instead as JS is designed to do, in that case undefined is returned.
If I put a return in front of the above it returns an object with a promise.
Still not sure how to proceed here.
Thanks for looking at it!

from angular-auto-validate.

jonsamwell avatar jonsamwell commented on May 23, 2024

Sorry for the delay been so busy - I'm definitely getting round to looking at this at the weekend!

from angular-auto-validate.

jonsamwell avatar jonsamwell commented on May 23, 2024

Just had another thought. There is a piece of undocumented functionality in the module which allows you to set validation from an external source -pretty much what you are doing i.e. an api call (it works well it just I haven't written test for it yet so it not officially released!)

I added a method to the form controller to apply external validation to model items.

The method on the form controller is:

frmCtrl.setExternalValidation = function (modelProperty, errorMsgKey, errorMessageOverride) {
    var success = false;
    if (frmCtrl[modelProperty]) {
        frmCtrl[modelProperty].setExternalValidation(errorMsgKey, errorMessageOverride);
        success = true;
    }
    return success;
};

It takes in the name of the control i.e.

<input type=“text” name”firstname” ng-model=“model.firstname” required min-length=“3” /></code>)

which should probably correspond to the ng-model property.
The errorMsgKey i.e. the key of the validation error that is able to be looked up from the error message provider - although this can be blank.
If it is blank or unknown you can provide the actual error message you want to display in the errorMessageOverride parameter.

So the call would look something like this:

frmCtrl.setExternalValidation('firstname', undefined, ’some error message to the user’);

or

frmCtrl.setExternalValidation('firstname', ‘required');

So in your controller the code to apply server validation after the from has been submitted would look something like this:

app.controller('demoCtrl', [
    '$scope',
    function ($scope) {
        $scope.user = {};

        $scope.submit = function (frmCtrl) {
            $http.post('https://api.app.com/users', $scope.user).then(function (response) {
                if (response.data.validationErrors) {
                    angular.forEach(response.data.validationErrors, function (error) {
                        frmCtrl.setExternalValidation(error.key, error.messageKey, error.message);
                    })
                }
            });
        };
    }
]);

Your view would look something like this

<form role="form" name=“singupFrm" novalidate="novalidate" ng-submit="submit();">
                <div class="form-group">
                    <label class="control-label">Name</label>
                    <input type="text" name="firstname" class="form-control" placeholder="Enter Name" ng-model="user.name" required="required" />
                </div>
                <div class="form-group">
                    <label class="control-label">Email address</label>
                    <input type="email" name=“email" class="form-control" placeholder="Enter email" ng-model="user.email" required="required" />
                </div>
                <div class="form-group">
                    <label class="control-label">Password</label>
                    <input type=“password" name=“password" class="form-control" ng-model="user.password" placeholder="Password" required="required" ng-minlength="6" />
                </div>

                <button type="submit" class="btn btn-default">Submit</button>
</form>

I hope this all make sense, it might be something worth exploring?

Jon

from angular-auto-validate.

jonsamwell avatar jonsamwell commented on May 23, 2024

Did you have any luck with this approach?

from angular-auto-validate.

sarg3nt avatar sarg3nt commented on May 23, 2024

Sorry. I was on vacation for over a week and haven't had time to get back to that. I looked at it briefly and must confess it didn't make allot of sense, but I'll try and take another look tomorrow. Can't today. Thanks!

Sent from my iPhone

On Nov 11, 2014, at 2:48 AM, Jon Samwell [email protected] wrote:

Did you have any luck with this approach?


Reply to this email directly or view it on GitHub.

from angular-auto-validate.

sarg3nt avatar sarg3nt commented on May 23, 2024

Hello, my apologies for not getting to this until now. Got the rest of the project done and am now looping back to this.
I'm not sure where I'm supposed to get access to frmCtrl. I'm sure I'm being dense here but would love any help you can give.

from angular-auto-validate.

sarg3nt avatar sarg3nt commented on May 23, 2024

To clarify a little further. I have a directive for the phone number I've created. Here's the beginning of the definition.

var directive = {
    scope: {
        label:"@",
        id: "@",
        required:"=?", // Are fields required.
    },
    link: link,
    restrict: 'E',
    require: 'ngModel',
    templateUrl: 'app/rma/directives/selPhoneNumber.html'
};
return directive;

function link(scope, element, attrs, ctrl) {
    console.log(ctrl);
    ctrl.setExternalValidation('technicalContactPhone', 'validatephone');

The ctrl.setExternalValidation call returns an error saying it is not a function . . .BUT the console log for ctrl shows that the function exists on the object (I am baffled).

The call to this directive looks like this.

<sel-phone-number label="Country Code and Phone Number" name="technicalContactPhone" id="technicalContactPhone" ng-model="model.technicalContactPhone" required="true"></sel-phone-number>

The problem I hope this solves is that I'm setting the validity in the directive like this
ctrl.$setValidity('validatephone', false);

And have a custom error message set up

defaultErrorMessageResolver.getErrorMessages().then(function (errorMessages) {
    errorMessages.validatephone = 'Please enter a valid phone number, including Country Calling Code and Area Code';
    errorMessages.serialNumberRequired = 'Serial number is required. If your product does not have a serial number, enter "none"';
});

Note; the serialNumberRequired message works fine.

But when the validity is set to false, nothing happens (outwardly). The dom is changed with the correct classes you would expect, but Auto Validate is not doing anything with them. I feel like I'm missing something really stupid and can't see it.

from angular-auto-validate.

jonsamwell avatar jonsamwell commented on May 23, 2024

Hmmm, I'll try a create a example to see if something odd is going on. What is the html of the directive's template? It might not be in the structure the element modifier is expecting so it is missing out putting the error message in.

In the meantime it would be worth putting a debugger; statement here
https://github.com/jonsamwell/angular-auto-validate/blob/master/src/services/defaultErrorMessageResolver.js#L167

To see if the error message resolve is actually finding that error message or even getting to that point in the code?

from angular-auto-validate.

sarg3nt avatar sarg3nt commented on May 23, 2024

Here is the full directive:

(function() {
    'use strict';

    angular
        .module('rmaApp')
        .directive('selPhoneNumber', selPhoneNumber);

    selPhoneNumber.$inject = ['validatePhoneService'];

    function selPhoneNumber(validatePhoneService) {
        // Usage:
        //     <sel-phone-number id="SomeId" ng-model="{countryCallingCode: '', phoneNumber:''}" required="true"></sel-phone-number>
        // Creates:
        // 
        var directive = {
            scope: {
                label:"@",
                id: "@",
                required:"=?", // Are fields required.
            },
            link: link,
            restrict: 'E',
            require: 'ngModel',
            templateUrl: 'app/rma/directives/selPhoneNumber.html'
        };
        return directive;

        function link(scope, element, attrs, ctrl) {
            console.log(ctrl);
            console.log(ctrl.setExternalValidation);
            // Below throws an error.
            ctrl.setExternalValidation('technicalContactPhone', 'validatephone', 'foo');

            // If user does not pass in required, then assume it is not required (if we don't do this, it will be undefined)
            if (scope.required === undefined) {
                scope.required = false;
            }

            // Functions
            scope.checkPhone = checkPhone;

            // Checks the phone values when there is a data load into the field.
            scope.$watch(function () { return scope.phoneNumber; }, function (newValue, oldValue) {
                if (oldValue === '' && newValue !== '') {
                    checkPhone();
                }
            });

            ctrl.$render = function () {
                scope.countryCallingCode = ctrl.$viewValue.countryCallingCode;
                scope.phoneNumber = ctrl.$viewValue.phoneNumber;
            };

            // Run check on load.
            checkPhone();

            function checkPhone() {
                if (angular.isDefined(scope.phoneNumber) && scope.phoneNumber.length > 0) {
                    var phone = parsePhone(scope.countryCallingCode, scope.phoneNumber);
                    validatePhoneService.get({ phoneccc: phone.countryCallingCode, phone: phone.phoneNumber }).$promise.then(function (data) {
                        if (data.Valid) {
                            scope.countryCallingCode = data.CountryCallingCode;
                            scope.phoneNumber = data.Phone;
                            ctrl.$setViewValue({ countryCallingCode: scope.countryCallingCode, phoneNumber: scope.phoneNumber });
                            ctrl.$setValidity('validatephone', true);
                        } else {
                            console.log('set validity to false');
                            ctrl.$setValidity('validatephone', false);
                        }
                    });
                }
            }

            // Parse a phone number country calling code and phone number body into an object.
            // If there is no phone number country calling code, attempt to find it in the body.
            function parsePhone(countryCallingCode, phoneNumber) {
                // Split the phone number up into an array for later use.
                // The delimiter
                var d = '',
                    phone = [],
                    result = { countryCallingCode: '', phoneNumber: phoneNumber };
                // What delimiter is being used.
                if (phoneNumber.indexOf(' ') > -1) { d = ' '; }
                if (phoneNumber.indexOf('.') > -1) { d = '.'; }
                if (phoneNumber.indexOf('-') > -1) { d = '-'; }
                // Split the phone number into an array by the delimiter
                phone = phoneNumber.split(d);

                // Try to set country calling code to the form value
                result.countryCallingCode = countryCallingCode;
                if (angular.isDefined(result.countryCallingCode) && result.countryCallingCode !== '') {
                    // Remove the + from the ccc if there.
                    result.countryCallingCode = result.countryCallingCode.replace('+', '');
                } else {
                    // Set ccc to the first element in the array, that should be the country calling code
                    result.countryCallingCode = phone[0];

                    if (angular.isDefined(result.countryCallingCode) && result.countryCallingCode !== '') {
                        // Get rid of the + if it is there.
                        result.countryCallingCode = result.countryCallingCode.replace('+', '');
                        // Remove the ccc from the phone array then rejoin it using a period and set it to the element
                        phone.splice(0, 1);
                        result.phoneNumber = phone.join('.');
                    }
                }

                return result;
            }
        }
    }
})();

Here is the html template

<label class="control-label" for="{{id}}">{{label}}</label>
<div class="input-group">
    <input type="text" class="form-control" style="width:60px" ng-model="countryCallingCode" ng-required="required" tooltip="Country Calling Code.  Example: +1 for US" tooltip-trigger="focus" tooltip-placement="top">
    <span class="input-group-addon" style="width:0; border-left: 0; border-right: 0;"><b>.</b></span>
    <input type="text" class="form-control" id="{{id}}" ng-model="phoneNumber" ng-required="required" ng-blur="checkPhone()" tooltip="Phone Number.  Example: 123.555.1212" tooltip-trigger="focus" tooltip-placement="top">
</div>

And here is an example reference of me using it

<form name="frm" role="form" novalidate ng-submit="submit();">
<div class="panel panel-default" ng-show="userLoaded">
        <div class="panel-heading">
            <span class="h3">Technical Contact Information</span><br />
            (The person who experienced the failure and who may be contacted later by an SEL technician for further information.
        </div>
        <div class="panel-body">
            <div class="row">
    <div class="col-sm-4">
                    <div class="form-group">
                        <sel-phone-number label="Country Code and Phone Number" name="technicalContactPhone" id="technicalContactPhone" ng-model="model.technicalContactPhone" required="true"></sel-phone-number>
                    </div>
                </div>
            </div>
        </div>
    </div>
</form>

Here is the model for the technicalContactPhone property

var model = {
    technicalContactPhone: {countryCallingCode: '', phoneNumber:''}
};

The service will return something like the following.

{"Valid":true,"CountryCallingCode":"+1","Phone":"509.432.3220"}

Let me know if there is anything else I can help with

from angular-auto-validate.

sarg3nt avatar sarg3nt commented on May 23, 2024

I did place a breakpoint on the line you indicated. It gets hit when the field is empty for the required attribute, but not for the phone validation.

from angular-auto-validate.

sarg3nt avatar sarg3nt commented on May 23, 2024

Still banging my head against the wall on this one. Not sure what to try next.

from angular-auto-validate.

Related Issues (20)

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.